All the methods in DataConnectionTracker should be called only through the handler. Fix this as trySetupData was being called in the broadcast receiver. Tested: Airplane mode and GPRS retry.
320 lines
11 KiB
Java
320 lines
11 KiB
Java
/*
|
|
* Copyright (C) 2006 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;
|
|
|
|
import android.app.PendingIntent;
|
|
import android.os.AsyncResult;
|
|
import android.os.Handler;
|
|
import android.os.INetStatService;
|
|
import android.os.Message;
|
|
import android.os.RemoteException;
|
|
import android.provider.Settings;
|
|
import android.provider.Settings.SettingNotFoundException;
|
|
import android.util.Log;
|
|
|
|
/**
|
|
* {@hide}
|
|
*
|
|
*/
|
|
public abstract class DataConnectionTracker extends Handler {
|
|
private static final boolean DBG = true;
|
|
|
|
/**
|
|
* IDLE: ready to start data connection setup, default state
|
|
* INITING: state of issued setupDefaultPDP() but not finish yet
|
|
* CONNECTING: state of issued startPppd() but not finish yet
|
|
* SCANNING: data connection fails with one apn but other apns are available
|
|
* ready to start data connection on other apns (before INITING)
|
|
* CONNECTED: IP connection is setup
|
|
* DISCONNECTING: Connection.disconnect() has been called, but PDP
|
|
* context is not yet deactivated
|
|
* FAILED: data connection fail for all apns settings
|
|
*
|
|
* getDataConnectionState() maps State to DataState
|
|
* FAILED or IDLE : DISCONNECTED
|
|
* INITING or CONNECTING or SCANNING: CONNECTING
|
|
* CONNECTED : CONNECTED or DISCONNECTING
|
|
*/
|
|
public enum State {
|
|
IDLE,
|
|
INITING,
|
|
CONNECTING,
|
|
SCANNING,
|
|
CONNECTED,
|
|
DISCONNECTING,
|
|
FAILED
|
|
}
|
|
|
|
public enum Activity {
|
|
NONE,
|
|
DATAIN,
|
|
DATAOUT,
|
|
DATAINANDOUT,
|
|
DORMANT
|
|
}
|
|
|
|
//***** Event Codes
|
|
protected static final int EVENT_DATA_SETUP_COMPLETE = 1;
|
|
protected static final int EVENT_RADIO_AVAILABLE = 3;
|
|
protected static final int EVENT_RECORDS_LOADED = 4;
|
|
protected static final int EVENT_TRY_SETUP_DATA = 5;
|
|
protected static final int EVENT_DATA_STATE_CHANGED = 6;
|
|
protected static final int EVENT_POLL_PDP = 7;
|
|
protected static final int EVENT_GET_PDP_LIST_COMPLETE = 11;
|
|
protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
|
|
protected static final int EVENT_VOICE_CALL_STARTED = 14;
|
|
protected static final int EVENT_VOICE_CALL_ENDED = 15;
|
|
protected static final int EVENT_GPRS_DETACHED = 19;
|
|
protected static final int EVENT_LINK_STATE_CHANGED = 20;
|
|
protected static final int EVENT_ROAMING_ON = 21;
|
|
protected static final int EVENT_ROAMING_OFF = 22;
|
|
protected static final int EVENT_ENABLE_NEW_APN = 23;
|
|
protected static final int EVENT_RESTORE_DEFAULT_APN = 24;
|
|
protected static final int EVENT_DISCONNECT_DONE = 25;
|
|
protected static final int EVENT_GPRS_ATTACHED = 26;
|
|
protected static final int EVENT_START_NETSTAT_POLL = 27;
|
|
protected static final int EVENT_START_RECOVERY = 28;
|
|
protected static final int EVENT_APN_CHANGED = 29;
|
|
protected static final int EVENT_CDMA_DATA_DETACHED = 30;
|
|
protected static final int EVENT_NV_READY = 31;
|
|
protected static final int EVENT_PS_RESTRICT_ENABLED = 32;
|
|
protected static final int EVENT_PS_RESTRICT_DISABLED = 33;
|
|
public static final int EVENT_CLEAN_UP_CONNECTION = 34;
|
|
|
|
//***** Constants
|
|
protected static final int RECONNECT_DELAY_INITIAL_MILLIS = 5 * 1000;
|
|
|
|
/** Cap out with 1 hour retry interval. */
|
|
protected static final int RECONNECT_DELAY_MAX_MILLIS = 60 * 60 * 1000;
|
|
|
|
/** Slow poll when attempting connection recovery. */
|
|
protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000;
|
|
/** Default ping deadline, in seconds. */
|
|
protected static final int DEFAULT_PING_DEADLINE = 5;
|
|
/** Default max failure count before attempting to network re-registration. */
|
|
protected static final int DEFAULT_MAX_PDP_RESET_FAIL = 3;
|
|
|
|
/**
|
|
* After detecting a potential connection problem, this is the max number
|
|
* of subsequent polls before attempting a radio reset. At this point,
|
|
* poll interval is 5 seconds (POLL_NETSTAT_SLOW_MILLIS), so set this to
|
|
* poll for about 2 more minutes.
|
|
*/
|
|
protected static final int NO_RECV_POLL_LIMIT = 24;
|
|
|
|
// 1 sec. default polling interval when screen is on.
|
|
protected static final int POLL_NETSTAT_MILLIS = 1000;
|
|
// 10 min. default polling interval when screen is off.
|
|
protected static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10;
|
|
// 2 min for round trip time
|
|
protected static final int POLL_LONGEST_RTT = 120 * 1000;
|
|
// 10 for packets without ack
|
|
protected static final int NUMBER_SENT_PACKETS_OF_HANG = 10;
|
|
// how long to wait before switching back to default APN
|
|
protected static final int RESTORE_DEFAULT_APN_DELAY = 1 * 60 * 1000;
|
|
// system property that can override the above value
|
|
protected static final String APN_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore";
|
|
// represents an invalid IP address
|
|
protected static final String NULL_IP = "0.0.0.0";
|
|
|
|
|
|
// member variables
|
|
protected PhoneBase phone;
|
|
protected Activity activity = Activity.NONE;
|
|
protected State state = State.IDLE;
|
|
protected Handler mDataConnectionTracker = null;
|
|
|
|
|
|
protected INetStatService netstat;
|
|
protected long txPkts, rxPkts, sentSinceLastRecv;
|
|
protected int netStatPollPeriod;
|
|
protected int mNoRecvPollCount = 0;
|
|
protected boolean netStatPollEnabled = false;
|
|
|
|
// wifi connection status will be updated by sticky intent
|
|
protected boolean mIsWifiConnected = false;
|
|
|
|
/** Intent sent when the reconnect alarm fires. */
|
|
protected PendingIntent mReconnectIntent = null;
|
|
|
|
/** CID of active data connection */
|
|
protected int cidActive;
|
|
|
|
/**
|
|
* Default constructor
|
|
*/
|
|
protected DataConnectionTracker(PhoneBase phone) {
|
|
super();
|
|
this.phone = phone;
|
|
}
|
|
|
|
public Activity getActivity() {
|
|
return activity;
|
|
}
|
|
|
|
public State getState() {
|
|
return state;
|
|
}
|
|
|
|
public String getStateInString() {
|
|
switch (state) {
|
|
case IDLE: return "IDLE";
|
|
case INITING: return "INIT";
|
|
case CONNECTING: return "CING";
|
|
case SCANNING: return "SCAN";
|
|
case CONNECTED: return "CNTD";
|
|
case DISCONNECTING: return "DING";
|
|
case FAILED: return "FAIL";
|
|
default: return "ERRO";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The data connection is expected to be setup while device
|
|
* 1. has Icc card
|
|
* 2. registered for data service
|
|
* 3. user doesn't explicitly disable data service
|
|
* 4. wifi is not on
|
|
*
|
|
* @return false while no data connection if all above requirements are met.
|
|
*/
|
|
public abstract boolean isDataConnectionAsDesired();
|
|
|
|
//The data roaming setting is now located in the shared preferences.
|
|
// See if the requested preference value is the same as that stored in
|
|
// the shared values. If it is not, then update it.
|
|
public void setDataOnRoamingEnabled(boolean enabled) {
|
|
if (getDataOnRoamingEnabled() != enabled) {
|
|
Settings.Secure.putInt(phone.getContext().getContentResolver(),
|
|
Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
|
|
}
|
|
Message roamingMsg = phone.getServiceState().getRoaming() ?
|
|
obtainMessage(EVENT_ROAMING_ON) : obtainMessage(EVENT_ROAMING_OFF);
|
|
sendMessage(roamingMsg);
|
|
}
|
|
|
|
//Retrieve the data roaming setting from the shared preferences.
|
|
public boolean getDataOnRoamingEnabled() {
|
|
try {
|
|
return Settings.Secure.getInt(phone.getContext().getContentResolver(),
|
|
Settings.Secure.DATA_ROAMING) > 0;
|
|
} catch (SettingNotFoundException snfe) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// abstract handler methods
|
|
protected abstract void onTrySetupData(String reason);
|
|
protected abstract void onRoamingOff();
|
|
protected abstract void onRoamingOn();
|
|
protected abstract void onRadioAvailable();
|
|
protected abstract void onRadioOffOrNotAvailable();
|
|
protected abstract void onDataSetupComplete(AsyncResult ar);
|
|
protected abstract void onDisconnectDone(AsyncResult ar);
|
|
protected abstract void onVoiceCallStarted();
|
|
protected abstract void onVoiceCallEnded();
|
|
protected abstract void onCleanUpConnection(boolean tearDown, String reason);
|
|
|
|
//***** Overridden from Handler
|
|
public void handleMessage (Message msg) {
|
|
switch (msg.what) {
|
|
|
|
case EVENT_TRY_SETUP_DATA:
|
|
String reason = null;
|
|
if (msg.obj instanceof String) {
|
|
reason = (String)msg.obj;
|
|
}
|
|
onTrySetupData(reason);
|
|
break;
|
|
|
|
case EVENT_ROAMING_OFF:
|
|
onRoamingOff();
|
|
break;
|
|
|
|
case EVENT_ROAMING_ON:
|
|
onRoamingOn();
|
|
break;
|
|
|
|
case EVENT_RADIO_AVAILABLE:
|
|
onRadioAvailable();
|
|
break;
|
|
|
|
case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
|
|
onRadioOffOrNotAvailable();
|
|
break;
|
|
|
|
case EVENT_DATA_SETUP_COMPLETE:
|
|
cidActive = msg.arg1;
|
|
onDataSetupComplete((AsyncResult) msg.obj);
|
|
break;
|
|
|
|
case EVENT_DISCONNECT_DONE:
|
|
onDisconnectDone((AsyncResult) msg.obj);
|
|
break;
|
|
|
|
case EVENT_VOICE_CALL_STARTED:
|
|
onVoiceCallStarted();
|
|
break;
|
|
|
|
case EVENT_VOICE_CALL_ENDED:
|
|
onVoiceCallEnded();
|
|
break;
|
|
|
|
case EVENT_CLEAN_UP_CONNECTION:
|
|
boolean tearDown = (msg.arg1 == 0) ? false : true;
|
|
onCleanUpConnection(tearDown, (String)msg.obj);
|
|
break;
|
|
|
|
default:
|
|
Log.e("DATA", "Unidentified event = " + msg.what);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Report the current state of data connectivity (enabled or disabled)
|
|
* @return {@code false} if data connectivity has been explicitly disabled,
|
|
* {@code true} otherwise.
|
|
*/
|
|
public abstract boolean getDataEnabled();
|
|
|
|
/**
|
|
* Report on whether data connectivity is enabled
|
|
* @return {@code false} if data connectivity has been explicitly disabled,
|
|
* {@code true} otherwise.
|
|
*/
|
|
public abstract boolean getAnyDataEnabled();
|
|
|
|
/**
|
|
* Prevent mobile data connections from being established,
|
|
* or once again allow mobile data connections. If the state
|
|
* toggles, then either tear down or set up data, as
|
|
* appropriate to match the new state.
|
|
* @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
|
|
* @return {@code true} if the operation succeeded
|
|
*/
|
|
public abstract boolean setDataEnabled(boolean enable);
|
|
|
|
protected abstract void startNetStatPoll();
|
|
|
|
protected abstract void stopNetStatPoll();
|
|
|
|
protected abstract void restartRadio();
|
|
|
|
protected abstract void log(String s);
|
|
}
|