ServiceStateTrackerpublic final class ServiceStateTracker extends android.os.Handler
Fields Summary |
---|
static final int | DATA_ACCESS_UNKNOWNThe access technology currently in use:
0 = unknown
1 = GPRS only
2 = EDGE
3 = UMTS | static final int | DATA_ACCESS_GPRS | static final int | DATA_ACCESS_EDGE | static final int | DATA_ACCESS_UMTS | static final int | MAX_NUM_DATA_STATE_READS | static final int | DATA_STATE_POLL_SLEEP_MS | GSMPhone | phone | CommandsInterface | cm | android.telephony.ServiceState | ss | android.telephony.ServiceState | newSS | android.telephony.gsm.GsmCellLocation | cellLoc | android.telephony.gsm.GsmCellLocation | newCellLoc | int | mPreferredNetworkType | RestrictedState | rs | int | rssi | int[] | pollingContext | boolean | mDesiredPowerState | boolean | dontPollSignalStrength | private int | gprsState | private int | newGPRSState | private int | networkTypeThe access technology currently in use: DATA_ACCESS_ | private int | newNetworkType | private boolean | mGsmRoaming | private android.os.RegistrantList | networkAttachedRegistrants | private android.os.RegistrantList | gprsAttachedRegistrants | private android.os.RegistrantList | gprsDetachedRegistrants | private android.os.RegistrantList | roamingOnRegistrants | private android.os.RegistrantList | roamingOffRegistrants | private android.os.RegistrantList | psRestrictEnabledRegistrants | private android.os.RegistrantList | psRestrictDisabledRegistrants | private boolean | mNeedFixZone | private int | mZoneOffset | private boolean | mZoneDst | private long | mZoneTime | private boolean | mGotCountryCode | String | mSavedTimeZone | long | mSavedTime | long | mSavedAtTime | private boolean | mNeedToRegForSimLoaded | private boolean | mStartedGprsRegCheck | private boolean | mReportedGprsNoReg | private android.app.Notification | mNotificationThe Notification object given to the NotificationManager. | private PowerManager.WakeLock | mWakeLock | private static final String | WAKELOCK_TAG | private String | curSpn | private String | curPlmn | private int | curSpnRule | static final boolean | DBG | static final String | LOG_TAG | static final int | POLL_PERIOD_MILLIS | static final int | DEFAULT_GPRS_CHECK_PERIOD_MILLIS | static final int | PS_ENABLED | static final int | PS_DISABLED | static final int | CS_ENABLED | static final int | CS_DISABLED | static final int | CS_NORMAL_ENABLED | static final int | CS_EMERGENCY_ENABLED | static final int | PS_NOTIFICATION | static final int | CS_NOTIFICATION | static final int | EVENT_RADIO_STATE_CHANGED | static final int | EVENT_NETWORK_STATE_CHANGED | static final int | EVENT_GET_SIGNAL_STRENGTH | static final int | EVENT_POLL_STATE_REGISTRATION | static final int | EVENT_POLL_STATE_GPRS | static final int | EVENT_POLL_STATE_OPERATOR | static final int | EVENT_POLL_SIGNAL_STRENGTH | static final int | EVENT_NITZ_TIME | static final int | EVENT_SIGNAL_STRENGTH_UPDATE | static final int | EVENT_RADIO_AVAILABLE | static final int | EVENT_POLL_STATE_NETWORK_SELECTION_MODE | static final int | EVENT_GET_LOC_DONE | static final int | EVENT_SIM_RECORDS_LOADED | static final int | EVENT_SIM_READY | static final int | EVENT_LOCATION_UPDATES_ENABLED | static final int | EVENT_GET_PREFERRED_NETWORK_TYPE | static final int | EVENT_SET_PREFERRED_NETWORK_TYPE | static final int | EVENT_RESET_PREFERRED_NETWORK_TYPE | static final int | EVENT_CHECK_REPORT_GPRS | static final int | EVENT_RESTRICTED_STATE_CHANGED | private static final String | TIMEZONE_PROPERTY | private static final String[] | GMT_COUNTRY_CODES | private android.database.ContentObserver | mAutoTimeObserver |
Constructors Summary |
---|
ServiceStateTracker(GSMPhone phone)
//***** Constructors
this.phone = phone;
cm = phone.mCM;
ss = new ServiceState();
newSS = new ServiceState();
cellLoc = new GsmCellLocation();
newCellLoc = new GsmCellLocation();
rs = new RestrictedState();
PowerManager powerManager =
(PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
cm.registerForNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null);
cm.setOnNITZTime(this, EVENT_NITZ_TIME, null);
cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
cm.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null);
cm.registerForSIMReady(this, EVENT_SIM_READY, null);
// system setting property AIRPLANE_MODE_ON is set in Settings.
int airplaneMode = Settings.System.getInt(
phone.getContext().getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0);
mDesiredPowerState = ! (airplaneMode > 0);
ContentResolver cr = phone.getContext().getContentResolver();
cr.registerContentObserver(
Settings.System.getUriFor(Settings.System.AUTO_TIME), true,
mAutoTimeObserver);
setRssiDefaultValues();
mNeedToRegForSimLoaded = true;
|
Methods Summary |
---|
private void | cancelPollState()Cancel a pending (if any) pollState() operation
// This will effectively cancel the rest of the poll requests
pollingContext = new int[1];
| void | disableLocationUpdates()
cm.setLocationUpdates(false, null);
| private static java.lang.String | displayNameFor(int off)Provides the name of the algorithmic time zone for the specified
offset. Taken from TimeZone.java.
off = off / 1000 / 60;
char[] buf = new char[9];
buf[0] = 'G";
buf[1] = 'M";
buf[2] = 'T";
if (off < 0) {
buf[3] = '-";
off = -off;
} else {
buf[3] = '+";
}
int hours = off / 60;
int minutes = off % 60;
buf[4] = (char) ('0" + hours / 10);
buf[5] = (char) ('0" + hours % 10);
buf[6] = ':";
buf[7] = (char) ('0" + minutes / 10);
buf[8] = (char) ('0" + minutes % 10);
return new String(buf);
| void | enableLocationUpdates()
cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
| private java.util.TimeZone | findTimeZone(int offset, boolean dst, long when)
int rawOffset = offset;
if (dst) {
rawOffset -= 3600000;
}
String[] zones = TimeZone.getAvailableIDs(rawOffset);
TimeZone guess = null;
Date d = new Date(when);
for (String zone : zones) {
TimeZone tz = TimeZone.getTimeZone(zone);
if (tz.getOffset(when) == offset &&
tz.inDaylightTime(d) == dst) {
guess = tz;
break;
}
}
return guess;
| private boolean | getAutoTime()
try {
return Settings.System.getInt(phone.getContext().getContentResolver(),
Settings.System.AUTO_TIME) > 0;
} catch (SettingNotFoundException snfe) {
return true;
}
| int | getCurrentGprsState()
return gprsState;
| public void | getLacAndCid(android.os.Message onComplete)
cm.getRegistrationState(obtainMessage(
EVENT_GET_LOC_DONE, onComplete));
| private java.util.TimeZone | getNitzTimeZone(int offset, boolean dst, long when)Returns a TimeZone object based only on parameters from the NITZ string.
TimeZone guess = findTimeZone(offset, dst, when);
if (guess == null) {
// Couldn't find a proper timezone. Perhaps the DST data is wrong.
guess = findTimeZone(offset, !dst, when);
}
if (DBG) {
Log.d(LOG_TAG, "getNitzTimeZone returning "
+ (guess == null ? guess : guess.getID()));
}
return guess;
| public void | handleMessage(android.os.Message msg)
AsyncResult ar;
int[] ints;
String[] strings;
Message message;
switch (msg.what) {
case EVENT_RADIO_AVAILABLE:
//this is unnecessary
//setPowerStateToDesired();
break;
case EVENT_SIM_READY:
// The SIM is now ready i.e if it was locked
// it has been unlocked. At this stage, the radio is already
// powered on.
if (mNeedToRegForSimLoaded) {
phone.mSIMRecords.registerForRecordsLoaded(this,
EVENT_SIM_RECORDS_LOADED, null);
mNeedToRegForSimLoaded = false;
}
// restore the previous network selection.
phone.restoreSavedNetworkSelection(null);
pollState();
// Signal strength polling stops when radio is off
queueNextSignalStrengthPoll();
break;
case EVENT_RADIO_STATE_CHANGED:
// This will do nothing in the radio not
// available case
setPowerStateToDesired();
pollState();
break;
case EVENT_NETWORK_STATE_CHANGED:
pollState();
break;
case EVENT_GET_SIGNAL_STRENGTH:
// This callback is called when signal strength is polled
// all by itself
if (!(cm.getRadioState().isOn())) {
// Polling will continue when radio turns back on
return;
}
ar = (AsyncResult) msg.obj;
onSignalStrengthResult(ar);
queueNextSignalStrengthPoll();
break;
case EVENT_GET_LOC_DONE:
ar = (AsyncResult) msg.obj;
if (ar.exception == null) {
String states[] = (String[])ar.result;
int lac = -1;
int cid = -1;
if (states.length == 3) {
try {
if (states[1] != null && states[1].length() > 0) {
lac = Integer.parseInt(states[1], 16);
}
if (states[2] != null && states[2].length() > 0) {
cid = Integer.parseInt(states[2], 16);
}
} catch (NumberFormatException ex) {
Log.w(LOG_TAG, "error parsing location: " + ex);
}
}
// only update if lac or cid changed
if (cellLoc.getCid() != cid || cellLoc.getLac() != lac) {
cellLoc.setLacAndCid(lac, cid);
phone.notifyLocationChanged();
}
}
if (ar.userObj != null) {
AsyncResult.forMessage(((Message) ar.userObj)).exception
= ar.exception;
((Message) ar.userObj).sendToTarget();
}
break;
case EVENT_POLL_STATE_REGISTRATION:
case EVENT_POLL_STATE_GPRS:
case EVENT_POLL_STATE_OPERATOR:
case EVENT_POLL_STATE_NETWORK_SELECTION_MODE:
ar = (AsyncResult) msg.obj;
handlePollStateResult(msg.what, ar);
break;
case EVENT_POLL_SIGNAL_STRENGTH:
// Just poll signal strength...not part of pollState()
cm.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
break;
case EVENT_NITZ_TIME:
ar = (AsyncResult) msg.obj;
String nitzString = (String)((Object[])ar.result)[0];
long nitzReceiveTime = ((Long)((Object[])ar.result)[1]).longValue();
setTimeFromNITZString(nitzString, nitzReceiveTime);
break;
case EVENT_SIGNAL_STRENGTH_UPDATE:
// This is a notification from
// CommandsInterface.setOnSignalStrengthUpdate
ar = (AsyncResult) msg.obj;
// The radio is telling us about signal strength changes
// we don't have to ask it
dontPollSignalStrength = true;
onSignalStrengthResult(ar);
break;
case EVENT_SIM_RECORDS_LOADED:
updateSpnDisplay();
break;
case EVENT_LOCATION_UPDATES_ENABLED:
ar = (AsyncResult) msg.obj;
if (ar.exception == null) {
getLacAndCid(null);
}
break;
case EVENT_SET_PREFERRED_NETWORK_TYPE:
ar = (AsyncResult) msg.obj;
// Don't care the result, only use for dereg network (COPS=2)
message = obtainMessage(EVENT_RESET_PREFERRED_NETWORK_TYPE, ar.userObj);
cm.setPreferredNetworkType(mPreferredNetworkType, message);
break;
case EVENT_RESET_PREFERRED_NETWORK_TYPE:
ar = (AsyncResult) msg.obj;
if (ar.userObj != null) {
AsyncResult.forMessage(((Message) ar.userObj)).exception
= ar.exception;
((Message) ar.userObj).sendToTarget();
}
break;
case EVENT_GET_PREFERRED_NETWORK_TYPE:
ar = (AsyncResult) msg.obj;
if (ar.exception == null) {
mPreferredNetworkType = ((int[])ar.result)[0];
} else {
mPreferredNetworkType = Phone.NT_AUTO_TYPE;
}
message = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE, ar.userObj);
int toggledNetworkType =
(mPreferredNetworkType == Phone.NT_AUTO_TYPE) ?
Phone.NT_GSM_TYPE : Phone.NT_AUTO_TYPE;
cm.setPreferredNetworkType(toggledNetworkType, message);
break;
case EVENT_CHECK_REPORT_GPRS:
if (ss != null && !isGprsConsistant(gprsState, ss.getState())) {
// Can't register data sevice while voice service is ok
// i.e. CREG is ok while CGREG is not
// possible a network or baseband side error
int cid = -1;
GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
if (loc != null) cid = loc.getCid();
EventLog.List val = new EventLog.List(ss.getOperatorNumeric(), cid);
EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CGREG_FAIL, val);
mReportedGprsNoReg = true;
}
mStartedGprsRegCheck = false;
break;
case EVENT_RESTRICTED_STATE_CHANGED:
// This is a notification from
// CommandsInterface.setOnRestrictedStateChanged
Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_RESTRICTED_STATE_CHANGED");
ar = (AsyncResult) msg.obj;
onRestrictedStateChanged(ar);
break;
}
| private void | handlePollStateResult(int what, android.os.AsyncResult ar)Handle the result of one of the pollState()-related requests
int ints[];
String states[];
// Ignore stale requests from last poll
if (ar.userObj != pollingContext) return;
if (ar.exception != null) {
CommandException.Error err=null;
if (ar.exception instanceof CommandException) {
err = ((CommandException)(ar.exception)).getCommandError();
}
if (err == CommandException.Error.RADIO_NOT_AVAILABLE) {
// Radio has crashed or turned off
cancelPollState();
return;
}
if (!cm.getRadioState().isOn()) {
// Radio has crashed or turned off
cancelPollState();
return;
}
if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW &&
err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
Log.e(LOG_TAG,
"RIL implementation has returned an error where it must succeed" +
ar.exception);
}
} else try {
switch (what) {
case EVENT_POLL_STATE_REGISTRATION:
states = (String[])ar.result;
int lac = -1;
int cid = -1;
int regState = -1;
if (states.length > 0) {
try {
regState = Integer.parseInt(states[0]);
if (states.length == 3) {
if (states[1] != null && states[1].length() > 0) {
lac = Integer.parseInt(states[1], 16);
}
if (states[2] != null && states[2].length() > 0) {
cid = Integer.parseInt(states[2], 16);
}
}
} catch (NumberFormatException ex) {
Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
}
}
mGsmRoaming = regCodeIsRoaming(regState);
newSS.setState (regCodeToServiceState(regState));
// LAC and CID are -1 if not avail
newCellLoc.setLacAndCid(lac, cid);
break;
case EVENT_POLL_STATE_GPRS:
states = (String[])ar.result;
int type = 0;
regState = -1;
if (states.length > 0) {
try {
regState = Integer.parseInt(states[0]);
// states[3] (if present) is the current radio technology
if (states.length >= 4 && states[3] != null) {
type = Integer.parseInt(states[3]);
}
} catch (NumberFormatException ex) {
Log.w(LOG_TAG, "error parsing GprsRegistrationState: " + ex);
}
}
newGPRSState = regCodeToServiceState(regState);
newNetworkType = type;
break;
case EVENT_POLL_STATE_OPERATOR:
String opNames[] = (String[])ar.result;
if (opNames != null && opNames.length >= 3) {
newSS.setOperatorName (
opNames[0], opNames[1], opNames[2]);
}
break;
case EVENT_POLL_STATE_NETWORK_SELECTION_MODE:
ints = (int[])ar.result;
newSS.setIsManualSelection(ints[0] == 1);
break;
}
} catch (RuntimeException ex) {
Log.e(LOG_TAG, "Exception while polling service state. "
+ "Probably malformed RIL response.", ex);
}
pollingContext[0]--;
if (pollingContext[0] == 0) {
newSS.setRoaming(isRoamingBetweenOperators(mGsmRoaming, newSS));
pollStateDone();
}
| boolean | isConcurrentVoiceAndData()
return (networkType == DATA_ACCESS_UMTS);
| private boolean | isGprsConsistant(int gprsState, int serviceState)Check if GPRS got registred while voice is registered
return !((serviceState == ServiceState.STATE_IN_SERVICE) &&
(gprsState != ServiceState.STATE_IN_SERVICE));
| private boolean | isRoamingBetweenOperators(boolean gsmRoaming, android.telephony.ServiceState s)Set roaming state when gsmRoaming is true and, if operator mcc is the
same as sim mcc, ons is different from spn
String spn = SystemProperties.get(PROPERTY_SIM_OPERATOR_ALPHA, "empty");
String onsl = s.getOperatorAlphaLong();
String onss = s.getOperatorAlphaShort();
boolean equalsOnsl = onsl != null && spn.equals(onsl);
boolean equalsOnss = onss != null && spn.equals(onss);
String simNumeric = SystemProperties.get(PROPERTY_SIM_OPERATOR_NUMERIC, "");
String operatorNumeric = s.getOperatorNumeric();
boolean equalsMcc = true;
try {
equalsMcc = simNumeric.substring(0, 3).
equals(operatorNumeric.substring(0, 3));
} catch (Exception e){
}
return gsmRoaming && !(equalsMcc && (equalsOnsl || equalsOnss));
| private static java.lang.String | networkTypeToString(int type)
String ret = "unknown";
switch (type) {
case DATA_ACCESS_GPRS:
ret = "GPRS";
break;
case DATA_ACCESS_EDGE:
ret = "EDGE";
break;
case DATA_ACCESS_UMTS:
ret = "UMTS";
break;
}
return ret;
| private void | onRestrictedStateChanged(android.os.AsyncResult ar)Set restricted state based on the OnRestrictedStateChanged notification
If any voice or packet restricted state changes, trigger a UI
notification and notify registrants when sim is ready.
Log.d(LOG_TAG, "[DSAC DEB] " + "onRestrictedStateChanged");
RestrictedState newRs = new RestrictedState();
Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at enter "+ rs);
if (ar.exception == null) {
int[] ints = (int[])ar.result;
int state = ints[0];
newRs.setCsEmergencyRestricted(
((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) ||
((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
//ignore the normal call and data restricted state before SIM READY
if (phone.getSimCard().getState() == SimCard.State.READY){
newRs.setCsNormalRestricted(
((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) ||
((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
newRs.setPsRestricted(
(state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0);
}
Log.d(LOG_TAG, "[DSAC DEB] " + "new rs "+ newRs);
if (!rs.isPsRestricted() && newRs.isPsRestricted()) {
psRestrictEnabledRegistrants.notifyRegistrants();
setNotification(PS_ENABLED);
} else if (rs.isPsRestricted() && !newRs.isPsRestricted()) {
psRestrictDisabledRegistrants.notifyRegistrants();
setNotification(PS_DISABLED);
}
/**
* There are two kind of cs restriction, normal and emergency. So
* there are 4 x 4 combinations in current and new restricted states
* and we only need to notify when state is changed.
*/
if (rs.isCsRestricted()) {
if (!newRs.isCsRestricted()) {
// remove all restriction
setNotification(CS_DISABLED);
} else if (!newRs.isCsNormalRestricted()) {
// remove normal restriction
setNotification(CS_EMERGENCY_ENABLED);
} else if (!newRs.isCsEmergencyRestricted()) {
// remove emergency restriction
setNotification(CS_NORMAL_ENABLED);
}
} else if (rs.isCsEmergencyRestricted() && !rs.isCsNormalRestricted()) {
if (!newRs.isCsRestricted()) {
// remove all restriction
setNotification(CS_DISABLED);
} else if (newRs.isCsRestricted()) {
// enable all restriction
setNotification(CS_ENABLED);
} else if (newRs.isCsNormalRestricted()) {
// remove emergency restriction and enable normal restriction
setNotification(CS_NORMAL_ENABLED);
}
} else if (!rs.isCsEmergencyRestricted() && rs.isCsNormalRestricted()) {
if (!newRs.isCsRestricted()) {
// remove all restriction
setNotification(CS_DISABLED);
} else if (newRs.isCsRestricted()) {
// enable all restriction
setNotification(CS_ENABLED);
} else if (newRs.isCsEmergencyRestricted()) {
// remove normal restriction and enable emergency restriction
setNotification(CS_EMERGENCY_ENABLED);
}
} else {
if (newRs.isCsRestricted()) {
// enable all restriction
setNotification(CS_ENABLED);
} else if (newRs.isCsEmergencyRestricted()) {
// enable emergency restriction
setNotification(CS_EMERGENCY_ENABLED);
} else if (newRs.isCsNormalRestricted()) {
// enable normal restriction
setNotification(CS_NORMAL_ENABLED);
}
}
rs = newRs;
}
Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at return "+ rs);
| private void | onSignalStrengthResult(android.os.AsyncResult ar)send signal-strength-changed notification if rssi changed
Called both for solicited and unsolicited signal stength updates
int oldRSSI = rssi;
if (ar.exception != null) {
// 99 = unknown
// most likely radio is resetting/disconnected
rssi = 99;
} else {
int[] ints = (int[])ar.result;
// bug 658816 seems to be a case where the result is 0-length
if (ints.length != 0) {
rssi = ints[0];
} else {
Log.e(LOG_TAG, "Bogus signal strength response");
rssi = 99;
}
}
if (rssi != oldRSSI) {
phone.notifySignalStrength();
}
| private void | pollState()A complete "service state" from our perspective is
composed of a handful of separate requests to the radio.
We make all of these requests at once, but then abandon them
and start over again if the radio notifies us that some
event has changed
pollingContext = new int[1];
pollingContext[0] = 0;
switch (cm.getRadioState()) {
case RADIO_UNAVAILABLE:
newSS.setStateOutOfService();
newCellLoc.setStateInvalid();
setRssiDefaultValues();
mGotCountryCode = false;
pollStateDone();
break;
case RADIO_OFF:
newSS.setStateOff();
newCellLoc.setStateInvalid();
setRssiDefaultValues();
mGotCountryCode = false;
pollStateDone();
break;
default:
// Issue all poll-related commands at once
// then count down the responses, which
// are allowed to arrive out-of-order
pollingContext[0]++;
cm.getOperator(
obtainMessage(
EVENT_POLL_STATE_OPERATOR, pollingContext));
pollingContext[0]++;
cm.getGPRSRegistrationState(
obtainMessage(
EVENT_POLL_STATE_GPRS, pollingContext));
pollingContext[0]++;
cm.getRegistrationState(
obtainMessage(
EVENT_POLL_STATE_REGISTRATION, pollingContext));
pollingContext[0]++;
cm.getNetworkSelectionMode(
obtainMessage(
EVENT_POLL_STATE_NETWORK_SELECTION_MODE, pollingContext));
break;
}
| private void | pollStateDone()
if (DBG) {
Log.d(LOG_TAG, "Poll ServiceState done: " +
" oldSS=[" + ss + "] newSS=[" + newSS +
"] oldGprs=" + gprsState + " newGprs=" + newGPRSState +
" oldType=" + networkTypeToString(networkType) +
" newType=" + networkTypeToString(newNetworkType));
}
boolean hasRegistered =
ss.getState() != ServiceState.STATE_IN_SERVICE
&& newSS.getState() == ServiceState.STATE_IN_SERVICE;
boolean hasDeregistered =
ss.getState() == ServiceState.STATE_IN_SERVICE
&& newSS.getState() != ServiceState.STATE_IN_SERVICE;
boolean hasGprsAttached =
gprsState != ServiceState.STATE_IN_SERVICE
&& newGPRSState == ServiceState.STATE_IN_SERVICE;
boolean hasGprsDetached =
gprsState == ServiceState.STATE_IN_SERVICE
&& newGPRSState != ServiceState.STATE_IN_SERVICE;
boolean hasNetworkTypeChanged = networkType != newNetworkType;
boolean hasChanged = !newSS.equals(ss);
boolean hasRoamingOn = !ss.getRoaming() && newSS.getRoaming();
boolean hasRoamingOff = ss.getRoaming() && !newSS.getRoaming();
boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
ServiceState tss;
tss = ss;
ss = newSS;
newSS = tss;
// clean slate for next time
newSS.setStateOutOfService();
GsmCellLocation tcl = cellLoc;
cellLoc = newCellLoc;
newCellLoc = tcl;
gprsState = newGPRSState;
networkType = newNetworkType;
newSS.setStateOutOfService(); // clean slate for next time
if (hasNetworkTypeChanged) {
phone.setSystemProperty(PROPERTY_DATA_NETWORK_TYPE,
networkTypeToString(networkType));
}
if (hasRegistered) {
Checkin.updateStats(phone.getContext().getContentResolver(),
Checkin.Stats.Tag.PHONE_GSM_REGISTERED, 1, 0.0);
networkAttachedRegistrants.notifyRegistrants();
}
if (hasChanged) {
String operatorNumeric;
phone.setSystemProperty(PROPERTY_OPERATOR_ALPHA,
ss.getOperatorAlphaLong());
operatorNumeric = ss.getOperatorNumeric();
phone.setSystemProperty(PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
if (operatorNumeric == null) {
phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, "");
} else {
String iso = "";
try{
iso = MccTable.countryCodeForMcc(Integer.parseInt(
operatorNumeric.substring(0,3)));
} catch ( NumberFormatException ex){
Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
} catch ( StringIndexOutOfBoundsException ex) {
Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
}
phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, iso);
mGotCountryCode = true;
if (mNeedFixZone) {
TimeZone zone = null;
// If the offset is (0, false) and the timezone property
// is set, use the timezone property rather than
// GMT.
String zoneName = SystemProperties.get(TIMEZONE_PROPERTY);
if ((mZoneOffset == 0) && (mZoneDst == false) &&
(zoneName != null) && (zoneName.length() > 0) &&
(Arrays.binarySearch(GMT_COUNTRY_CODES, iso) < 0)) {
zone = TimeZone.getDefault();
// For NITZ string without timezone,
// need adjust time to reflect default timezone setting
long tzOffset;
tzOffset = zone.getOffset(System.currentTimeMillis());
if (getAutoTime()) {
setAndBroadcastNetworkSetTime(System.currentTimeMillis() - tzOffset);
} else {
// Adjust the saved NITZ time to account for tzOffset.
mSavedTime = mSavedTime - tzOffset;
}
} else if (iso.equals("")){
// Country code not found. This is likely a test network.
// Get a TimeZone based only on the NITZ parameters (best guess).
zone = getNitzTimeZone(mZoneOffset, mZoneDst, mZoneTime);
} else {
zone = TimeUtils.getTimeZone(mZoneOffset,
mZoneDst, mZoneTime, iso);
}
mNeedFixZone = false;
if (zone != null) {
if (getAutoTime()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
}
}
}
phone.setSystemProperty(PROPERTY_OPERATOR_ISROAMING,
ss.getRoaming() ? "true" : "false");
updateSpnDisplay();
phone.notifyServiceStateChanged(ss);
}
if (hasGprsAttached) {
gprsAttachedRegistrants.notifyRegistrants();
}
if (hasGprsDetached) {
gprsDetachedRegistrants.notifyRegistrants();
}
if (hasNetworkTypeChanged) {
phone.notifyDataConnection(null);
}
if (hasRoamingOn) {
roamingOnRegistrants.notifyRegistrants();
}
if (hasRoamingOff) {
roamingOffRegistrants.notifyRegistrants();
}
if (hasLocationChanged) {
phone.notifyLocationChanged();
}
if (! isGprsConsistant(gprsState, ss.getState())) {
if (!mStartedGprsRegCheck && !mReportedGprsNoReg) {
mStartedGprsRegCheck = true;
int check_period = Settings.Gservices.getInt(
phone.getContext().getContentResolver(),
Settings.Gservices.GPRS_REGISTER_CHECK_PERIOD_MS,
DEFAULT_GPRS_CHECK_PERIOD_MILLIS);
sendMessageDelayed(obtainMessage(EVENT_CHECK_REPORT_GPRS),
check_period);
}
} else {
mReportedGprsNoReg = false;
}
| private void | queueNextSignalStrengthPoll()
if (dontPollSignalStrength) {
// The radio is telling us about signal strength changes
// we don't have to ask it
return;
}
Message msg;
msg = obtainMessage();
msg.what = EVENT_POLL_SIGNAL_STRENGTH;
long nextTime;
// TODO Done't poll signal strength if screen is off
sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
| void | reRegisterNetwork(android.os.Message onComplete)Reregister network through toggle perferred network type
This is a work aorund to deregister and register network since there is
no ril api to set COPS=2 (deregister) only.
cm.getPreferredNetworkType(
obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE, onComplete));
| private boolean | regCodeIsRoaming(int code)code is registration state 0-5 from TS 27.007 7.2
returns true if registered roam, false otherwise
// 5 is "in service -- roam"
return 5 == code;
| private int | regCodeToServiceState(int code)code is registration state 0-5 from TS 27.007 7.2
switch (code) {
case 0:
case 2: // 2 is "searching"
case 3: // 3 is "registration denied"
case 4: // 4 is "unknown" no vaild in current baseband
return ServiceState.STATE_OUT_OF_SERVICE;
case 1:
return ServiceState.STATE_IN_SERVICE;
case 5:
// in service, roam
return ServiceState.STATE_IN_SERVICE;
default:
Log.w(LOG_TAG, "unexpected service state " + code);
return ServiceState.STATE_OUT_OF_SERVICE;
}
| void | registerForGprsAttached(android.os.Handler h, int what, java.lang.Object obj)Registration point for transition into GPRS attached.
Registrant r = new Registrant(h, what, obj);
gprsAttachedRegistrants.add(r);
if (gprsState == ServiceState.STATE_IN_SERVICE) {
r.notifyRegistrant();
}
| void | registerForGprsDetached(android.os.Handler h, int what, java.lang.Object obj)Registration point for transition into GPRS detached.
Registrant r = new Registrant(h, what, obj);
gprsDetachedRegistrants.add(r);
if (gprsState == ServiceState.STATE_OUT_OF_SERVICE) {
r.notifyRegistrant();
}
| void | registerForNetworkAttach(android.os.Handler h, int what, java.lang.Object obj)
Registrant r = new Registrant(h, what, obj);
networkAttachedRegistrants.add(r);
if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
r.notifyRegistrant();
}
| void | registerForPsRestrictedDisabled(android.os.Handler h, int what, java.lang.Object obj)Registration point for transition out of packet service restricted zone.
Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedDisabled ");
Registrant r = new Registrant(h, what, obj);
psRestrictDisabledRegistrants.add(r);
if (rs.isPsRestricted()) {
r.notifyRegistrant();
}
| void | registerForPsRestrictedEnabled(android.os.Handler h, int what, java.lang.Object obj)Registration point for transition into packet service restricted zone.
Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedEnabled ");
Registrant r = new Registrant(h, what, obj);
psRestrictEnabledRegistrants.add(r);
if (rs.isPsRestricted()) {
r.notifyRegistrant();
}
| void | registerForRoamingOff(android.os.Handler h, int what, java.lang.Object obj)Registration point for combined roaming off
combined roaming is true when roaming is true and ONS differs SPN
Registrant r = new Registrant(h, what, obj);
roamingOffRegistrants.add(r);
if (!ss.getRoaming()) {
r.notifyRegistrant();
}
| void | registerForRoamingOn(android.os.Handler h, int what, java.lang.Object obj)Registration point for combined roaming on
combined roaming is true when roaming is true and ONS differs SPN
Registrant r = new Registrant(h, what, obj);
roamingOnRegistrants.add(r);
if (ss.getRoaming()) {
r.notifyRegistrant();
}
| private void | revertToNitz()
if (Settings.System.getInt(phone.getContext().getContentResolver(),
Settings.System.AUTO_TIME, 0) == 0) {
return;
}
Log.d(LOG_TAG, "Reverting to NITZ: tz='" + mSavedTimeZone
+ "' mSavedTime=" + mSavedTime
+ " mSavedAtTime=" + mSavedAtTime);
if (mSavedTimeZone != null && mSavedTime != 0 && mSavedAtTime != 0) {
setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
setAndBroadcastNetworkSetTime(mSavedTime
+ (SystemClock.elapsedRealtime() - mSavedAtTime));
}
| private void | saveNitzTime(long time)
mSavedTime = time;
mSavedAtTime = SystemClock.elapsedRealtime();
| private void | saveNitzTimeZone(java.lang.String zoneId)
mSavedTimeZone = zoneId;
| private void | setAndBroadcastNetworkSetTime(long time)Set the time and Send out a sticky broadcast so the system can determine
if the time was set by the carrier.
SystemClock.setCurrentTimeMillis(time);
Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
intent.putExtra("time", time);
phone.getContext().sendStickyBroadcast(intent);
| private void | setAndBroadcastNetworkSetTimeZone(java.lang.String zoneId)Set the timezone and send out a sticky broadcast so the system can
determine if the timezone was set by the carrier.
AlarmManager alarm =
(AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
alarm.setTimeZone(zoneId);
Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
intent.putExtra("time-zone", zoneId);
phone.getContext().sendStickyBroadcast(intent);
| private void | setNotification(int notifyType)Post a notification to NotificationManager for restricted state
Log.d(LOG_TAG, "[DSAC DEB] " + "create notification " + notifyType);
Context context = phone.getContext();
mNotification = new Notification();
mNotification.when = System.currentTimeMillis();
mNotification.flags = Notification.FLAG_AUTO_CANCEL;
mNotification.icon = com.android.internal.R.drawable.stat_sys_warning;
Intent intent = new Intent();
mNotification.contentIntent = PendingIntent
.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
CharSequence details = "";
CharSequence title = context.getText(com.android.internal.R.string.RestrictedChangedTitle);
int notificationId = CS_NOTIFICATION;
switch (notifyType) {
case PS_ENABLED:
notificationId = PS_NOTIFICATION;
details = context.getText(com.android.internal.R.string.RestrictedOnData);;
break;
case PS_DISABLED:
notificationId = PS_NOTIFICATION;
break;
case CS_ENABLED:
details = context.getText(com.android.internal.R.string.RestrictedOnAll);;
break;
case CS_NORMAL_ENABLED:
details = context.getText(com.android.internal.R.string.RestrictedOnNormal);;
break;
case CS_EMERGENCY_ENABLED:
details = context.getText(com.android.internal.R.string.RestrictedOnEmergency);;
break;
case CS_DISABLED:
// do nothing and cancel the notification later
break;
}
Log.d(LOG_TAG, "[DSAC DEB] " + "put notification " + title + " / " +details);
mNotification.tickerText = title;
mNotification.setLatestEventInfo(context, title, details,
mNotification.contentIntent);
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) {
// cancel previous post notification
notificationManager.cancel(notificationId);
} else {
// update restricted state notification
notificationManager.notify(notificationId, mNotification);
}
| private void | setPowerStateToDesired()
// If we want it on and it's off, turn it on
if (mDesiredPowerState
&& cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF
) {
cm.setRadioPower(true, null);
} else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
DataConnectionTracker dcTracker = phone.mDataConnection;
if (! dcTracker.isDataConnectionAsDesired()) {
EventLog.List val = new EventLog.List(
dcTracker.getStateInString(),
(dcTracker.getAnyDataEnabled() ? 1 : 0) );
EventLog.writeEvent(TelephonyEventLog.EVENT_DATA_STATE_RADIO_OFF, val);
}
dcTracker.cleanConnectionBeforeRadioOff();
// poll data state up to 15 times, with a 100ms delay
// totaling 1.5 sec. Normal data disable action will finish in 100ms.
for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
if (dcTracker.state != State.CONNECTED
&& dcTracker.state != State.DISCONNECTING) {
Log.d(LOG_TAG, "Data shutdown complete.");
break;
}
SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
}
// If it's on and available and we want it off..
cm.setRadioPower(false, null);
} // Otherwise, we're in the desired state
| public void | setRadioPower(boolean power)
mDesiredPowerState = power;
setPowerStateToDesired();
| private void | setRssiDefaultValues()
rssi = 99;
| private void | setTimeFromNITZString(java.lang.String nitz, long nitzReceiveTime)nitzReceiveTime is time_t that the NITZ time was posted
// "yy/mm/dd,hh:mm:ss(+/-)tz"
// tz is in number of quarter-hours
long start = SystemClock.elapsedRealtime();
Log.i(LOG_TAG, "NITZ: " + nitz + "," + nitzReceiveTime +
" start=" + start + " delay=" + (start - nitzReceiveTime));
try {
/* NITZ time (hour:min:sec) will be in UTC but it supplies the timezone
* offset as well (which we won't worry about until later) */
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
c.clear();
c.set(Calendar.DST_OFFSET, 0);
String[] nitzSubs = nitz.split("[/:,+-]");
int year = 2000 + Integer.parseInt(nitzSubs[0]);
c.set(Calendar.YEAR, year);
// month is 0 based!
int month = Integer.parseInt(nitzSubs[1]) - 1;
c.set(Calendar.MONTH, month);
int date = Integer.parseInt(nitzSubs[2]);
c.set(Calendar.DATE, date);
int hour = Integer.parseInt(nitzSubs[3]);
c.set(Calendar.HOUR, hour);
int minute = Integer.parseInt(nitzSubs[4]);
c.set(Calendar.MINUTE, minute);
int second = Integer.parseInt(nitzSubs[5]);
c.set(Calendar.SECOND, second);
boolean sign = (nitz.indexOf('-") == -1);
int tzOffset = Integer.parseInt(nitzSubs[6]);
int dst = (nitzSubs.length >= 8 ) ? Integer.parseInt(nitzSubs[7])
: 0;
// The zone offset received from NITZ is for current local time,
// so DST correction is already applied. Don't add it again.
//
// tzOffset += dst * 4;
//
// We could unapply it if we wanted the raw offset.
tzOffset = (sign ? 1 : -1) * tzOffset * 15 * 60 * 1000;
TimeZone zone = null;
// As a special extension, the Android emulator appends the name of
// the host computer's timezone to the nitz string. this is zoneinfo
// timezone name of the form Area!Location or Area!Location!SubLocation
// so we need to convert the ! into /
if (nitzSubs.length >= 9) {
String tzname = nitzSubs[8].replace('!",'/");
zone = TimeZone.getTimeZone( tzname );
}
String iso = SystemProperties.get(PROPERTY_OPERATOR_ISO_COUNTRY);
if (zone == null) {
if (mGotCountryCode) {
if (iso != null && iso.length() > 0) {
zone = TimeUtils.getTimeZone(tzOffset, dst != 0,
c.getTimeInMillis(),
iso);
} else {
// We don't have a valid iso country code. This is
// most likely because we're on a test network that's
// using a bogus MCC (eg, "001"), so get a TimeZone
// based only on the NITZ parameters.
zone = getNitzTimeZone(tzOffset, (dst != 0), c.getTimeInMillis());
}
}
}
if (zone == null) {
// We got the time before the country, so we don't know
// how to identify the DST rules yet. Save the information
// and hope to fix it up later.
mNeedFixZone = true;
mZoneOffset = tzOffset;
mZoneDst = dst != 0;
mZoneTime = c.getTimeInMillis();
}
if (zone != null) {
if (getAutoTime()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
}
String ignore = SystemProperties.get("gsm.ignore-nitz");
if (ignore != null && ignore.equals("yes")) {
Log.i(LOG_TAG, "NITZ: Not setting clock because gsm.ignore-nitz is set");
return;
}
try {
mWakeLock.acquire();
if (getAutoTime()) {
long millisSinceNitzReceived
= SystemClock.elapsedRealtime() - nitzReceiveTime;
if (millisSinceNitzReceived < 0) {
// Sanity check: something is wrong
Log.i(LOG_TAG, "NITZ: not setting time, clock has rolled "
+ "backwards since NITZ time was received, "
+ nitz);
return;
}
if (millisSinceNitzReceived > Integer.MAX_VALUE) {
// If the time is this far off, something is wrong > 24 days!
Log.i(LOG_TAG, "NITZ: not setting time, processing has taken "
+ (millisSinceNitzReceived / (1000 * 60 * 60 * 24))
+ " days");
return;
}
// Note: with range checks above, cast to int is safe
c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived);
Log.i(LOG_TAG, "NITZ: Setting time of day to " + c.getTime()
+ " NITZ receive delay(ms): " + millisSinceNitzReceived
+ " gained(ms): "
+ (c.getTimeInMillis() - System.currentTimeMillis())
+ " from " + nitz);
setAndBroadcastNetworkSetTime(c.getTimeInMillis());
Log.i(LOG_TAG, "NITZ: after Setting time of day");
}
SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
saveNitzTime(c.getTimeInMillis());
if (Config.LOGV) {
long end = SystemClock.elapsedRealtime();
Log.v(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start));
}
} finally {
mWakeLock.release();
}
} catch (RuntimeException ex) {
Log.e(LOG_TAG, "NITZ: Parsing NITZ time " + nitz, ex);
}
| private static int | twoDigitsAt(java.lang.String s, int offset)
int a, b;
a = Character.digit(s.charAt(offset), 10);
b = Character.digit(s.charAt(offset+1), 10);
if (a < 0 || b < 0) {
throw new RuntimeException("invalid format");
}
return a*10 + b;
| private void | updateSpnDisplay()
int rule = phone.mSIMRecords.getDisplayRule(ss.getOperatorNumeric());
String spn = phone.mSIMRecords.getServiceProviderName();
String plmn = ss.getOperatorAlphaLong();
if (rule != curSpnRule
|| !TextUtils.equals(spn, curSpn)
|| !TextUtils.equals(plmn, curPlmn)) {
boolean showSpn =
(rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN;
boolean showPlmn =
(rule & SIMRecords.SPN_RULE_SHOW_PLMN) == SIMRecords.SPN_RULE_SHOW_PLMN;
Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION);
intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn);
intent.putExtra(Intents.EXTRA_SPN, spn);
intent.putExtra(Intents.EXTRA_SHOW_PLMN, showPlmn);
intent.putExtra(Intents.EXTRA_PLMN, plmn);
phone.getContext().sendStickyBroadcast(intent);
}
curSpnRule = rule;
curSpn = spn;
curPlmn = plmn;
|
|