DataConnectionTracker.java revision ad4d9e5bebb5a9ba01c1459d941019887f4a7d6d
1/*
2 * Copyright (C) 2006 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
17package com.android.internal.telephony;
18
19import android.app.PendingIntent;
20import android.os.AsyncResult;
21import android.os.Handler;
22import android.os.INetStatService;
23import android.os.Message;
24import android.os.RemoteException;
25import android.provider.Settings;
26import android.provider.Settings.SettingNotFoundException;
27import android.util.Log;
28
29/**
30 * {@hide}
31 *
32 */
33public abstract class DataConnectionTracker extends Handler {
34    private static final boolean DBG = true;
35
36    /**
37     * IDLE: ready to start data connection setup, default state
38     * INITING: state of issued setupDefaultPDP() but not finish yet
39     * CONNECTING: state of issued startPppd() but not finish yet
40     * SCANNING: data connection fails with one apn but other apns are available
41     *           ready to start data connection on other apns (before INITING)
42     * CONNECTED: IP connection is setup
43     * DISCONNECTING: Connection.disconnect() has been called, but PDP
44     *                context is not yet deactivated
45     * FAILED: data connection fail for all apns settings
46     *
47     * getDataConnectionState() maps State to DataState
48     *      FAILED or IDLE : DISCONNECTED
49     *      INITING or CONNECTING or SCANNING: CONNECTING
50     *      CONNECTED : CONNECTED or DISCONNECTING
51     */
52    public enum State {
53        IDLE,
54        INITING,
55        CONNECTING,
56        SCANNING,
57        CONNECTED,
58        DISCONNECTING,
59        FAILED
60    }
61
62    public enum Activity {
63        NONE,
64        DATAIN,
65        DATAOUT,
66        DATAINANDOUT,
67        DORMANT
68    }
69
70    //***** Event Codes
71    protected static final int EVENT_DATA_SETUP_COMPLETE = 1;
72    protected static final int EVENT_RADIO_AVAILABLE = 3;
73    protected static final int EVENT_RECORDS_LOADED = 4;
74    protected static final int EVENT_TRY_SETUP_DATA = 5;
75    protected static final int EVENT_DATA_STATE_CHANGED = 6;
76    protected static final int EVENT_POLL_PDP = 7;
77    protected static final int EVENT_GET_PDP_LIST_COMPLETE = 11;
78    protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
79    protected static final int EVENT_VOICE_CALL_STARTED = 14;
80    protected static final int EVENT_VOICE_CALL_ENDED = 15;
81    protected static final int EVENT_GPRS_DETACHED = 19;
82    protected static final int EVENT_LINK_STATE_CHANGED = 20;
83    protected static final int EVENT_ROAMING_ON = 21;
84    protected static final int EVENT_ROAMING_OFF = 22;
85    protected static final int EVENT_ENABLE_NEW_APN = 23;
86    protected static final int EVENT_RESTORE_DEFAULT_APN = 24;
87    protected static final int EVENT_DISCONNECT_DONE = 25;
88    protected static final int EVENT_GPRS_ATTACHED = 26;
89    protected static final int EVENT_START_NETSTAT_POLL = 27;
90    protected static final int EVENT_START_RECOVERY = 28;
91    protected static final int EVENT_APN_CHANGED = 29;
92    protected static final int EVENT_CDMA_DATA_DETACHED = 30;
93    protected static final int EVENT_NV_READY = 31;
94    protected static final int EVENT_PS_RESTRICT_ENABLED = 32;
95    protected static final int EVENT_PS_RESTRICT_DISABLED = 33;
96    public static final int EVENT_CLEAN_UP_CONNECTION = 34;
97    protected static final int EVENT_CDMA_OTA_PROVISION = 35;
98
99    //***** Constants
100
101    /** Retry configuration: A doubling of retry times from 5secs to 30minutes */
102    protected static final String DEFAULT_DATA_RETRY_CONFIG = "default_randomization=2000,"
103        + "5000,10000,20000,40000,80000:5000,160000:5000,"
104        + "320000:5000,640000:5000,1280000:5000,1800000:5000";
105
106    /** Slow poll when attempting connection recovery. */
107    protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000;
108    /** Default ping deadline, in seconds. */
109    protected static final int DEFAULT_PING_DEADLINE = 5;
110    /** Default max failure count before attempting to network re-registration. */
111    protected static final int DEFAULT_MAX_PDP_RESET_FAIL = 3;
112
113    /**
114     * After detecting a potential connection problem, this is the max number
115     * of subsequent polls before attempting a radio reset.  At this point,
116     * poll interval is 5 seconds (POLL_NETSTAT_SLOW_MILLIS), so set this to
117     * poll for about 2 more minutes.
118     */
119    protected static final int NO_RECV_POLL_LIMIT = 24;
120
121    // 1 sec. default polling interval when screen is on.
122    protected static final int POLL_NETSTAT_MILLIS = 1000;
123    // 10 min. default polling interval when screen is off.
124    protected static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10;
125    // 2 min for round trip time
126    protected static final int POLL_LONGEST_RTT = 120 * 1000;
127    // 10 for packets without ack
128    protected static final int NUMBER_SENT_PACKETS_OF_HANG = 10;
129    // how long to wait before switching back to default APN
130    protected static final int RESTORE_DEFAULT_APN_DELAY = 1 * 60 * 1000;
131    // system property that can override the above value
132    protected static final String APN_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore";
133    // represents an invalid IP address
134    protected static final String NULL_IP = "0.0.0.0";
135
136
137    // member variables
138    protected PhoneBase phone;
139    protected Activity activity = Activity.NONE;
140    protected State state = State.IDLE;
141    protected Handler mDataConnectionTracker = null;
142
143
144    protected INetStatService netstat;
145    protected long txPkts, rxPkts, sentSinceLastRecv;
146    protected int netStatPollPeriod;
147    protected int mNoRecvPollCount = 0;
148    protected boolean netStatPollEnabled = false;
149
150    /** Manage the behavior of data retry after failure */
151    protected final RetryManager mRetryMgr = new RetryManager();
152
153    // wifi connection status will be updated by sticky intent
154    protected boolean mIsWifiConnected = false;
155
156    /** Intent sent when the reconnect alarm fires. */
157    protected PendingIntent mReconnectIntent = null;
158
159    /** CID of active data connection */
160    protected int cidActive;
161
162   /**
163     * Default constructor
164     */
165    protected DataConnectionTracker(PhoneBase phone) {
166        super();
167        this.phone = phone;
168    }
169
170    public Activity getActivity() {
171        return activity;
172    }
173
174    public State getState() {
175        return state;
176    }
177
178    public String getStateInString() {
179        switch (state) {
180            case IDLE:          return "IDLE";
181            case INITING:       return "INIT";
182            case CONNECTING:    return "CING";
183            case SCANNING:      return "SCAN";
184            case CONNECTED:     return "CNTD";
185            case DISCONNECTING: return "DING";
186            case FAILED:        return "FAIL";
187            default:            return "ERRO";
188        }
189    }
190
191    /**
192     * The data connection is expected to be setup while device
193     *  1. has Icc card
194     *  2. registered for data service
195     *  3. user doesn't explicitly disable data service
196     *  4. wifi is not on
197     *
198     * @return false while no data connection if all above requirements are met.
199     */
200    public abstract boolean isDataConnectionAsDesired();
201
202    //The data roaming setting is now located in the shared preferences.
203    //  See if the requested preference value is the same as that stored in
204    //  the shared values.  If it is not, then update it.
205    public void setDataOnRoamingEnabled(boolean enabled) {
206        if (getDataOnRoamingEnabled() != enabled) {
207            Settings.Secure.putInt(phone.getContext().getContentResolver(),
208                Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
209            if (phone.getServiceState().getRoaming()) {
210                if (enabled) {
211                    mRetryMgr.resetRetryCount();
212                }
213                sendMessage(obtainMessage(EVENT_ROAMING_ON));
214            }
215        }
216    }
217
218    //Retrieve the data roaming setting from the shared preferences.
219    public boolean getDataOnRoamingEnabled() {
220        try {
221            return Settings.Secure.getInt(phone.getContext().getContentResolver(),
222                Settings.Secure.DATA_ROAMING) > 0;
223        } catch (SettingNotFoundException snfe) {
224            return false;
225        }
226    }
227
228    // abstract handler methods
229    protected abstract void onTrySetupData(String reason);
230    protected abstract void onRoamingOff();
231    protected abstract void onRoamingOn();
232    protected abstract void onRadioAvailable();
233    protected abstract void onRadioOffOrNotAvailable();
234    protected abstract void onDataSetupComplete(AsyncResult ar);
235    protected abstract void onDisconnectDone(AsyncResult ar);
236    protected abstract void onVoiceCallStarted();
237    protected abstract void onVoiceCallEnded();
238    protected abstract void onCleanUpConnection(boolean tearDown, String reason);
239
240  //***** Overridden from Handler
241    public void handleMessage (Message msg) {
242        switch (msg.what) {
243
244            case EVENT_TRY_SETUP_DATA:
245                String reason = null;
246                if (msg.obj instanceof String) {
247                    reason = (String)msg.obj;
248                }
249                onTrySetupData(reason);
250                break;
251
252            case EVENT_ROAMING_OFF:
253                if (getDataOnRoamingEnabled() == false) {
254                    mRetryMgr.resetRetryCount();
255                }
256                onRoamingOff();
257                break;
258
259            case EVENT_ROAMING_ON:
260                onRoamingOn();
261                break;
262
263            case EVENT_RADIO_AVAILABLE:
264                onRadioAvailable();
265                break;
266
267            case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
268                onRadioOffOrNotAvailable();
269                break;
270
271            case EVENT_DATA_SETUP_COMPLETE:
272                cidActive = msg.arg1;
273                onDataSetupComplete((AsyncResult) msg.obj);
274                break;
275
276            case EVENT_DISCONNECT_DONE:
277                onDisconnectDone((AsyncResult) msg.obj);
278                break;
279
280            case EVENT_VOICE_CALL_STARTED:
281                onVoiceCallStarted();
282                break;
283
284            case EVENT_VOICE_CALL_ENDED:
285                onVoiceCallEnded();
286                break;
287
288            case EVENT_CLEAN_UP_CONNECTION:
289                boolean tearDown = (msg.arg1 == 0) ? false : true;
290                onCleanUpConnection(tearDown, (String)msg.obj);
291                break;
292
293            default:
294                Log.e("DATA", "Unidentified event = " + msg.what);
295                break;
296        }
297    }
298
299    /**
300     * Report the current state of data connectivity (enabled or disabled)
301     * @return {@code false} if data connectivity has been explicitly disabled,
302     * {@code true} otherwise.
303     */
304    public abstract boolean getDataEnabled();
305
306    /**
307     * Report on whether data connectivity is enabled
308     * @return {@code false} if data connectivity has been explicitly disabled,
309     * {@code true} otherwise.
310     */
311    public abstract boolean getAnyDataEnabled();
312
313    /**
314     * Prevent mobile data connections from being established,
315     * or once again allow mobile data connections. If the state
316     * toggles, then either tear down or set up data, as
317     * appropriate to match the new state.
318     * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
319     * @return {@code true} if the operation succeeded
320     */
321    public abstract boolean setDataEnabled(boolean enable);
322
323    protected abstract void startNetStatPoll();
324
325    protected abstract void stopNetStatPoll();
326
327    protected abstract void restartRadio();
328
329    protected abstract void log(String s);
330}
331