DcRetryAlarmController.java revision 2cc8c148fa4cb6cba5deac6b011268b4174a0b02
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 */
16package com.android.internal.telephony.dataconnection;
17
18import android.app.AlarmManager;
19import android.app.PendingIntent;
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.os.AsyncResult;
25import android.os.SystemClock;
26import android.telephony.Rlog;
27import android.text.TextUtils;
28
29import com.android.internal.telephony.PhoneBase;
30import com.android.internal.telephony.RILConstants;
31
32/**
33 * The Data Connection Retry Alarm Controller.
34 */
35public 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