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