Merge changes Ia8496a8d,Ic011551f,I13ff9bb0
* changes:
In PhoneFactory, dynamically allocate 2nd phone when switching to dsds
Have UiccController compitible with dynamicy ss <-> ds switch
Update ProxyController to be compatible with dynamic ss <-> ds switch
diff --git a/src/java/com/android/internal/telephony/Connection.java b/src/java/com/android/internal/telephony/Connection.java
index ede22e1..6cc9e63 100755
--- a/src/java/com/android/internal/telephony/Connection.java
+++ b/src/java/com/android/internal/telephony/Connection.java
@@ -20,6 +20,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.DisconnectCause;
import android.telephony.Rlog;
import android.telephony.ServiceState;
@@ -94,7 +95,7 @@
public interface Listener {
public void onVideoStateChanged(int videoState);
public void onConnectionCapabilitiesChanged(int capability);
- public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat);
+ public void onCallRadioTechChanged(@RilRadioTechnology int vrat);
public void onVideoProviderChanged(
android.telecom.Connection.VideoProvider videoProvider);
public void onAudioQualityChanged(int audioQuality);
@@ -125,7 +126,7 @@
@Override
public void onConnectionCapabilitiesChanged(int capability) {}
@Override
- public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat) {}
+ public void onCallRadioTechChanged(@RilRadioTechnology int vrat) {}
@Override
public void onVideoProviderChanged(
android.telecom.Connection.VideoProvider videoProvider) {}
@@ -227,7 +228,7 @@
*
* This is used to propagate the call radio technology to upper layer.
*/
- private @ServiceState.RilRadioTechnology int mCallRadioTech =
+ private @RilRadioTechnology int mCallRadioTech =
ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
private boolean mAudioModeIsVoip;
private int mAudioQuality;
@@ -902,7 +903,7 @@
* @return the RIL Voice Radio Technology used for current connection,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public @ServiceState.RilRadioTechnology int getCallRadioTech() {
+ public @RilRadioTechnology int getCallRadioTech() {
return mCallRadioTech;
}
@@ -980,7 +981,7 @@
* @param vrat the RIL voice radio technology for current connection,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+ public void setCallRadioTech(@RilRadioTechnology int vrat) {
if (mCallRadioTech == vrat) {
return;
}
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 1bbcd5e..6a22715 100755
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -30,6 +30,7 @@
import android.os.RegistrantList;
import android.os.SystemProperties;
import android.telecom.TelecomManager;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.CarrierConfigManager;
import android.telephony.CellLocation;
import android.telephony.DisconnectCause;
@@ -1654,7 +1655,7 @@
* @param vrat the RIL voice radio technology for CS calls,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public void dispatchCsCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+ public void dispatchCsCallRadioTech(@RilRadioTechnology int vrat) {
if (mConnections == null) {
log("dispatchCsCallRadioTech: mConnections is null");
return;
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 82bb78b..a2ee834 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -58,6 +58,7 @@
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.telephony.AccessNetworkConstants;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.CarrierConfigManager;
import android.telephony.CellLocation;
import android.telephony.ImsiEncryptionInfo;
@@ -947,27 +948,27 @@
/**
* ImsService reports "IN_SERVICE" for its voice registration state even if the device
* has lost the physical link to the tower. This helper method merges the IMS and modem
- * ServiceState, only overriding the voice registration state when we are registered to IMS over
- * IWLAN. In this case the voice registration state will always be "OUT_OF_SERVICE", so override
- * the voice registration state with the data registration state.
+ * ServiceState, only overriding the voice registration state when we are registered to IMS. In
+ * this case the voice registration state may be "OUT_OF_SERVICE", so override the voice
+ * registration state with the data registration state.
*/
private ServiceState mergeServiceStates(ServiceState baseSs, ServiceState imsSs) {
+ // No need to merge states if the baseSs is IN_SERVICE.
+ if (baseSs.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
+ return baseSs;
+ }
// "IN_SERVICE" in this case means IMS is registered.
if (imsSs.getVoiceRegState() != ServiceState.STATE_IN_SERVICE) {
return baseSs;
}
- if (imsSs.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) {
- ServiceState newSs = new ServiceState(baseSs);
- // Voice override for IWLAN. In this case, voice registration is OUT_OF_SERVICE, but
- // the data RAT is IWLAN, so use that as a basis for determining whether or not the
- // physical link is available.
- newSs.setVoiceRegState(baseSs.getDataRegState());
- newSs.setEmergencyOnly(false); // only get here if voice is IN_SERVICE
- return newSs;
- }
-
- return baseSs;
+ ServiceState newSs = new ServiceState(baseSs);
+ // Voice override for IMS case. In this case, voice registration is OUT_OF_SERVICE, but
+ // IMS is available, so use data registration state as a basis for determining
+ // whether or not the physical link is available.
+ newSs.setVoiceRegState(baseSs.getDataRegState());
+ newSs.setEmergencyOnly(false); // only get here if voice is IN_SERVICE
+ return newSs;
}
private boolean handleCallDeflectionIncallSupplementaryService(
@@ -3839,7 +3840,7 @@
* @return the RIL voice radio technology used for CS calls,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public @ServiceState.RilRadioTechnology int getCsCallRadioTech() {
+ public @RilRadioTechnology int getCsCallRadioTech() {
int calcVrat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
if (mSST != null) {
calcVrat = getCsCallRadioTech(mSST.mSS.getVoiceRegState(),
@@ -3868,7 +3869,7 @@
* @return the RIL voice radio technology used for CS calls,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- private @ServiceState.RilRadioTechnology int getCsCallRadioTech(int vrs, int vrat) {
+ private @RilRadioTechnology int getCsCallRadioTech(int vrs, int vrat) {
logd("getCsCallRadioTech, current vrs=" + vrs + ", vrat=" + vrat);
int calcVrat = vrat;
if (vrs != ServiceState.STATE_IN_SERVICE
diff --git a/src/java/com/android/internal/telephony/NitzStateMachineImpl.java b/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
index d479b20..2fec367 100644
--- a/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
+++ b/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
@@ -267,6 +267,8 @@
logMsg += " [Not setting device time zone (zoneId == null)]";
Rlog.d(LOG_TAG, logMsg);
}
+ mSavedTimeZoneId = null;
+ mNitzTimeZoneDetectionSuccessful = false;
}
} catch (RuntimeException ex) {
Rlog.e(LOG_TAG, "updateTimeZoneFromCountryAndNitz: Processing NITZ data"
@@ -584,6 +586,7 @@
+ " iso=" + iso
+ " lookupResult=" + lookupResult);
}
+ mSavedTimeZoneId = null;
}
}
@@ -596,4 +599,9 @@
public NitzData getCachedNitzData() {
return mLatestNitzSignal != null ? mLatestNitzSignal.getValue() : null;
}
+
+ // VisibleForTesting
+ public String getSavedTimeZoneId() {
+ return mSavedTimeZoneId;
+ }
}
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index fd22e77..fd92404 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -2362,6 +2362,15 @@
mCi.nvResetConfig(3 /* factory NV reset */, response);
}
+ /**
+ * Perform modem configuration erase. Used for network reset
+ *
+ * @param response Callback message.
+ */
+ public void eraseModemConfig(Message response) {
+ mCi.nvResetConfig(2 /* erase NV */, response);
+ }
+
public void notifyDataActivity() {
mNotifier.notifyDataActivity(this);
}
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index 0162bbe..363e8ff 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -76,7 +76,7 @@
public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int subId, int keyType,
String callingPackage) {
- return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage,
+ return callPhoneMethodForSubIdWithPrivilegedCheck(subId,
"getCarrierInfoForImsiEncryption",
(phone)-> phone.getCarrierInfoForImsiEncryption(keyType));
}
@@ -100,14 +100,13 @@
*/
public void resetCarrierKeysForImsiEncryption(int subId, String callingPackage) {
callPhoneMethodForSubIdWithModifyCheck(subId, callingPackage,
- "setCarrierInfoForImsiEncryption",
+ "resetCarrierKeysForImsiEncryption",
(phone)-> {
phone.resetCarrierKeysForImsiEncryption();
return null;
});
}
-
public String getDeviceSvn(String callingPackage) {
return getDeviceSvnUsingSubId(getDefaultSubscription(), callingPackage);
}
@@ -431,7 +430,6 @@
aContext, aSubId, aCallingPackage, aMessage));
}
-
private <T> T callPhoneMethodForSubIdWithPrivilegedCheck(
int subId, String message, CallPhoneMethodHelper<T> callMethodHelper) {
return callPhoneMethodWithPermissionCheck(subId, null, message, callMethodHelper,
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 10e35f2..b8b1347 100755
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -57,6 +57,7 @@
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.AccessNetworkConstants.TransportType;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.CarrierConfigManager;
import android.telephony.CellIdentity;
import android.telephony.CellIdentityCdma;
@@ -71,7 +72,6 @@
import android.telephony.PhysicalChannelConfig;
import android.telephony.Rlog;
import android.telephony.ServiceState;
-import android.telephony.ServiceState.RilRadioTechnology;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
diff --git a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
index d73c900..a26b561 100644
--- a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
@@ -16,7 +16,6 @@
package com.android.internal.telephony.dataconnection;
-import android.app.PendingIntent;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkConfig;
@@ -68,8 +67,6 @@
String mReason;
- PendingIntent mReconnectAlarmIntent;
-
/**
* user/app requested connection on this APN
*/
@@ -170,22 +167,6 @@
}
/**
- * Get the reconnect intent.
- * @return The reconnect intent
- */
- public synchronized PendingIntent getReconnectIntent() {
- return mReconnectAlarmIntent;
- }
-
- /**
- * Save the reconnect intent which can be used for cancelling later.
- * @param intent The reconnect intent
- */
- public synchronized void setReconnectIntent(PendingIntent intent) {
- mReconnectAlarmIntent = intent;
- }
-
- /**
* Get the current APN setting.
* @return APN setting
*/
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 53337fd..e151c7c 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -1329,6 +1329,16 @@
return result;
}
+ /** @return {@code true} if validation is required, {@code false} otherwise. */
+ public boolean isValidationRequired() {
+ final NetworkCapabilities nc = getNetworkCapabilities();
+ return nc != null
+ && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
+ }
+
/**
* @return {@code True} if 464xlat should be skipped.
*/
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
index 381bc6e..ae773bb 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
@@ -187,7 +187,7 @@
DcTracker dct = mPhone.getDcTracker(mTransportType);
if (dct != null) {
Message msg = dct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- status, 0, redirectUrl);
+ status, mDataConnection.getCid(), redirectUrl);
msg.sendToTarget();
}
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index d1c37cb..c30b6eb 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -66,9 +66,10 @@
import android.provider.Telephony;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.TransportType;
-import android.telephony.Annotation.DataFailureCause;
import android.telephony.Annotation.ApnType;
+import android.telephony.Annotation.DataFailureCause;
import android.telephony.Annotation.NetworkType;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.CarrierConfigManager;
import android.telephony.CellLocation;
import android.telephony.DataFailCause;
@@ -76,7 +77,6 @@
import android.telephony.PcoData;
import android.telephony.Rlog;
import android.telephony.ServiceState;
-import android.telephony.ServiceState.RilRadioTechnology;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
@@ -254,14 +254,6 @@
private static final boolean DATA_STALL_SUSPECTED = true;
private static final boolean DATA_STALL_NOT_SUSPECTED = false;
- private static final String INTENT_RECONNECT_ALARM =
- "com.android.internal.telephony.data-reconnect";
- private static final String INTENT_RECONNECT_ALARM_EXTRA_TYPE = "reconnect_alarm_extra_type";
- private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON =
- "reconnect_alarm_extra_reason";
- private static final String INTENT_RECONNECT_ALARM_EXTRA_TRANSPORT_TYPE =
- "reconnect_alarm_extra_transport_type";
-
private static final String INTENT_DATA_STALL_ALARM =
"com.android.internal.telephony.data-stall";
// Tag for tracking stale alarms
@@ -358,8 +350,6 @@
stopNetStatPoll();
startNetStatPoll();
restartDataStallAlarm();
- } else if (action.startsWith(INTENT_RECONNECT_ALARM)) {
- onActionIntentReconnectAlarm(intent);
} else if (action.equals(INTENT_DATA_STALL_ALARM)) {
onActionIntentDataStallAlarm(intent);
} else if (action.equals(INTENT_PROVISIONING_APN_ALARM)) {
@@ -491,28 +481,13 @@
}
}
- private void onActionIntentReconnectAlarm(Intent intent) {
- Message msg = obtainMessage(DctConstants.EVENT_DATA_RECONNECT);
- msg.setData(intent.getExtras());
- sendMessage(msg);
- }
-
- private void onDataReconnect(Bundle bundle) {
- String reason = bundle.getString(INTENT_RECONNECT_ALARM_EXTRA_REASON);
- String apnType = bundle.getString(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
-
+ private void onDataReconnect(ApnContext apnContextforRetry, int subId) {
int phoneSubId = mPhone.getSubId();
- int currSubId = bundle.getInt(PhoneConstants.SUBSCRIPTION_KEY,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ String apnType = apnContextforRetry.getApnType();
+ String reason = apnContextforRetry.getReason();
- // Stop reconnect if not current subId is not correct.
- // FIXME STOPSHIP - phoneSubId is coming up as -1 way after boot and failing this?
- if (!SubscriptionManager.isValidSubscriptionId(currSubId) || (currSubId != phoneSubId)) {
- return;
- }
-
- int transportType = bundle.getInt(INTENT_RECONNECT_ALARM_EXTRA_TRANSPORT_TYPE, 0);
- if (transportType != mTransportType) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId) || (subId != phoneSubId)) {
+ log("onDataReconnect: invalid subId");
return;
}
@@ -540,8 +515,6 @@
}
// TODO: IF already associated should we send the EVENT_TRY_SETUP_DATA???
sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, apnContext));
-
- apnContext.setReconnectIntent(null);
}
}
@@ -749,13 +722,6 @@
initApnContexts();
- for (ApnContext apnContext : mApnContexts.values()) {
- // Register the reconnect and restart actions.
- filter = new IntentFilter();
- filter.addAction(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
- mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
- }
-
initEmergencyApnSetting();
addEmergencyApnSetting();
@@ -1753,7 +1719,7 @@
// Make sure reconnection alarm is cleaned up if there is no ApnContext
// associated to the connection.
if (dataConnection != null) {
- cancelReconnectAlarm(apnContext);
+ cancelReconnect(apnContext);
}
str = "cleanUpConnectionInternal: X detach=" + detach + " reason="
+ apnContext.getReason();
@@ -1856,24 +1822,6 @@
return null;
}
- /**
- * Cancels the alarm associated with apnContext.
- *
- * @param apnContext on which the alarm should be stopped.
- */
- private void cancelReconnectAlarm(ApnContext apnContext) {
- if (apnContext == null) return;
-
- PendingIntent intent = apnContext.getReconnectIntent();
-
- if (intent != null) {
- AlarmManager am =
- (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
- am.cancel(intent);
- apnContext.setReconnectIntent(null);
- }
- }
-
boolean isPermanentFailure(@DataFailureCause int dcFailCause) {
return (DataFailCause.isPermanentFailure(mPhone.getContext(), dcFailCause,
mPhone.getSubId())
@@ -2198,31 +2146,31 @@
return retry;
}
- private void startAlarmForReconnect(long delay, ApnContext apnContext) {
- String apnType = apnContext.getApnType();
-
- Intent intent = new Intent(INTENT_RECONNECT_ALARM + "." + apnType);
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, apnType);
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TRANSPORT_TYPE, mTransportType);
- SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ private void startReconnect(long delay, ApnContext apnContext) {
+ Message msg = obtainMessage(DctConstants.EVENT_DATA_RECONNECT,
+ mPhone.getSubId(), mTransportType, apnContext);
+ cancelReconnect(apnContext);
+ sendMessageDelayed(msg, delay);
if (DBG) {
- log("startAlarmForReconnect: delay=" + delay + " action=" + intent.getAction()
- + " apn=" + apnContext);
+ log("startReconnect: delay=" + delay + " apn="
+ + apnContext + "reason: " + apnContext.getReason()
+ + " subId: " + mPhone.getSubId());
}
+ }
- PendingIntent alarmIntent = PendingIntent.getBroadcast(mPhone.getContext(), 0,
- intent, PendingIntent.FLAG_UPDATE_CURRENT);
- apnContext.setReconnectIntent(alarmIntent);
+ /**
+ * Cancels the alarm associated with apnContext.
+ *
+ * @param apnContext on which the alarm should be stopped.
+ */
+ private void cancelReconnect(ApnContext apnContext) {
+ if (apnContext == null) return;
- // Use the exact timer instead of the inexact one to provide better user experience.
- // In some extreme cases, we saw the retry was delayed for few minutes.
- // Note that if the stated trigger time is in the past, the alarm will be triggered
- // immediately.
- mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + delay, alarmIntent);
+ if (DBG) {
+ log("cancelReconnect: apn=" + apnContext);
+ }
+ removeMessages(DctConstants.EVENT_DATA_RECONNECT, apnContext);
}
private void notifyNoData(@DataFailureCause int lastFailCauseCode,
@@ -2903,7 +2851,7 @@
// Wait a bit before trying the next APN, so that
// we're not tying up the RIL command channel
- startAlarmForReconnect(delay, apnContext);
+ startReconnect(delay, apnContext);
} else {
// If we are not going to retry any APN, set this APN context to failed state.
// This would be the final state of a data connection.
@@ -2920,10 +2868,11 @@
*
* @param status One of {@code NetworkAgent.VALID_NETWORK} or
* {@code NetworkAgent.INVALID_NETWORK}.
+ * @param cid context id {@code cid}
* @param redirectUrl If the Internet probe was redirected, this
* is the destination it was redirected to, otherwise {@code null}
*/
- private void onNetworkStatusChanged(int status, String redirectUrl) {
+ private void onNetworkStatusChanged(int status, int cid, String redirectUrl) {
if (!TextUtils.isEmpty(redirectUrl)) {
Intent intent = new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED);
intent.putExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY, redirectUrl);
@@ -2931,6 +2880,7 @@
log("Notify carrier signal receivers with redirectUrl: " + redirectUrl);
} else {
final boolean isValid = status == NetworkAgent.VALID_NETWORK;
+ final DataConnection dc = getDataConnectionByContextId(cid);
if (!mDsRecoveryHandler.isRecoveryOnBadNetworkEnabled()) {
if (DBG) log("Skip data stall recovery on network status change with in threshold");
return;
@@ -2939,7 +2889,9 @@
if (DBG) log("Skip data stall recovery on non WWAN");
return;
}
- mDsRecoveryHandler.processNetworkStatusChanged(isValid);
+ if (dc != null && dc.isValidationRequired()) {
+ mDsRecoveryHandler.processNetworkStatusChanged(isValid);
+ }
}
}
@@ -2996,7 +2948,7 @@
if (delay > 0) {
// Data connection is in IDLE state, so when we reconnect later, we'll rebuild
// the waiting APN list, which will also reset/reconfigure the retry manager.
- startAlarmForReconnect(delay, apnContext);
+ startReconnect(delay, apnContext);
}
} else {
boolean restartRadioAfterProvisioning = mPhone.getContext().getResources().getBoolean(
@@ -3583,8 +3535,9 @@
case DctConstants.EVENT_NETWORK_STATUS_CHANGED:
int status = msg.arg1;
+ int cid = msg.arg2;
String url = (String) msg.obj;
- onNetworkStatusChanged(status, url);
+ onNetworkStatusChanged(status, cid, url);
break;
case DctConstants.EVENT_RADIO_AVAILABLE:
@@ -3775,7 +3728,8 @@
break;
}
case DctConstants.EVENT_DATA_RECONNECT:
- onDataReconnect(msg.getData());
+ if (DBG) log("EVENT_DATA_RECONNECT: subId=" + msg.arg1);
+ onDataReconnect((ApnContext) msg.obj, msg.arg1);
break;
case DctConstants.EVENT_DATA_SERVICE_BINDING_CHANGED:
onDataServiceBindingChanged((Boolean) ((AsyncResult) msg.obj).result);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 3d49d79..bf2a00c 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -47,6 +47,7 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.net.NetworkStats;
import android.net.Uri;
import android.os.AsyncResult;
@@ -204,7 +205,10 @@
private ServiceState mSS = new ServiceState();
private RcsFeatureManager mRcsManager;
- private final FeatureConnector<RcsFeatureManager> mRcsManagerConnector;
+ @VisibleForTesting
+ public FeatureConnector<RcsFeatureManager> mRcsManagerConnector;
+ @VisibleForTesting
+ public FeatureConnector.Listener<RcsFeatureManager> mRcsFeatureConnectorListener;
// To redial silently through GSM or CDMA when dialing through IMS fails
private String mLastDialString;
@@ -331,34 +335,9 @@
// Force initial roaming state update later, on EVENT_CARRIER_CONFIG_CHANGED.
// Settings provider or CarrierConfig may not be loaded now.
- mRcsManagerConnector = new FeatureConnector<RcsFeatureManager>(mContext, mPhoneId,
- new FeatureConnector.Listener<RcsFeatureManager>() {
- @Override
- public boolean isSupported() {
- if (!ImsManager.isImsSupportedOnDevice(mContext)) {
- return false;
- }
- if (!RcsFeatureManager.isRcsUceSupportedByCarrier(mContext, mPhoneId)) {
- return false;
- }
- return true;
- }
-
- @Override
- public RcsFeatureManager getFeatureManager() {
- return new RcsFeatureManager(mContext, mPhoneId);
- }
-
- @Override
- public void connectionReady(RcsFeatureManager manager) throws ImsException {
- mRcsManager = manager;
- }
-
- @Override
- public void connectionUnavailable() {
- }
- }, mContext.getMainExecutor(), "ImsPhone");
- mRcsManagerConnector.connect();
+ // Listen to the carrier config changed to initialize RcsFeatureManager
+ IntentFilter filter = new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ mContext.registerReceiver(mCarrierConfigChangedReceiver, filter);
}
//todo: get rid of this function. It is not needed since parentPhone obj never changes
@@ -382,7 +361,75 @@
mDefaultPhone.unregisterForServiceStateChanged(this);
}
- mRcsManagerConnector.disconnect();
+ mContext.unregisterReceiver(mCarrierConfigChangedReceiver);
+
+ if (mRcsManagerConnector != null) {
+ mRcsManagerConnector.disconnect();
+ mRcsManagerConnector = null;
+ }
+ }
+
+ private BroadcastReceiver mCarrierConfigChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent == null) {
+ return;
+ }
+ if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) {
+ Bundle bundle = intent.getExtras();
+ if (bundle == null) {
+ return;
+ }
+ int phoneId = bundle.getInt(CarrierConfigManager.EXTRA_SLOT_INDEX);
+ if (phoneId == mPhoneId) {
+ sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED);
+ }
+ }
+ }
+ };
+
+ /**
+ * Create RcsManagerConnector to initialize RcsFeatureManager
+ */
+ @VisibleForTesting
+ public void initRcsFeatureManager() {
+ if (mRcsManagerConnector != null) {
+ mRcsManagerConnector.disconnect();
+ mRcsManagerConnector = null;
+ }
+
+ logd("initRcsFeatureManager");
+ mRcsFeatureConnectorListener = new FeatureConnector.Listener<>() {
+ @Override
+ public boolean isSupported() {
+ // Check if Telephony IMS is supported or not
+ if (!ImsManager.isImsSupportedOnDevice(mContext)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public RcsFeatureManager getFeatureManager() {
+ return new RcsFeatureManager(mContext, mPhoneId);
+ }
+
+ @Override
+ public void connectionReady(RcsFeatureManager manager) throws ImsException {
+ logd("RcsFeatureManager is ready");
+ mRcsManager = manager;
+ }
+
+ @Override
+ public void connectionUnavailable() {
+ logd("RcsFeatureManager is unavailable");
+ mRcsManager = null;
+ }
+ };
+
+ mRcsManagerConnector = new FeatureConnector<>(mContext, mPhoneId,
+ mRcsFeatureConnectorListener, mContext.getMainExecutor(), LOG_TAG);
+ mRcsManagerConnector.connect();
}
@UnsupportedAppUsage
@@ -1591,6 +1638,12 @@
updateRoamingState(sst.mSS);
}
break;
+ case EVENT_CARRIER_CONFIG_CHANGED:
+ if (DBG) logd("EVENT_CARRIER_CONFIG_CHANGED");
+ if (mRcsManager == null) {
+ initRcsFeatureManager();
+ }
+ break;
default:
super.handleMessage(msg);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 0070e3d..cdc03aa 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -912,6 +912,7 @@
mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
pendingCallClirMode = clirMode;
mPendingCallVideoState = videoState;
+ mPendingIntentExtras = dialArgs.intentExtras;
pendingCallInEcm = true;
}
}
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommands.java b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
index db581b2..261b60e 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -46,6 +46,7 @@
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataProfile;
import android.telephony.emergency.EmergencyNumber;
@@ -1179,6 +1180,14 @@
}
}
+ // Store different cids to simulate concurrent IMS and default data calls
+ if ((dataProfile.getSupportedApnTypesBitmask() & ApnSetting.TYPE_IMS)
+ == ApnSetting.TYPE_IMS) {
+ mSetupDataCallResult.cid = 0;
+ } else {
+ mSetupDataCallResult.cid = 1;
+ }
+
DataCallResponse response = RIL.convertDataCallResult(mSetupDataCallResult);
if (mDcSuccess) {
resultSuccess(result, response);
diff --git a/src/java/com/android/internal/telephony/util/TelephonyUtils.java b/src/java/com/android/internal/telephony/util/TelephonyUtils.java
index 1048e5c..ea44d98 100644
--- a/src/java/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/src/java/com/android/internal/telephony/util/TelephonyUtils.java
@@ -25,6 +25,8 @@
* This class provides various util functions
*/
public final class TelephonyUtils {
+ public static boolean IS_USER = "user".equals(android.os.Build.TYPE);
+
/** {@hide} */
public static String emptyIfNull(@Nullable String str) {
return str == null ? "" : str;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index 5c09525..ae8dd62 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -158,14 +158,6 @@
public void testGetMergedServiceState() throws Exception {
ServiceState imsServiceState = new ServiceState();
- NetworkRegistrationInfo imsCsWwanRegInfo = new NetworkRegistrationInfo.Builder()
- .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
- .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
- .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
- .setRegistrationState(
- NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
- .build();
-
NetworkRegistrationInfo imsPsWwanRegInfo = new NetworkRegistrationInfo.Builder()
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
@@ -182,10 +174,11 @@
NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.build();
- imsServiceState.addNetworkRegistrationInfo(imsCsWwanRegInfo);
+ // Only PS states are tracked for IMS.
imsServiceState.addNetworkRegistrationInfo(imsPsWwanRegInfo);
imsServiceState.addNetworkRegistrationInfo(imsPsWlanRegInfo);
+ // Voice reg state in this case is whether or not IMS is registered.
imsServiceState.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
imsServiceState.setDataRegState(ServiceState.STATE_IN_SERVICE);
imsServiceState.setIwlanPreferred(true);
@@ -236,6 +229,88 @@
assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, mergedServiceState.getDataNetworkType());
}
+ /**
+ * Some vendors do not provide a voice registration for LTE when attached to LTE only (no CSFB
+ * available). In this case, we should still get IN_SERVICE for voice service state, since
+ * IMS is registered.
+ */
+ @Test
+ @SmallTest
+ public void testGetMergedServiceStateNoCsfb() throws Exception {
+ ServiceState imsServiceState = new ServiceState();
+
+ NetworkRegistrationInfo imsPsWwanRegInfo = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .build();
+
+ NetworkRegistrationInfo imsPsWlanRegInfo = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
+ .build();
+
+ // Only PS states are tracked for IMS.
+ imsServiceState.addNetworkRegistrationInfo(imsPsWwanRegInfo);
+ imsServiceState.addNetworkRegistrationInfo(imsPsWlanRegInfo);
+
+ // Voice reg state in this case is whether or not IMS is registered.
+ imsServiceState.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
+ imsServiceState.setDataRegState(ServiceState.STATE_IN_SERVICE);
+ imsServiceState.setIwlanPreferred(true);
+ doReturn(imsServiceState).when(mImsPhone).getServiceState();
+
+ replaceInstance(Phone.class, "mImsPhone", mPhoneUT, mImsPhone);
+
+ ServiceState serviceState = new ServiceState();
+
+ NetworkRegistrationInfo csWwanRegInfo = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_UNKNOWN)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
+ .build();
+
+ NetworkRegistrationInfo psWwanRegInfo = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .build();
+
+ NetworkRegistrationInfo psWlanRegInfo = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
+ .build();
+
+ serviceState.addNetworkRegistrationInfo(csWwanRegInfo);
+ serviceState.addNetworkRegistrationInfo(psWwanRegInfo);
+ serviceState.addNetworkRegistrationInfo(psWlanRegInfo);
+ // No CSFB, voice is OOS for LTE only attach
+ serviceState.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
+ serviceState.setDataRegState(ServiceState.STATE_IN_SERVICE);
+ serviceState.setIwlanPreferred(true);
+
+ mSST.mSS = serviceState;
+ mPhoneUT.mSST = mSST;
+
+ ServiceState mergedServiceState = mPhoneUT.getServiceState();
+
+ assertEquals(ServiceState.STATE_IN_SERVICE, mergedServiceState.getVoiceRegState());
+ assertEquals(ServiceState.STATE_IN_SERVICE, mergedServiceState.getDataRegState());
+ assertEquals(TelephonyManager.NETWORK_TYPE_LTE, mergedServiceState.getDataNetworkType());
+ }
+
@Test
@SmallTest
public void testGetSubscriberIdForGsmPhone() {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java
index 3702d3e..1f554a8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java
@@ -102,6 +102,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -221,6 +222,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -254,6 +256,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
// A valid NITZ signal for the non-default zone should still be correctly detected.
@@ -268,6 +271,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
// Demonstrate what happens with a bogus NITZ for NZ: because the default zone is boosted
@@ -285,6 +289,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(expectedTimeZoneId, mNitzStateMachine.getSavedTimeZoneId());
}
}
@@ -318,6 +323,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
// A valid NITZ signal for a different zone should also be correctly detected.
@@ -332,6 +338,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
// Demonstrate what happens with a bogus NITZ for US: because the default zone is not
@@ -346,8 +353,9 @@
.verifyNothingWasSetAndReset();
// Check NitzStateMachine state.
- assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
}
}
@@ -374,6 +382,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -399,6 +408,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -423,6 +433,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the country code becoming known.
script.countryReceived(scenario.getNetworkCountryIsoCode())
@@ -432,6 +443,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -455,6 +467,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the country code becoming known.
script.countryReceived(scenario.getNetworkCountryIsoCode());
@@ -465,6 +478,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -490,6 +504,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(goodNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the country code becoming known.
script.countryReceived(scenario.getNetworkCountryIsoCode())
@@ -498,6 +513,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(goodNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -520,6 +536,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Simulate receiving an NITZ signal.
script.nitzReceived(goodNitzSignal);
@@ -534,6 +551,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(goodNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -568,6 +586,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the country code becoming known.
script.countryReceived(scenario.getNetworkCountryIsoCode())
@@ -576,6 +595,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -606,6 +626,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Simulate receiving an NITZ signal.
script.nitzReceived(badNitzSignal);
@@ -618,6 +639,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -651,6 +673,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the country code becoming known.
script.countryReceived(scenario.getNetworkCountryIsoCode())
@@ -661,6 +684,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -692,6 +716,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate receiving an NITZ signal.
script.nitzReceived(badNitzSignal);
@@ -704,6 +729,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -740,6 +766,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(emulatorNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(emulatorTimeZoneId, mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -759,6 +786,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate receiving the NITZ signal.
TimestampedValue<NitzData> nitzSignal =
@@ -772,6 +800,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(expectedZoneId, mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -797,6 +826,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// The time zone should be set (but the country is not valid so it's unlikely to be
// correct).
@@ -805,6 +835,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(expectedZoneId, mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -842,7 +873,9 @@
.verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(preflightNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Boarded flight: Airplane mode turned on / time zone detection still enabled.
// The NitzStateMachineImpl must lose all state and stop having an opinion about time zone.
@@ -854,7 +887,9 @@
script.toggleAirplaneMode(true);
// Check state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Verify there's no time zone opinion by toggling auto time zone off and on.
script.toggleTimeZoneDetectionEnabled(false)
@@ -878,7 +913,9 @@
.verifyNothingWasSetAndReset();
// Check the state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Post flight: Device has moved and receives new signals.
@@ -903,7 +940,9 @@
scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(postFlightNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
/**
@@ -944,7 +983,9 @@
.verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(initialNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Simulate losing the network. The NitzStateMachineImpl must lose all NITZ state and stop
// having an opinion about time zone.
@@ -956,7 +997,9 @@
script.incrementTime(timeStepMillis);
// Check state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Verify there's no time zone opinion by toggling auto time zone off and on.
script.toggleTimeZoneDetectionEnabled(false)
@@ -978,7 +1021,9 @@
.verifyNothingWasSetAndReset();
// Check the state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the passage of time and update the device realtime clock.
scenario.incrementTime(timeStepMillis);
@@ -996,7 +1041,9 @@
scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(finalNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
/**
@@ -1037,7 +1084,9 @@
.verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(initialNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Simulate losing the network. The NitzStateMachineImpl must lose all NITZ state but should
// retain country knowledge and so remain opinionated about time zone ID because the country
@@ -1050,7 +1099,9 @@
script.incrementTime(timeStepMillis);
// Check state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Verify there's a time zone opinion by toggling auto time zone off and on.
script.toggleTimeZoneDetectionEnabled(false)
@@ -1072,7 +1123,9 @@
.verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId());
// Check the state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Simulate the passage of time and update the device realtime clock.
scenario.incrementTime(timeStepMillis);
@@ -1090,7 +1143,9 @@
scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(finalNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
/**
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
index a1b37d8..fda30f5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
@@ -119,12 +119,14 @@
import android.telephony.CellIdentityCdma;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
+import android.telephony.CellIdentityNr;
import android.telephony.CellIdentityTdscdma;
import android.telephony.CellIdentityWcdma;
import android.telephony.CellInfo;
import android.telephony.CellInfoCdma;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
+import android.telephony.CellInfoNr;
import android.telephony.CellInfoTdscdma;
import android.telephony.CellInfoWcdma;
import android.telephony.CellSignalStrengthCdma;
@@ -205,6 +207,7 @@
private static final int MNC = 260;
private static final String MNC_STR = "260";
private static final int NETWORK_ID = 65534;
+ private static final int NRARFCN = 3279165;
private static final int PCI = 503;
private static final int PSC = 500;
private static final int RIL_TIMESTAMP_TYPE_OEM_RIL = 3;
@@ -1563,6 +1566,47 @@
}
@Test
+ public void testConvertHalCellInfoList_1_4ForNr() {
+ android.hardware.radio.V1_4.CellInfoNr cellinfo =
+ new android.hardware.radio.V1_4.CellInfoNr();
+ cellinfo.cellidentity.nci = CI;
+ cellinfo.cellidentity.pci = PCI;
+ cellinfo.cellidentity.tac = TAC;
+ cellinfo.cellidentity.nrarfcn = NRARFCN;
+ cellinfo.cellidentity.mcc = MCC_STR;
+ cellinfo.cellidentity.mnc = MNC_STR;
+ cellinfo.cellidentity.operatorNames.alphaLong = ALPHA_LONG;
+ cellinfo.cellidentity.operatorNames.alphaShort = ALPHA_SHORT;
+ cellinfo.signalStrength.ssRsrp = -RSRP;
+ cellinfo.signalStrength.ssRsrq = -RSRQ;
+ cellinfo.signalStrength.ssSinr = SIGNAL_NOISE_RATIO;
+ cellinfo.signalStrength.csiRsrp = -RSRP;
+ cellinfo.signalStrength.csiRsrq = -RSRQ;
+ cellinfo.signalStrength.csiSinr = SIGNAL_NOISE_RATIO;
+
+ android.hardware.radio.V1_4.CellInfo record = new android.hardware.radio.V1_4.CellInfo();
+ record.info.nr(cellinfo);
+
+ ArrayList<android.hardware.radio.V1_4.CellInfo> records = new ArrayList<>();
+ records.add(record);
+
+ ArrayList<CellInfo> ret = RIL.convertHalCellInfoList_1_4(records);
+
+ CellInfoNr cellInfoNr = (CellInfoNr) ret.get(0);
+ CellIdentityNr cellIdentityNr = (CellIdentityNr) cellInfoNr.getCellIdentity();
+ CellSignalStrengthNr signalStrengthNr =
+ (CellSignalStrengthNr) cellInfoNr.getCellSignalStrength();
+
+ CellIdentityNr expectedCellIdentity = new CellIdentityNr(PCI, TAC, NRARFCN, MCC_STR,
+ MNC_STR, CI, ALPHA_LONG, ALPHA_SHORT);
+ CellSignalStrengthNr expectedSignalStrength = new CellSignalStrengthNr(-RSRP, -RSRQ,
+ SIGNAL_NOISE_RATIO, -RSRP, -RSRQ, SIGNAL_NOISE_RATIO);
+
+ assertEquals(expectedCellIdentity, cellIdentityNr);
+ assertEquals(expectedSignalStrength, signalStrengthNr);
+ }
+
+ @Test
public void testConvertDataCallResult() {
// Test V1.0 SetupDataCallResult
android.hardware.radio.V1_0.SetupDataCallResult result10 =
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
index 101c719..f6ef326 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -720,21 +720,14 @@
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
- // Verify the retry manger schedule another data call setup.
- verify(mAlarmManager, times(1)).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
- anyLong(), any(PendingIntent.class));
-
// This time we'll let RIL command succeed.
mSimulatedCommands.setDataCallResult(true, createSetupDataCallResult());
- // Simulate the timer expires.
- Intent intent = new Intent("com.android.internal.telephony.data-reconnect.default");
- intent.putExtra("reconnect_alarm_extra_type", PhoneConstants.APN_TYPE_DEFAULT);
- intent.putExtra("reconnect_alarm_extra_transport_type",
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, 0);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- mContext.sendBroadcast(intent);
+ //Send event for reconnecting data
+ initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RECONNECT,
+ mPhone.getPhoneId(), AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+ mApnContext));
waitForMs(200);
dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
@@ -1361,14 +1354,11 @@
verify(mAlarmManager, times(1)).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
anyLong(), any(PendingIntent.class));
- // Simulate the timer expires.
- Intent intent = new Intent("com.android.internal.telephony.data-reconnect.default");
- intent.putExtra("reconnect_alarm_extra_type", PhoneConstants.APN_TYPE_DEFAULT);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, 0);
- intent.putExtra("reconnect_alarm_extra_transport_type",
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- mContext.sendBroadcast(intent);
+ //Send event for reconnecting data
+ initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RECONNECT,
+ mPhone.getPhoneId(), AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+ mApnContext));
waitForMs(200);
// Verify if RIL command was sent properly.
@@ -1597,16 +1587,17 @@
eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
+ waitForMs(200);
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
logd("Sending EVENT_NETWORK_STATUS_CHANGED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.VALID_NETWORK, 0, null));
+ NetworkAgent.VALID_NETWORK, 1, null));
waitForMs(200);
logd("Sending EVENT_NETWORK_STATUS_CHANGED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.INVALID_NETWORK, 0, null));
+ NetworkAgent.INVALID_NETWORK, 1, null));
waitForMs(200);
// Verify that its no-op when the new data stall detection feature is disabled
@@ -1638,16 +1629,17 @@
eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
+ waitForMs(200);
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
logd("Sending EVENT_NETWORK_STATUS_CHANGED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.VALID_NETWORK, 0, null));
+ NetworkAgent.VALID_NETWORK, 1, null));
waitForMs(200);
logd("Sending EVENT_NETWORK_STATUS_CHANGED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.INVALID_NETWORK, 0, null));
+ NetworkAgent.INVALID_NETWORK, 1, null));
waitForMs(200);
verify(mSimulatedCommandsVerifier, times(1)).getDataCallList(any(Message.class));
@@ -1680,11 +1672,12 @@
eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
+ waitForMs(200);
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.INVALID_NETWORK, 0, null));
+ NetworkAgent.INVALID_NETWORK, 1, null));
waitForMs(200);
// expected tear down all DataConnections
@@ -1724,7 +1717,7 @@
logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.INVALID_NETWORK, 0, null));
+ NetworkAgent.INVALID_NETWORK, 1, null));
waitForMs(200);
// expected to get preferred network type
@@ -1761,7 +1754,7 @@
logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.INVALID_NETWORK, 0, null));
+ NetworkAgent.INVALID_NETWORK, 1, null));
waitForMs(200);
// expected to get preferred network type
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
index 0cdc34c..0db3204 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
@@ -35,6 +35,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
@@ -63,9 +64,11 @@
import androidx.test.filters.FlakyTest;
+import com.android.ims.FeatureConnector;
import com.android.ims.ImsEcbmStateListener;
import com.android.ims.ImsManager;
import com.android.ims.ImsUtInterface;
+import com.android.ims.RcsFeatureManager;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.CommandsInterface;
@@ -832,6 +835,19 @@
assertNotNull(mImsPhoneUT.getServiceStateTracker());
}
+ @Test
+ @SmallTest
+ public void testRcsFeatureManagerInitialization() throws Exception {
+ FeatureConnector<RcsFeatureManager> mockRcsManagerConnector =
+ (FeatureConnector<RcsFeatureManager>) mock(FeatureConnector.class);
+ mImsPhoneUT.mRcsManagerConnector = mockRcsManagerConnector;
+
+ mImsPhoneUT.initRcsFeatureManager();
+
+ verify(mockRcsManagerConnector).disconnect();
+ assertNotNull(mImsPhoneUT.mRcsManagerConnector);
+ }
+
private ServiceState getServiceStateDataAndVoice(int rat, int regState, boolean isRoaming) {
ServiceState ss = new ServiceState();
ss.setStateOutOfService();