1ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville/* 2ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * Copyright (C) 2013 The Android Open Source Project 3ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * 4ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 5ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * you may not use this file except in compliance with the License. 6ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * You may obtain a copy of the License at 7ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * 8ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * http://www.apache.org/licenses/LICENSE-2.0 9ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * 10ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * Unless required by applicable law or agreed to in writing, software 11ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * distributed under the License is distributed on an "AS IS" BASIS, 12ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * See the License for the specific language governing permissions and 14ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * limitations under the License. 15ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville */ 16ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savillepackage com.android.internal.telephony.dataconnection; 17ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 18ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport android.app.AlarmManager; 19ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport android.app.PendingIntent; 20ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport android.content.BroadcastReceiver; 21ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport android.content.Context; 22ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport android.content.Intent; 23ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport android.content.IntentFilter; 24ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport android.os.AsyncResult; 25ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport android.os.SystemClock; 26ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport android.telephony.Rlog; 27ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport android.text.TextUtils; 28ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 29ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport com.android.internal.telephony.PhoneBase; 30ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savilleimport com.android.internal.telephony.RILConstants; 31ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 32ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville/** 33ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * The Data Connection Retry Alarm Controller. 34ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville */ 35ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Savillepublic class DcRetryAlarmController { 36ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville private String mLogTag = "DcRac"; 37ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville private static final boolean DBG = true; 38ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 39ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville private PhoneBase mPhone; 40ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville private DataConnection mDc; 41ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville private AlarmManager mAlarmManager; 42ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 43ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville // The Intent action for retrying and its two extra's 44ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville private String mActionRetry; 45ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville private static final String INTENT_RETRY_ALARM_WHAT = "what"; 46ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville private static final String INTENT_RETRY_ALARM_TAG = "tag"; 47ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 48ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 49ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville @Override 50ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville public void onReceive(Context context, Intent intent) { 51ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville String action = intent.getAction(); 52ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (TextUtils.isEmpty(action)) { 53ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville // Our mActionXxxx's could be null when disposed this could match an empty action. 54ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville log("onReceive: ignore empty action='" + action + "'"); 55ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville return; 56ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 57ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (TextUtils.equals(action, mActionRetry)) { 58ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (!intent.hasExtra(INTENT_RETRY_ALARM_WHAT)) { 59ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville throw new RuntimeException(mActionRetry + " has no INTENT_RETRY_ALRAM_WHAT"); 60ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 61ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (!intent.hasExtra(INTENT_RETRY_ALARM_TAG)) { 62ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville throw new RuntimeException(mActionRetry + " has no INTENT_RETRY_ALRAM_TAG"); 63ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 64ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville int what = intent.getIntExtra(INTENT_RETRY_ALARM_WHAT, Integer.MAX_VALUE); 65ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville int tag = intent.getIntExtra(INTENT_RETRY_ALARM_TAG, Integer.MAX_VALUE); 66ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (DBG) { 67ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville log("onReceive: action=" + action 68ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville + " sendMessage(what:" + mDc.getWhatToString(what) 69ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville + ", tag:" + tag + ")"); 70ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 71ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mDc.sendMessage(mDc.obtainMessage(what, tag, 0)); 72ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } else { 73ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (DBG) log("onReceive: unknown action=" + action); 74ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 75ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 76ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville }; 77ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 78ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville DcRetryAlarmController(PhoneBase phone, DataConnection dc) { 79ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mLogTag = dc.getName(); 80ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mPhone = phone; 81ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mDc = dc; 82ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mAlarmManager = (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE); 83ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mActionRetry = mDc.getClass().getCanonicalName() + "." + mDc.getName() + ".action_retry"; 84ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 85ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville IntentFilter filter = new IntentFilter(); 86ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville filter.addAction(mActionRetry); 87ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville log("DcRetryAlarmController: register for intent action=" + mActionRetry); 88ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 89ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mDc.getHandler()); 90ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 91ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 92ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville /** 93ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * Dispose of resources when shutting down 94ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville */ 95ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville void dispose() { 96ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (DBG) log("dispose"); 97ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mPhone.getContext().unregisterReceiver(mIntentReceiver); 98ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mPhone = null; 99ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mDc = null; 100ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mAlarmManager = null; 101ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mActionRetry = null; 102ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 103ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 104ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville /** 105ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * Using dc.mRetryManager and the result of the SETUP_DATA_CALL determine 106ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * the retry delay. 107ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * 108ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * @param dc is the DataConnection 109ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * @param ar is the result from SETUP_DATA_CALL 110ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville * @return < 0 if no retry is needed otherwise the delay to the next SETUP_DATA_CALL 111ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville */ 112ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville int getSuggestedRetryTime(DataConnection dc, AsyncResult ar) { 113ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville int retryDelay; 114ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 115ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville DataCallResponse response = (DataCallResponse) ar.result; 116ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville retryDelay = response.suggestedRetryTime; 117ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (retryDelay == RILConstants.MAX_INT) { 118ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (DBG) log("getSuggestedRetryTime: suggestedRetryTime is MAX_INT, retry NOT needed"); 119ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville retryDelay = -1; 120ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } else if (retryDelay >= 0) { 121ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (DBG) log("getSuggestedRetryTime: suggestedRetryTime is >= 0 use it"); 122ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } else if (dc.mRetryManager.isRetryNeeded()) { 123ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville retryDelay = dc.mRetryManager.getRetryTimer(); 124ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (retryDelay < 0) { 125ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville retryDelay = 0; 126ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 127ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (DBG) log("getSuggestedRetryTime: retry is needed"); 128ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } else { 129ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (DBG) log("getSuggestedRetryTime: retry is NOT needed"); 130ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville retryDelay = -1; 131ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 132ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 133ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (DBG) { 134ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville log("getSuggestedRetryTime: " + retryDelay + " response=" + response + " dc=" + dc); 135ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 136ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville return retryDelay; 137ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 138ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 139ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville public void startRetryAlarm(int what, int tag, int delay) { 140ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville Intent intent = new Intent(mActionRetry); 141ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville intent.putExtra(INTENT_RETRY_ALARM_WHAT, what); 142ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville intent.putExtra(INTENT_RETRY_ALARM_TAG, tag); 143ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 144ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville if (DBG) { 145ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville log("startRetryAlarm: next attempt in " + (delay / 1000) + "s" + 146ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville " what=" + what + " tag=" + tag); 147ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 148ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 149ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville PendingIntent retryIntent = PendingIntent.getBroadcast (mPhone.getContext(), 0, 150ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville intent, PendingIntent.FLAG_UPDATE_CURRENT); 151ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 152ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville SystemClock.elapsedRealtime() + delay, retryIntent); 153ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 154ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 155ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville @Override 156ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville public String toString() { 157ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville StringBuilder sb = new StringBuilder(); 158ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville sb.append(mLogTag).append(" [dcRac] "); 159ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville sb.append(" mPhone=").append(mPhone); 160ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville sb.append(" mDc=").append(mDc); 161ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville sb.append(" mAlaramManager=").append(mAlarmManager); 162ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville sb.append(" mActionRetry=").append(mActionRetry); 163ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville return sb.toString(); 164ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 165ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville 166ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville private void log(String s) { 167ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville Rlog.d(mLogTag, "[dcRac] " + s); 168ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville } 169ff4e317d24f0d23bdc0f306d53ddc51f2f1ecf6aWink Saville} 170