GsmServiceStateTrackerpublic final class GsmServiceStateTracker extends com.android.internal.telephony.ServiceStateTracker
Fields Summary |
---|
static final String | LOG_TAG | static final boolean | VDBG | private static final int | EVENT_ALL_DATA_DISCONNECTED | private GSMPhone | mPhone | android.telephony.gsm.GsmCellLocation | mCellLoc | android.telephony.gsm.GsmCellLocation | mNewCellLoc | int | mPreferredNetworkType | private int | mMaxDataCalls | private int | mNewMaxDataCalls | private int | mReasonDataDenied | private int | mNewReasonDataDenied | private boolean | mGsmRoamingGSM roaming status solely based on TS 27.007 7.2 CREG. Only used by
handlePollStateResult to store CREG roaming result. | private boolean | mDataRoamingData roaming status solely based on TS 27.007 10.1.19 CGREG. Only used by
handlePollStateResult to store CGREG roaming result. | private boolean | mEmergencyOnlyMark when service state is in emergency call only mode | private boolean | mNeedFixZoneAfterNitzSometimes we get the NITZ time before we know what country we
are in. Keep the time zone information from the NITZ string so
we can fix the time zone once know the country. | private int | mZoneOffset | private boolean | mZoneDst | private long | mZoneTime | private boolean | mGotCountryCode | private android.content.ContentResolver | mCr | private boolean | mNitzUpdatedTimeBoolean is true is setTimeFromNITZString was called | String | mSavedTimeZone | long | mSavedTime | long | mSavedAtTime | private boolean | mStartedGprsRegCheckStarted the recheck process after finding gprs should registered but not. | private boolean | mReportedGprsNoRegAlready sent the event-log for no gprs register. | private android.app.Notification | mNotificationThe Notification object given to the NotificationManager. | private PowerManager.WakeLock | mWakeLockWake lock used while setting time of day. | private static final String | WAKELOCK_TAG | static final int | PS_ENABLEDNotification type. | 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_NOTIFICATIONNotification id. | static final int | CS_NOTIFICATION | private android.content.BroadcastReceiver | mIntentReceiver | private android.database.ContentObserver | mAutoTimeObserver | private android.database.ContentObserver | mAutoTimeZoneObserver |
Constructors Summary |
---|
public GsmServiceStateTracker(GSMPhone phone)
super(phone, phone.mCi, new CellInfoGsm());
mPhone = phone;
mCellLoc = new GsmCellLocation();
mNewCellLoc = new GsmCellLocation();
PowerManager powerManager =
(PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
mCi.registerForVoiceNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null);
mCi.setOnNITZTime(this, EVENT_NITZ_TIME, null);
mCi.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null);
// system setting property AIRPLANE_MODE_ON is set in Settings.
int airplaneMode = Settings.Global.getInt(
phone.getContext().getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0);
mDesiredPowerState = ! (airplaneMode > 0);
mCr = phone.getContext().getContentResolver();
mCr.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.AUTO_TIME), true,
mAutoTimeObserver);
mCr.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true,
mAutoTimeZoneObserver);
setSignalStrengthDefaultValues();
// Monitor locale change
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_LOCALE_CHANGED);
phone.getContext().registerReceiver(mIntentReceiver, filter);
filter = new IntentFilter();
Context context = phone.getContext();
filter.addAction(ACTION_RADIO_OFF);
filter.addAction(TelephonyIntents.ACTION_SET_RADIO_CAPABILITY_DONE);
context.registerReceiver(mIntentReceiver, filter);
|
Methods Summary |
---|
private boolean | currentMccEqualsSimMcc(android.telephony.ServiceState s)Compare SIM MCC with Operator MCC
String simNumeric = ((TelephonyManager) mPhone.getContext().
getSystemService(Context.TELEPHONY_SERVICE)).
getSimOperatorNumericForPhone(getPhoneId());
String operatorNumeric = s.getOperatorNumeric();
boolean equalsMcc = true;
try {
equalsMcc = simNumeric.substring(0, 3).
equals(operatorNumeric.substring(0, 3));
} catch (Exception e){
}
return equalsMcc;
| public void | dispose()
checkCorrectThread();
log("ServiceStateTracker dispose");
// Unregister for all events.
mCi.unregisterForAvailable(this);
mCi.unregisterForRadioStateChanged(this);
mCi.unregisterForVoiceNetworkStateChanged(this);
if (mUiccApplcation != null) {mUiccApplcation.unregisterForReady(this);}
if (mIccRecords != null) {mIccRecords.unregisterForRecordsLoaded(this);}
mCi.unSetOnRestrictedStateChanged(this);
mCi.unSetOnNITZTime(this);
mCr.unregisterContentObserver(mAutoTimeObserver);
mCr.unregisterContentObserver(mAutoTimeZoneObserver);
mPhone.getContext().unregisterReceiver(mIntentReceiver);
super.dispose();
| public void | dump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)
pw.println("GsmServiceStateTracker extends:");
super.dump(fd, pw, args);
pw.println(" mPhone=" + mPhone);
pw.println(" mSS=" + mSS);
pw.println(" mNewSS=" + mNewSS);
pw.println(" mCellLoc=" + mCellLoc);
pw.println(" mNewCellLoc=" + mNewCellLoc);
pw.println(" mPreferredNetworkType=" + mPreferredNetworkType);
pw.println(" mMaxDataCalls=" + mMaxDataCalls);
pw.println(" mNewMaxDataCalls=" + mNewMaxDataCalls);
pw.println(" mReasonDataDenied=" + mReasonDataDenied);
pw.println(" mNewReasonDataDenied=" + mNewReasonDataDenied);
pw.println(" mGsmRoaming=" + mGsmRoaming);
pw.println(" mDataRoaming=" + mDataRoaming);
pw.println(" mEmergencyOnly=" + mEmergencyOnly);
pw.println(" mNeedFixZoneAfterNitz=" + mNeedFixZoneAfterNitz);
pw.flush();
pw.println(" mZoneOffset=" + mZoneOffset);
pw.println(" mZoneDst=" + mZoneDst);
pw.println(" mZoneTime=" + mZoneTime);
pw.println(" mGotCountryCode=" + mGotCountryCode);
pw.println(" mNitzUpdatedTime=" + mNitzUpdatedTime);
pw.println(" mSavedTimeZone=" + mSavedTimeZone);
pw.println(" mSavedTime=" + mSavedTime);
pw.println(" mSavedAtTime=" + mSavedAtTime);
pw.println(" mStartedGprsRegCheck=" + mStartedGprsRegCheck);
pw.println(" mReportedGprsNoReg=" + mReportedGprsNoReg);
pw.println(" mNotification=" + mNotification);
pw.println(" mWakeLock=" + mWakeLock);
pw.println(" mCurSpn=" + mCurSpn);
pw.println(" mCurShowSpn=" + mCurShowSpn);
pw.println(" mCurPlmn=" + mCurPlmn);
pw.println(" mCurShowPlmn=" + mCurShowPlmn);
pw.flush();
| protected void | finalize()
if(DBG) log("finalize");
| 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.Global.getInt(mPhone.getContext().getContentResolver(),
Settings.Global.AUTO_TIME) > 0;
} catch (SettingNotFoundException snfe) {
return true;
}
| private boolean | getAutoTimeZone()
try {
return Settings.Global.getInt(mPhone.getContext().getContentResolver(),
Settings.Global.AUTO_TIME_ZONE) > 0;
} catch (SettingNotFoundException snfe) {
return true;
}
| public android.telephony.CellLocation | getCellLocation()
if ((mCellLoc.getLac() >= 0) && (mCellLoc.getCid() >= 0)) {
if (DBG) log("getCellLocation(): X good mCellLoc=" + mCellLoc);
return mCellLoc;
} else {
List<CellInfo> result = getAllCellInfo();
if (result != null) {
// A hack to allow tunneling of LTE information via GsmCellLocation
// so that older Network Location Providers can return some information
// on LTE only networks, see bug 9228974.
//
// We'll search the return CellInfo array preferring GSM/WCDMA
// data, but if there is none we'll tunnel the first LTE information
// in the list.
//
// The tunnel'd LTE information is returned as follows:
// LAC = TAC field
// CID = CI field
// PSC = 0.
GsmCellLocation cellLocOther = new GsmCellLocation();
for (CellInfo ci : result) {
if (ci instanceof CellInfoGsm) {
CellInfoGsm cellInfoGsm = (CellInfoGsm)ci;
CellIdentityGsm cellIdentityGsm = cellInfoGsm.getCellIdentity();
cellLocOther.setLacAndCid(cellIdentityGsm.getLac(),
cellIdentityGsm.getCid());
cellLocOther.setPsc(cellIdentityGsm.getPsc());
if (DBG) log("getCellLocation(): X ret GSM info=" + cellLocOther);
return cellLocOther;
} else if (ci instanceof CellInfoWcdma) {
CellInfoWcdma cellInfoWcdma = (CellInfoWcdma)ci;
CellIdentityWcdma cellIdentityWcdma = cellInfoWcdma.getCellIdentity();
cellLocOther.setLacAndCid(cellIdentityWcdma.getLac(),
cellIdentityWcdma.getCid());
cellLocOther.setPsc(cellIdentityWcdma.getPsc());
if (DBG) log("getCellLocation(): X ret WCDMA info=" + cellLocOther);
return cellLocOther;
} else if ((ci instanceof CellInfoLte) &&
((cellLocOther.getLac() < 0) || (cellLocOther.getCid() < 0))) {
// We'll return the first good LTE info we get if there is no better answer
CellInfoLte cellInfoLte = (CellInfoLte)ci;
CellIdentityLte cellIdentityLte = cellInfoLte.getCellIdentity();
if ((cellIdentityLte.getTac() != Integer.MAX_VALUE)
&& (cellIdentityLte.getCi() != Integer.MAX_VALUE)) {
cellLocOther.setLacAndCid(cellIdentityLte.getTac(),
cellIdentityLte.getCi());
cellLocOther.setPsc(0);
if (DBG) {
log("getCellLocation(): possible LTE cellLocOther=" + cellLocOther);
}
}
}
}
if (DBG) {
log("getCellLocation(): X ret best answer cellLocOther=" + cellLocOther);
}
return cellLocOther;
} else {
if (DBG) {
log("getCellLocation(): X empty mCellLoc and CellInfo mCellLoc=" + mCellLoc);
}
return mCellLoc;
}
}
| public int | getCurrentDataConnectionState()
return mSS.getDataRegState();
| 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("getNitzTimeZone returning " + (guess == null ? guess : guess.getID()));
return guess;
| protected com.android.internal.telephony.Phone | getPhone()
return mPhone;
| private com.android.internal.telephony.uicc.UiccCardApplication | getUiccCardApplication()
return mUiccController.getUiccCardApplication(mPhone.getPhoneId(),
UiccController.APP_FAM_3GPP);
| public void | handleMessage(android.os.Message msg)
AsyncResult ar;
int[] ints;
String[] strings;
Message message;
if (!mPhone.mIsTheCurrentActivePhone) {
Rlog.e(LOG_TAG, "Received message " + msg +
"[" + msg.what + "] while being destroyed. Ignoring.");
return;
}
switch (msg.what) {
case EVENT_RADIO_AVAILABLE:
//this is unnecessary
//setPowerStateToDesired();
break;
case EVENT_SIM_READY:
// Reset the mPreviousSubId so we treat a SIM power bounce
// as a first boot. See b/19194287
mOnSubscriptionsChangedListener.mPreviousSubId.set(-1);
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 (!(mCi.getRadioState().isOn())) {
// Polling will continue when radio turns back on
return;
}
ar = (AsyncResult) msg.obj;
onSignalStrengthResult(ar, true);
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) {
Rlog.w(LOG_TAG, "error parsing location: " + ex);
}
}
mCellLoc.setLacAndCid(lac, cid);
mPhone.notifyLocationChanged();
}
// Release any temporary cell lock, which could have been
// acquired to allow a single-shot location update.
disableSingleLocationUpdate();
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()
mCi.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
mDontPollSignalStrength = true;
onSignalStrengthResult(ar, true);
break;
case EVENT_SIM_RECORDS_LOADED:
log("EVENT_SIM_RECORDS_LOADED: what=" + msg.what);
// Gsm doesn't support OTASP so its not needed
mPhone.notifyOtaspChanged(OTASP_NOT_NEEDED);
updatePhoneObject();
updateSpnDisplay();
break;
case EVENT_LOCATION_UPDATES_ENABLED:
ar = (AsyncResult) msg.obj;
if (ar.exception == null) {
mCi.getVoiceRegistrationState(obtainMessage(EVENT_GET_LOC_DONE, 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);
mCi.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 = RILConstants.NETWORK_MODE_GLOBAL;
}
message = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE, ar.userObj);
int toggledNetworkType = RILConstants.NETWORK_MODE_GLOBAL;
mCi.setPreferredNetworkType(toggledNetworkType, message);
break;
case EVENT_CHECK_REPORT_GPRS:
if (mSS != null && !isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) {
// Can't register data service while voice service is ok
// i.e. CREG is ok while CGREG is not
// possible a network or baseband side error
GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
EventLog.writeEvent(EventLogTags.DATA_NETWORK_REGISTRATION_FAIL,
mSS.getOperatorNumeric(), loc != null ? loc.getCid() : -1);
mReportedGprsNoReg = true;
}
mStartedGprsRegCheck = false;
break;
case EVENT_RESTRICTED_STATE_CHANGED:
// This is a notification from
// CommandsInterface.setOnRestrictedStateChanged
if (DBG) log("EVENT_RESTRICTED_STATE_CHANGED");
ar = (AsyncResult) msg.obj;
onRestrictedStateChanged(ar);
break;
case EVENT_ALL_DATA_DISCONNECTED:
int dds = SubscriptionManager.getDefaultDataSubId();
ProxyController.getInstance().unregisterForAllDataDisconnected(dds, this);
synchronized(this) {
if (mPendingRadioPowerOffAfterDataOff) {
if (DBG) log("EVENT_ALL_DATA_DISCONNECTED, turn radio off now.");
hangupAndPowerOff();
mPendingRadioPowerOffAfterDataOff = false;
} else {
log("EVENT_ALL_DATA_DISCONNECTED is stale");
}
}
break;
case EVENT_CHANGE_IMS_STATE:
if (DBG) log("EVENT_CHANGE_IMS_STATE:");
setPowerStateToDesired();
break;
default:
super.handleMessage(msg);
break;
}
| protected 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 != mPollingContext) 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 (!mCi.getRadioState().isOn()) {
// Radio has crashed or turned off
cancelPollState();
return;
}
if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
loge("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 type = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
int regState = ServiceState.RIL_REG_STATE_UNKNOWN;
int reasonRegStateDenied = -1;
int psc = -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);
}
// states[3] (if present) is the current radio technology
if (states.length >= 4 && states[3] != null) {
type = Integer.parseInt(states[3]);
}
}
if (states.length > 14) {
if (states[14] != null && states[14].length() > 0) {
psc = Integer.parseInt(states[14], 16);
}
}
} catch (NumberFormatException ex) {
loge("error parsing RegistrationState: " + ex);
}
}
mGsmRoaming = regCodeIsRoaming(regState);
mNewSS.setState(regCodeToServiceState(regState));
mNewSS.setRilVoiceRadioTechnology(type);
boolean isVoiceCapable = mPhoneBase.getContext().getResources()
.getBoolean(com.android.internal.R.bool.config_voice_capable);
if ((regState == ServiceState.RIL_REG_STATE_DENIED_EMERGENCY_CALL_ENABLED
|| regState == ServiceState.RIL_REG_STATE_NOT_REG_EMERGENCY_CALL_ENABLED
|| regState == ServiceState.RIL_REG_STATE_SEARCHING_EMERGENCY_CALL_ENABLED
|| regState == ServiceState.RIL_REG_STATE_UNKNOWN_EMERGENCY_CALL_ENABLED)
&& isVoiceCapable) {
mEmergencyOnly = true;
} else {
mEmergencyOnly = false;
}
// LAC and CID are -1 if not avail
mNewCellLoc.setLacAndCid(lac, cid);
mNewCellLoc.setPsc(psc);
break;
}
case EVENT_POLL_STATE_GPRS: {
states = (String[])ar.result;
int type = 0;
int regState = ServiceState.RIL_REG_STATE_UNKNOWN;
mNewReasonDataDenied = -1;
mNewMaxDataCalls = 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]);
}
if ((states.length >= 5 ) &&
(regState == ServiceState.RIL_REG_STATE_DENIED)) {
mNewReasonDataDenied = Integer.parseInt(states[4]);
}
if (states.length >= 6) {
mNewMaxDataCalls = Integer.parseInt(states[5]);
}
} catch (NumberFormatException ex) {
loge("error parsing GprsRegistrationState: " + ex);
}
}
int dataRegState = regCodeToServiceState(regState);
mNewSS.setDataRegState(dataRegState);
mDataRoaming = regCodeIsRoaming(regState);
mNewSS.setRilDataRadioTechnology(type);
if (DBG) {
log("handlPollStateResultMessage: GsmSST setDataRegState=" + dataRegState
+ " regState=" + regState
+ " dataRadioTechnology=" + type);
}
break;
}
case EVENT_POLL_STATE_OPERATOR: {
String opNames[] = (String[])ar.result;
if (opNames != null && opNames.length >= 3) {
// FIXME: Giving brandOverride higher precedence, is this desired?
String brandOverride = mUiccController.getUiccCard(getPhoneId()) != null ?
mUiccController.getUiccCard(getPhoneId()).getOperatorBrandOverride() : null;
if (brandOverride != null) {
log("EVENT_POLL_STATE_OPERATOR: use brandOverride=" + brandOverride);
mNewSS.setOperatorName(brandOverride, brandOverride, opNames[2]);
} else {
mNewSS.setOperatorName (opNames[0], opNames[1], opNames[2]);
}
}
break;
}
case EVENT_POLL_STATE_NETWORK_SELECTION_MODE: {
ints = (int[])ar.result;
mNewSS.setIsManualSelection(ints[0] == 1);
if ((ints[0] == 1) && (!mPhone.isManualNetSelAllowed())) {
/*
* modem is currently in manual selection but manual
* selection is not allowed in the current mode so
* switch to automatic registration
*/
mPhone.setNetworkSelectionModeAutomatic (null);
log(" Forcing Automatic Network Selection, " +
"manual selection is not allowed");
}
break;
}
}
} catch (RuntimeException ex) {
loge("Exception while polling service state. Probably malformed RIL response." + ex);
}
mPollingContext[0]--;
if (mPollingContext[0] == 0) {
/**
* Since the roaming state of gsm service (from +CREG) and
* data service (from +CGREG) could be different, the new SS
* is set to roaming when either is true.
*
* There are exceptions for the above rule.
* The new SS is not set as roaming while gsm service reports
* roaming but indeed it is same operator.
* And the operator is considered non roaming.
*
* The test for the operators is to handle special roaming
* agreements and MVNO's.
*/
boolean roaming = (mGsmRoaming || mDataRoaming);
if (mGsmRoaming && !isOperatorConsideredRoaming(mNewSS) &&
(isSameNamedOperators(mNewSS) || isOperatorConsideredNonRoaming(mNewSS))) {
roaming = false;
}
if (mPhone.isMccMncMarkedAsNonRoaming(mNewSS.getOperatorNumeric())) {
roaming = false;
} else if (mPhone.isMccMncMarkedAsRoaming(mNewSS.getOperatorNumeric())) {
roaming = true;
}
mNewSS.setVoiceRoaming(roaming);
mNewSS.setDataRoaming(roaming);
mNewSS.setEmergencyOnly(mEmergencyOnly);
pollStateDone();
}
| protected void | hangupAndPowerOff()
// hang up all active voice calls
if (mPhone.isInCall()) {
mPhone.mCT.mRingingCall.hangupIfAlive();
mPhone.mCT.mBackgroundCall.hangupIfAlive();
mPhone.mCT.mForegroundCall.hangupIfAlive();
}
mCi.setRadioPower(false, null);
| public boolean | isConcurrentVoiceAndDataAllowed()
return (mSS.getRilVoiceRadioTechnology() >= ServiceState.RIL_RADIO_TECHNOLOGY_UMTS);
| private boolean | isGprsConsistent(int dataRegState, int voiceRegState)Check if GPRS got registered while voice is registered.
return !((voiceRegState == ServiceState.STATE_IN_SERVICE) &&
(dataRegState != ServiceState.STATE_IN_SERVICE));
| private boolean | isOperatorConsideredNonRoaming(android.telephony.ServiceState s)Do not set roaming state in case of oprators considered non-roaming.
+ Can use mcc or mcc+mnc as item of config_operatorConsideredNonRoaming.
For example, 302 or 21407. If mcc or mcc+mnc match with operator,
don't set roaming state.
String operatorNumeric = s.getOperatorNumeric();
String[] numericArray = mPhone.getContext().getResources().getStringArray(
com.android.internal.R.array.config_operatorConsideredNonRoaming);
if (numericArray.length == 0 || operatorNumeric == null) {
return false;
}
for (String numeric : numericArray) {
if (operatorNumeric.startsWith(numeric)) {
return true;
}
}
return false;
| private boolean | isOperatorConsideredRoaming(android.telephony.ServiceState s)
String operatorNumeric = s.getOperatorNumeric();
String[] numericArray = mPhone.getContext().getResources().getStringArray(
com.android.internal.R.array.config_sameNamedOperatorConsideredRoaming);
if (numericArray.length == 0 || operatorNumeric == null) {
return false;
}
for (String numeric : numericArray) {
if (operatorNumeric.startsWith(numeric)) {
return true;
}
}
return false;
| private boolean | isSameNamedOperators(android.telephony.ServiceState s)Set roaming state if operator mcc is the same as sim mcc
and ons is different from spn
String spn = ((TelephonyManager) mPhone.getContext().
getSystemService(Context.TELEPHONY_SERVICE)).
getSimOperatorNameForPhone(getPhoneId());
String onsl = s.getOperatorAlphaLong();
String onss = s.getOperatorAlphaShort();
boolean equalsOnsl = onsl != null && spn.equals(onsl);
boolean equalsOnss = onss != null && spn.equals(onss);
return currentMccEqualsSimMcc(s) && (equalsOnsl || equalsOnss);
| protected void | log(java.lang.String s)
Rlog.d(LOG_TAG, "[GsmSST] " + s);
| protected void | loge(java.lang.String s)
Rlog.e(LOG_TAG, "[GsmSST] " + s);
| 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.
RestrictedState newRs = new RestrictedState();
if (DBG) log("onRestrictedStateChanged: E rs "+ mRestrictedState);
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 (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_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);
}
if (DBG) log("onRestrictedStateChanged: new rs "+ newRs);
if (!mRestrictedState.isPsRestricted() && newRs.isPsRestricted()) {
mPsRestrictEnabledRegistrants.notifyRegistrants();
setNotification(PS_ENABLED);
} else if (mRestrictedState.isPsRestricted() && !newRs.isPsRestricted()) {
mPsRestrictDisabledRegistrants.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 (mRestrictedState.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 (mRestrictedState.isCsEmergencyRestricted() &&
!mRestrictedState.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 (!mRestrictedState.isCsEmergencyRestricted() &&
mRestrictedState.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);
}
}
mRestrictedState = newRs;
}
log("onRestrictedStateChanged: X rs "+ mRestrictedState);
| public void | onSetPhoneRCDone(java.util.ArrayList phoneRcs)
int INVALID = -1;
int size = 0;
boolean needToChangeNetworkMode = false;
RadioAccessFamily phoneRaf = null;
int myPhoneId = mPhone.getPhoneId();
int newCapability = 0;
int networkMode = INVALID;
if (phoneRcs == null) return;
size = phoneRcs.size();
for (int i = 0; i < size; i++) {
phoneRaf = phoneRcs.get(i);
if (myPhoneId == phoneRaf.getPhoneId()) {
needToChangeNetworkMode = true;
newCapability = phoneRaf.getRadioAccessFamily();
break;
}
}
if (needToChangeNetworkMode) {
if ((newCapability & RadioAccessFamily.RAF_LTE)
== RadioAccessFamily.RAF_LTE) {
networkMode = RILConstants.NETWORK_MODE_LTE_GSM_WCDMA;
} else if ((newCapability & RadioAccessFamily.RAF_UMTS)
== RadioAccessFamily.RAF_UMTS) {
networkMode = RILConstants.NETWORK_MODE_WCDMA_PREF;
} else if ((newCapability & RadioAccessFamily.RAF_GSM)
== RadioAccessFamily.RAF_GSM) {
networkMode = RILConstants.NETWORK_MODE_GSM_ONLY;
} else {
networkMode = INVALID;
log("Error: capability is not define");
}
if (DBG) log("myPhoneId=" + myPhoneId + " newCapability=" + newCapability
+ " networkMode=" + networkMode);
if (networkMode != INVALID) {
//FIXME : update preferred network mode
//TelephonyManager.putIntAtIndex(mPhone.getContext().getContentResolver(),
// Settings.Global.PREFERRED_NETWORK_MODE, myPhoneId, networkMode);
//networkMode = PhoneFactory.calculatePreferredNetworkType(mPhone.getContext());
//FIXME : update preferred network mode
mCi.setPreferredNetworkType(networkMode, null);
}
}
| protected void | onUpdateIccAvailability()
if (mUiccController == null ) {
return;
}
UiccCardApplication newUiccApplication = getUiccCardApplication();
if (mUiccApplcation != newUiccApplication) {
if (mUiccApplcation != null) {
log("Removing stale icc objects.");
mUiccApplcation.unregisterForReady(this);
if (mIccRecords != null) {
mIccRecords.unregisterForRecordsLoaded(this);
}
mIccRecords = null;
mUiccApplcation = null;
}
if (newUiccApplication != null) {
log("New card found");
mUiccApplcation = newUiccApplication;
mIccRecords = mUiccApplcation.getIccRecords();
mUiccApplcation.registerForReady(this, EVENT_SIM_READY, null);
if (mIccRecords != null) {
mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
}
}
}
| public 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
mPollingContext = new int[1];
mPollingContext[0] = 0;
switch (mCi.getRadioState()) {
case RADIO_UNAVAILABLE:
mNewSS.setStateOutOfService();
mNewCellLoc.setStateInvalid();
setSignalStrengthDefaultValues();
mGotCountryCode = false;
mNitzUpdatedTime = false;
pollStateDone();
break;
case RADIO_OFF:
mNewSS.setStateOff();
mNewCellLoc.setStateInvalid();
setSignalStrengthDefaultValues();
mGotCountryCode = false;
mNitzUpdatedTime = false;
pollStateDone();
break;
default:
// Issue all poll-related commands at once
// then count down the responses, which
// are allowed to arrive out-of-order
mPollingContext[0]++;
mCi.getOperator(
obtainMessage(
EVENT_POLL_STATE_OPERATOR, mPollingContext));
mPollingContext[0]++;
mCi.getDataRegistrationState(
obtainMessage(
EVENT_POLL_STATE_GPRS, mPollingContext));
mPollingContext[0]++;
mCi.getVoiceRegistrationState(
obtainMessage(
EVENT_POLL_STATE_REGISTRATION, mPollingContext));
mPollingContext[0]++;
mCi.getNetworkSelectionMode(
obtainMessage(
EVENT_POLL_STATE_NETWORK_SELECTION_MODE, mPollingContext));
break;
}
| private void | pollStateDone()
if (DBG) {
log("Poll ServiceState done: " +
" oldSS=[" + mSS + "] newSS=[" + mNewSS + "]" +
" oldMaxDataCalls=" + mMaxDataCalls +
" mNewMaxDataCalls=" + mNewMaxDataCalls +
" oldReasonDataDenied=" + mReasonDataDenied +
" mNewReasonDataDenied=" + mNewReasonDataDenied);
}
if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) {
mNewSS.setVoiceRoaming(true);
mNewSS.setDataRoaming(true);
}
useDataRegStateForDataOnlyDevices();
boolean hasRegistered =
mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE
&& mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE;
boolean hasDeregistered =
mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
&& mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE;
boolean hasGprsAttached =
mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE
&& mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE;
boolean hasGprsDetached =
mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE
&& mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE;
boolean hasDataRegStateChanged =
mSS.getDataRegState() != mNewSS.getDataRegState();
boolean hasVoiceRegStateChanged =
mSS.getVoiceRegState() != mNewSS.getVoiceRegState();
boolean hasRilVoiceRadioTechnologyChanged =
mSS.getRilVoiceRadioTechnology() != mNewSS.getRilVoiceRadioTechnology();
boolean hasRilDataRadioTechnologyChanged =
mSS.getRilDataRadioTechnology() != mNewSS.getRilDataRadioTechnology();
boolean hasChanged = !mNewSS.equals(mSS);
boolean hasVoiceRoamingOn = !mSS.getVoiceRoaming() && mNewSS.getVoiceRoaming();
boolean hasVoiceRoamingOff = mSS.getVoiceRoaming() && !mNewSS.getVoiceRoaming();
boolean hasDataRoamingOn = !mSS.getDataRoaming() && mNewSS.getDataRoaming();
boolean hasDataRoamingOff = mSS.getDataRoaming() && !mNewSS.getDataRoaming();
boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc);
TelephonyManager tm =
(TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
// Add an event log when connection state changes
if (hasVoiceRegStateChanged || hasDataRegStateChanged) {
EventLog.writeEvent(EventLogTags.GSM_SERVICE_STATE_CHANGE,
mSS.getVoiceRegState(), mSS.getDataRegState(),
mNewSS.getVoiceRegState(), mNewSS.getDataRegState());
}
// Add an event log when network type switched
// TODO: we may add filtering to reduce the event logged,
// i.e. check preferred network setting, only switch to 2G, etc
if (hasRilVoiceRadioTechnologyChanged) {
int cid = -1;
GsmCellLocation loc = mNewCellLoc;
if (loc != null) cid = loc.getCid();
// NOTE: this code was previously located after mSS and mNewSS are swapped, so
// existing logs were incorrectly using the new state for "network_from"
// and STATE_OUT_OF_SERVICE for "network_to". To avoid confusion, use a new log tag
// to record the correct states.
EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED_NEW, cid,
mSS.getRilVoiceRadioTechnology(),
mNewSS.getRilVoiceRadioTechnology());
if (DBG) {
log("RAT switched "
+ ServiceState.rilRadioTechnologyToString(mSS.getRilVoiceRadioTechnology())
+ " -> "
+ ServiceState.rilRadioTechnologyToString(
mNewSS.getRilVoiceRadioTechnology()) + " at cell " + cid);
}
}
// swap mSS and mNewSS to put new state in mSS
ServiceState tss = mSS;
mSS = mNewSS;
mNewSS = tss;
// clean slate for next time
mNewSS.setStateOutOfService();
// swap mCellLoc and mNewCellLoc to put new state in mCellLoc
GsmCellLocation tcl = mCellLoc;
mCellLoc = mNewCellLoc;
mNewCellLoc = tcl;
mReasonDataDenied = mNewReasonDataDenied;
mMaxDataCalls = mNewMaxDataCalls;
if (hasRilVoiceRadioTechnologyChanged) {
updatePhoneObject();
}
if (hasRilDataRadioTechnologyChanged) {
tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), mSS.getRilVoiceRadioTechnology());
}
if (hasRegistered) {
mNetworkAttachedRegistrants.notifyRegistrants();
if (DBG) {
log("pollStateDone: registering current mNitzUpdatedTime=" +
mNitzUpdatedTime + " changing to false");
}
mNitzUpdatedTime = false;
}
if (hasChanged) {
String operatorNumeric;
updateSpnDisplay();
tm.setNetworkOperatorNameForPhone(mPhone.getPhoneId(), mSS.getOperatorAlphaLong());
String prevOperatorNumeric = tm.getNetworkOperatorForPhone(mPhone.getPhoneId());
operatorNumeric = mSS.getOperatorNumeric();
tm.setNetworkOperatorNumericForPhone(mPhone.getPhoneId(), operatorNumeric);
updateCarrierMccMncConfiguration(operatorNumeric,
prevOperatorNumeric, mPhone.getContext());
if (operatorNumeric == null) {
if (DBG) log("operatorNumeric is null");
tm.setNetworkCountryIsoForPhone(mPhone.getPhoneId(), "");
mGotCountryCode = false;
mNitzUpdatedTime = false;
} else {
String iso = "";
String mcc = "";
try{
mcc = operatorNumeric.substring(0, 3);
iso = MccTable.countryCodeForMcc(Integer.parseInt(mcc));
} catch ( NumberFormatException ex){
loge("pollStateDone: countryCodeForMcc error" + ex);
} catch ( StringIndexOutOfBoundsException ex) {
loge("pollStateDone: countryCodeForMcc error" + ex);
}
tm.setNetworkCountryIsoForPhone(mPhone.getPhoneId(), iso);
mGotCountryCode = true;
TimeZone zone = null;
if (!mNitzUpdatedTime && !mcc.equals("000") && !TextUtils.isEmpty(iso) &&
getAutoTimeZone()) {
// Test both paths if ignore nitz is true
boolean testOneUniqueOffsetPath = SystemProperties.getBoolean(
TelephonyProperties.PROPERTY_IGNORE_NITZ, false) &&
((SystemClock.uptimeMillis() & 1) == 0);
ArrayList<TimeZone> uniqueZones = TimeUtils.getTimeZonesWithUniqueOffsets(iso);
if ((uniqueZones.size() == 1) || testOneUniqueOffsetPath) {
zone = uniqueZones.get(0);
if (DBG) {
log("pollStateDone: no nitz but one TZ for iso-cc=" + iso +
" with zone.getID=" + zone.getID() +
" testOneUniqueOffsetPath=" + testOneUniqueOffsetPath);
}
setAndBroadcastNetworkSetTimeZone(zone.getID());
} else {
if (DBG) {
log("pollStateDone: there are " + uniqueZones.size() +
" unique offsets for iso-cc='" + iso +
" testOneUniqueOffsetPath=" + testOneUniqueOffsetPath +
"', do nothing");
}
}
}
if (shouldFixTimeZoneNow(mPhone, operatorNumeric, prevOperatorNumeric,
mNeedFixZoneAfterNitz)) {
// 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 (DBG) {
log("pollStateDone: fix time zone zoneName='" + zoneName +
"' mZoneOffset=" + mZoneOffset + " mZoneDst=" + mZoneDst +
" iso-cc='" + iso +
"' iso-cc-idx=" + Arrays.binarySearch(GMT_COUNTRY_CODES, iso));
}
if ("".equals(iso) && mNeedFixZoneAfterNitz) {
// 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);
if (DBG) log("pollStateDone: using NITZ TimeZone");
} else
// "(mZoneOffset == 0) && (mZoneDst == false) &&
// (Arrays.binarySearch(GMT_COUNTRY_CODES, iso) < 0)"
// means that we received a NITZ string telling
// it is in GMT+0 w/ DST time zone
// BUT iso tells is NOT, e.g, a wrong NITZ reporting
// local time w/ 0 offset.
if ((mZoneOffset == 0) && (mZoneDst == false) &&
(zoneName != null) && (zoneName.length() > 0) &&
(Arrays.binarySearch(GMT_COUNTRY_CODES, iso) < 0)) {
zone = TimeZone.getDefault();
if (mNeedFixZoneAfterNitz) {
// For wrong NITZ reporting local time w/ 0 offset,
// need adjust time to reflect default timezone setting
long ctm = System.currentTimeMillis();
long tzOffset = zone.getOffset(ctm);
if (DBG) {
log("pollStateDone: tzOffset=" + tzOffset + " ltod=" +
TimeUtils.logTimeOfDay(ctm));
}
if (getAutoTime()) {
long adj = ctm - tzOffset;
if (DBG) log("pollStateDone: adj ltod=" +
TimeUtils.logTimeOfDay(adj));
setAndBroadcastNetworkSetTime(adj);
} else {
// Adjust the saved NITZ time to account for tzOffset.
mSavedTime = mSavedTime - tzOffset;
}
}
if (DBG) log("pollStateDone: using default TimeZone");
} else {
zone = TimeUtils.getTimeZone(mZoneOffset, mZoneDst, mZoneTime, iso);
if (DBG) log("pollStateDone: using getTimeZone(off, dst, time, iso)");
}
mNeedFixZoneAfterNitz = false;
if (zone != null) {
log("pollStateDone: zone != null zone.getID=" + zone.getID());
if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
} else {
log("pollStateDone: zone == null");
}
}
}
tm.setNetworkRoamingForPhone(mPhone.getPhoneId(), mSS.getVoiceRoaming());
setRoamingType(mSS);
log("Broadcasting ServiceState : " + mSS);
mPhone.notifyServiceStateChanged(mSS);
}
if (hasGprsAttached) {
mAttachedRegistrants.notifyRegistrants();
}
if (hasGprsDetached) {
mDetachedRegistrants.notifyRegistrants();
}
if (hasDataRegStateChanged || hasRilDataRadioTechnologyChanged) {
notifyDataRegStateRilRadioTechnologyChanged();
mPhone.notifyDataConnection(null);
}
if (hasVoiceRoamingOn) {
mVoiceRoamingOnRegistrants.notifyRegistrants();
}
if (hasVoiceRoamingOff) {
mVoiceRoamingOffRegistrants.notifyRegistrants();
}
if (hasDataRoamingOn) {
mDataRoamingOnRegistrants.notifyRegistrants();
}
if (hasDataRoamingOff) {
mDataRoamingOffRegistrants.notifyRegistrants();
}
if (hasLocationChanged) {
mPhone.notifyLocationChanged();
}
if (! isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) {
if (!mStartedGprsRegCheck && !mReportedGprsNoReg) {
mStartedGprsRegCheck = true;
int check_period = Settings.Global.getInt(
mPhone.getContext().getContentResolver(),
Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS,
DEFAULT_GPRS_CHECK_PERIOD_MILLIS);
sendMessageDelayed(obtainMessage(EVENT_CHECK_REPORT_GPRS),
check_period);
}
} else {
mReportedGprsNoReg = false;
}
// TODO: Add GsmCellIdenity updating, see CdmaLteServiceStateTracker.
| public void | powerOffRadioSafely(com.android.internal.telephony.dataconnection.DcTrackerBase dcTracker)Clean up existing voice and data connection then turn off radio power.
Hang up the existing voice calls to decrease call drop rate.
synchronized (this) {
if (!mPendingRadioPowerOffAfterDataOff) {
int dds = SubscriptionManager.getDefaultDataSubId();
// To minimize race conditions we call cleanUpAllConnections on
// both if else paths instead of before this isDisconnected test.
if (dcTracker.isDisconnected()
&& (dds == mPhone.getSubId()
|| (dds != mPhone.getSubId()
&& ProxyController.getInstance().isDataDisconnected(dds)))) {
// To minimize race conditions we do this after isDisconnected
dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
if (DBG) log("Data disconnected, turn off radio right away.");
hangupAndPowerOff();
} else {
// hang up all active voice calls first
if (mPhone.isInCall()) {
mPhone.mCT.mRingingCall.hangupIfAlive();
mPhone.mCT.mBackgroundCall.hangupIfAlive();
mPhone.mCT.mForegroundCall.hangupIfAlive();
}
dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
if (dds != mPhone.getSubId()
&& !ProxyController.getInstance().isDataDisconnected(dds)) {
if (DBG) log("Data is active on DDS. Wait for all data disconnect");
// Data is not disconnected on DDS. Wait for the data disconnect complete
// before sending the RADIO_POWER off.
ProxyController.getInstance().registerForAllDataDisconnected(dds, this,
EVENT_ALL_DATA_DISCONNECTED, null);
mPendingRadioPowerOffAfterDataOff = true;
}
Message msg = Message.obtain(this);
msg.what = EVENT_SET_RADIO_POWER_OFF;
msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag;
if (sendMessageDelayed(msg, 30000)) {
if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio.");
mPendingRadioPowerOffAfterDataOff = true;
} else {
log("Cannot send delayed Msg, turn off radio right away.");
hangupAndPowerOff();
mPendingRadioPowerOffAfterDataOff = false;
}
}
}
}
| private void | queueNextSignalStrengthPoll()
if (mDontPollSignalStrength) {
// 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 Don't poll signal strength if screen is off
sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
| private boolean | regCodeIsRoaming(int code)code is registration state 0-5 from TS 27.007 7.2
returns true if registered roam, false otherwise
return ServiceState.RIL_REG_STATE_ROAMING == 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
case 10:// same as 0, but indicates that emergency call is possible.
case 12:// same as 2, but indicates that emergency call is possible.
case 13:// same as 3, but indicates that emergency call is possible.
case 14:// same as 4, but indicates that emergency call is possible.
return ServiceState.STATE_OUT_OF_SERVICE;
case 1:
return ServiceState.STATE_IN_SERVICE;
case 5:
// in service, roam
return ServiceState.STATE_IN_SERVICE;
default:
loge("regCodeToServiceState: unexpected service state " + code);
return ServiceState.STATE_OUT_OF_SERVICE;
}
| private void | revertToNitzTime()
if (Settings.Global.getInt(mPhone.getContext().getContentResolver(),
Settings.Global.AUTO_TIME, 0) == 0) {
return;
}
if (DBG) {
log("Reverting to NITZ Time: mSavedTime=" + mSavedTime
+ " mSavedAtTime=" + mSavedAtTime);
}
if (mSavedTime != 0 && mSavedAtTime != 0) {
setAndBroadcastNetworkSetTime(mSavedTime
+ (SystemClock.elapsedRealtime() - mSavedAtTime));
}
| private void | revertToNitzTimeZone()
if (Settings.Global.getInt(mPhone.getContext().getContentResolver(),
Settings.Global.AUTO_TIME_ZONE, 0) == 0) {
return;
}
if (DBG) log("Reverting to NITZ TimeZone: tz='" + mSavedTimeZone);
if (mSavedTimeZone != null) {
setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
}
| 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.
if (DBG) log("setAndBroadcastNetworkSetTime: time=" + time + "ms");
SystemClock.setCurrentTimeMillis(time);
Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra("time", time);
mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
| 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.
if (DBG) log("setAndBroadcastNetworkSetTimeZone: setTimeZone=" + zoneId);
AlarmManager alarm =
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
alarm.setTimeZone(zoneId);
Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra("time-zone", zoneId);
mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
if (DBG) {
log("setAndBroadcastNetworkSetTimeZone: call alarm.setTimeZone and broadcast zoneId=" +
zoneId);
}
| public void | setImsRegistrationState(boolean registered)
if (mImsRegistrationOnOff && !registered) {
if (mAlarmSwitch) {
mImsRegistrationOnOff = registered;
Context context = mPhone.getContext();
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.cancel(mRadioOffIntent);
mAlarmSwitch = false;
sendMessage(obtainMessage(EVENT_CHANGE_IMS_STATE));
return;
}
}
mImsRegistrationOnOff = registered;
| private void | setNotification(int notifyType)Post a notification to NotificationManager for restricted state
if (DBG) log("setNotification: create notification " + notifyType);
// Needed because sprout RIL sends these when they shouldn't?
boolean isSetNotification = mPhone.getContext().getResources().getBoolean(
com.android.internal.R.bool.config_user_notification_of_restrictied_mobile_access);
if (!isSetNotification) {
if (DBG) log("Ignore all the notifications");
return;
}
Context context = mPhone.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:
long dataSubId = SubscriptionManager.getDefaultDataSubId();
if (dataSubId != mPhone.getSubId()) {
return;
}
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.RestrictedOnAllVoice);
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;
}
if (DBG) log("setNotification: put notification " + title + " / " +details);
mNotification.tickerText = title;
mNotification.color = context.getResources().getColor(
com.android.internal.R.color.system_notification_accent_color);
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);
}
| protected void | setPowerStateToDesired()
if (DBG) {
log("mDeviceShuttingDown = " + mDeviceShuttingDown);
log("mDesiredPowerState = " + mDesiredPowerState);
log("getRadioState = " + mCi.getRadioState());
log("mPowerOffDelayNeed = " + mPowerOffDelayNeed);
log("mAlarmSwitch = " + mAlarmSwitch);
}
if (mAlarmSwitch) {
if(DBG) log("mAlarmSwitch == true");
Context context = mPhone.getContext();
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.cancel(mRadioOffIntent);
mAlarmSwitch = false;
}
// If we want it on and it's off, turn it on
if (mDesiredPowerState
&& mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
mCi.setRadioPower(true, null);
} else if (!mDesiredPowerState && mCi.getRadioState().isOn()) {
// If it's on and available and we want it off gracefully
if (mPowerOffDelayNeed) {
if (mImsRegistrationOnOff && !mAlarmSwitch) {
if(DBG) log("mImsRegistrationOnOff == true");
Context context = mPhone.getContext();
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ACTION_RADIO_OFF);
mRadioOffIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
mAlarmSwitch = true;
if (DBG) log("Alarm setting");
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 3000, mRadioOffIntent);
} else {
DcTrackerBase dcTracker = mPhone.mDcTracker;
powerOffRadioSafely(dcTracker);
}
} else {
DcTrackerBase dcTracker = mPhone.mDcTracker;
powerOffRadioSafely(dcTracker);
}
} else if (mDeviceShuttingDown && mCi.getRadioState().isAvailable()) {
mCi.requestShutdown(null);
}
| protected void | setRoamingType(android.telephony.ServiceState currentServiceState)Set both voice and data roaming type,
judging from the ISO country of SIM VS network.
final boolean isVoiceInService =
(currentServiceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE);
if (isVoiceInService) {
if (currentServiceState.getVoiceRoaming()) {
// check roaming type by MCC
if (inSameCountry(currentServiceState.getVoiceOperatorNumeric())) {
currentServiceState.setVoiceRoamingType(
ServiceState.ROAMING_TYPE_DOMESTIC);
} else {
currentServiceState.setVoiceRoamingType(
ServiceState.ROAMING_TYPE_INTERNATIONAL);
}
} else {
currentServiceState.setVoiceRoamingType(ServiceState.ROAMING_TYPE_NOT_ROAMING);
}
}
final boolean isDataInService =
(currentServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE);
final int dataRegType = currentServiceState.getRilDataRadioTechnology();
if (isDataInService) {
if (!currentServiceState.getDataRoaming()) {
currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_NOT_ROAMING);
} else if (ServiceState.isGsm(dataRegType)) {
if (isVoiceInService) {
// GSM data should have the same state as voice
currentServiceState.setDataRoamingType(currentServiceState
.getVoiceRoamingType());
} else {
// we can not decide GSM data roaming type without voice
currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN);
}
} else {
// we can not decide 3gpp2 roaming state here
currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN);
}
}
| private void | setSignalStrengthDefaultValues()
mSignalStrength = new SignalStrength(true);
| 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();
if (DBG) {log("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 = ((TelephonyManager) mPhone.getContext().
getSystemService(Context.TELEPHONY_SERVICE)).
getNetworkCountryIsoForPhone(mPhone.getPhoneId());
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) || (mZoneOffset != tzOffset) || (mZoneDst != (dst != 0))){
// We got the time before the country or the zone has changed
// so we don't know how to identify the DST rules yet. Save
// the information and hope to fix it up later.
mNeedFixZoneAfterNitz = true;
mZoneOffset = tzOffset;
mZoneDst = dst != 0;
mZoneTime = c.getTimeInMillis();
}
if (zone != null) {
if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
}
String ignore = SystemProperties.get("gsm.ignore-nitz");
if (ignore != null && ignore.equals("yes")) {
log("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
if (DBG) {
log("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!
if (DBG) {
log("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);
if (DBG) {
log("NITZ: Setting time of day to " + c.getTime()
+ " NITZ receive delay(ms): " + millisSinceNitzReceived
+ " gained(ms): "
+ (c.getTimeInMillis() - System.currentTimeMillis())
+ " from " + nitz);
}
setAndBroadcastNetworkSetTime(c.getTimeInMillis());
Rlog.i(LOG_TAG, "NITZ: after Setting time of day");
}
SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
saveNitzTime(c.getTimeInMillis());
if (VDBG) {
long end = SystemClock.elapsedRealtime();
log("NITZ: end=" + end + " dur=" + (end - start));
}
mNitzUpdatedTime = true;
} finally {
mWakeLock.release();
}
} catch (RuntimeException ex) {
loge("NITZ: Parsing NITZ time " + nitz + " ex=" + ex);
}
| protected void | updateSpnDisplay()
// The values of plmn/showPlmn change in different scenarios.
// 1) No service but emergency call allowed -> expected
// to show "Emergency call only"
// EXTRA_SHOW_PLMN = true
// EXTRA_PLMN = "Emergency call only"
// 2) No service at all --> expected to show "No service"
// EXTRA_SHOW_PLMN = true
// EXTRA_PLMN = "No service"
// 3) Normal operation in either home or roaming service
// EXTRA_SHOW_PLMN = depending on IccRecords rule
// EXTRA_PLMN = plmn
// 4) No service due to power off, aka airplane mode
// EXTRA_SHOW_PLMN = false
// EXTRA_PLMN = null
IccRecords iccRecords = mIccRecords;
String plmn = null;
boolean showPlmn = false;
int rule = (iccRecords != null) ? iccRecords.getDisplayRule(mSS.getOperatorNumeric()) : 0;
if (mSS.getVoiceRegState() == ServiceState.STATE_OUT_OF_SERVICE
|| mSS.getVoiceRegState() == ServiceState.STATE_EMERGENCY_ONLY) {
showPlmn = true;
if (mEmergencyOnly) {
// No service but emergency call allowed
plmn = Resources.getSystem().
getText(com.android.internal.R.string.emergency_calls_only).toString();
} else {
// No service at all
plmn = Resources.getSystem().
getText(com.android.internal.R.string.lockscreen_carrier_default).toString();
}
if (DBG) log("updateSpnDisplay: radio is on but out " +
"of service, set plmn='" + plmn + "'");
} else if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
// In either home or roaming service
plmn = mSS.getOperatorAlphaLong();
showPlmn = !TextUtils.isEmpty(plmn) &&
((rule & SIMRecords.SPN_RULE_SHOW_PLMN)
== SIMRecords.SPN_RULE_SHOW_PLMN);
} else {
// Power off state, such as airplane mode, show plmn as "No service"
showPlmn = true;
plmn = Resources.getSystem().
getText(com.android.internal.R.string.lockscreen_carrier_default).toString();
if (DBG) log("updateSpnDisplay: radio is off w/ showPlmn="
+ showPlmn + " plmn=" + plmn);
}
// The value of spn/showSpn are same in different scenarios.
// EXTRA_SHOW_SPN = depending on IccRecords rule
// EXTRA_SPN = spn
String spn = (iccRecords != null) ? iccRecords.getServiceProviderName() : "";
boolean showSpn = !TextUtils.isEmpty(spn)
&& ((rule & SIMRecords.SPN_RULE_SHOW_SPN)
== SIMRecords.SPN_RULE_SHOW_SPN);
// airplane mode or spn equals plmn, do not show spn
if (mSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF
|| (showPlmn && TextUtils.equals(spn, plmn))) {
spn = null;
showSpn = false;
}
// Update SPN_STRINGS_UPDATED_ACTION IFF any value changes
if (showPlmn != mCurShowPlmn
|| showSpn != mCurShowSpn
|| !TextUtils.equals(spn, mCurSpn)
|| !TextUtils.equals(plmn, mCurPlmn)) {
if (DBG) {
log(String.format("updateSpnDisplay: changed" +
" sending intent rule=" + rule +
" showPlmn='%b' plmn='%s' showSpn='%b' spn='%s'",
showPlmn, plmn, showSpn, spn));
}
Intent intent = new Intent(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(TelephonyIntents.EXTRA_SHOW_SPN, showSpn);
intent.putExtra(TelephonyIntents.EXTRA_SPN, spn);
intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn);
intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn);
SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
if (!mSubscriptionController.setPlmnSpn(mPhone.getPhoneId(),
showPlmn, plmn, showSpn, spn)) {
mSpnUpdatePending = true;
}
}
mCurShowSpn = showSpn;
mCurShowPlmn = showPlmn;
mCurSpn = spn;
mCurPlmn = plmn;
|
|