/* * 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); } }