blob: 78a641dfeb46722bd18daa44c9dd5d0229276cec [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.telephony.dataconnection;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncResult;
import android.os.SystemClock;
import android.telephony.Rlog;
import android.text.TextUtils;
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.RILConstants;
/**
* The Data Connection Retry Alarm Controller.
*/
public class DcRetryAlarmController {
private String mLogTag = "DcRac";
private static final boolean DBG = true;
private PhoneBase mPhone;
private DataConnection mDc;
private AlarmManager mAlarmManager;
// The Intent action for retrying and its two extra's
private String mActionRetry;
private static final String INTENT_RETRY_ALARM_WHAT = "what";
private static final String INTENT_RETRY_ALARM_TAG = "tag";
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (TextUtils.isEmpty(action)) {
// Our mActionXxxx's could be null when disposed this could match an empty action.
log("onReceive: ignore empty action='" + action + "'");
return;
}
if (TextUtils.equals(action, mActionRetry)) {
if (!intent.hasExtra(INTENT_RETRY_ALARM_WHAT)) {
throw new RuntimeException(mActionRetry + " has no INTENT_RETRY_ALRAM_WHAT");
}
if (!intent.hasExtra(INTENT_RETRY_ALARM_TAG)) {
throw new RuntimeException(mActionRetry + " has no INTENT_RETRY_ALRAM_TAG");
}
int what = intent.getIntExtra(INTENT_RETRY_ALARM_WHAT, Integer.MAX_VALUE);
int tag = intent.getIntExtra(INTENT_RETRY_ALARM_TAG, Integer.MAX_VALUE);
if (DBG) {
log("onReceive: action=" + action
+ " sendMessage(what:" + mDc.getWhatToString(what)
+ ", tag:" + tag + ")");
}
mDc.sendMessage(mDc.obtainMessage(what, tag, 0));
} else {
if (DBG) log("onReceive: unknown action=" + action);
}
}
};
DcRetryAlarmController(PhoneBase phone, DataConnection dc) {
mLogTag = dc.getName();
mPhone = phone;
mDc = dc;
mAlarmManager = (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
mActionRetry = mDc.getClass().getCanonicalName() + "." + mDc.getName() + ".action_retry";
IntentFilter filter = new IntentFilter();
filter.addAction(mActionRetry);
log("DcRetryAlarmController: register for intent action=" + mActionRetry);
mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mDc.getHandler());
}
/**
* Dispose of resources when shutting down
*/
void dispose() {
if (DBG) log("dispose");
mPhone.getContext().unregisterReceiver(mIntentReceiver);
mPhone = null;
mDc = null;
mAlarmManager = null;
mActionRetry = null;
}
/**
* Using dc.mRetryManager and the result of the SETUP_DATA_CALL determine
* the retry delay.
*
* @param dc is the DataConnection
* @param ar is the result from SETUP_DATA_CALL
* @return < 0 if no retry is needed otherwise the delay to the next SETUP_DATA_CALL
*/
int getSuggestedRetryTime(DataConnection dc, AsyncResult ar) {
int retryDelay;
DataCallResponse response = (DataCallResponse) ar.result;
retryDelay = response.suggestedRetryTime;
if (retryDelay == RILConstants.MAX_INT) {
if (DBG) log("getSuggestedRetryTime: suggestedRetryTime is MAX_INT, retry NOT needed");
retryDelay = -1;
} else if (retryDelay >= 0) {
if (DBG) log("getSuggestedRetryTime: suggestedRetryTime is >= 0 use it");
} else if (dc.mRetryManager.isRetryNeeded()) {
retryDelay = dc.mRetryManager.getRetryTimer();
if (retryDelay < 0) {
retryDelay = 0;
}
if (DBG) log("getSuggestedRetryTime: retry is needed");
} else {
if (DBG) log("getSuggestedRetryTime: retry is NOT needed");
retryDelay = -1;
}
if (DBG) {
log("getSuggestedRetryTime: " + retryDelay + " response=" + response + " dc=" + dc);
}
return retryDelay;
}
public void startRetryAlarm(int what, int tag, int delay) {
Intent intent = new Intent(mActionRetry);
intent.putExtra(INTENT_RETRY_ALARM_WHAT, what);
intent.putExtra(INTENT_RETRY_ALARM_TAG, tag);
if (DBG) {
log("startRetryAlarm: next attempt in " + (delay / 1000) + "s" +
" what=" + what + " tag=" + tag);
}
PendingIntent retryIntent = PendingIntent.getBroadcast (mPhone.getContext(), 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + delay, retryIntent);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(mLogTag).append(" [dcRac] ");
sb.append(" mPhone=").append(mPhone);
sb.append(" mDc=").append(mDc);
sb.append(" mAlaramManager=").append(mAlarmManager);
sb.append(" mActionRetry=").append(mActionRetry);
return sb.toString();
}
private void log(String s) {
Rlog.d(mLogTag, "[dcRac] " + s);
}
}