Merge "[Settings] Replace isImsRegistered"
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
index 1986965..d7e07d9 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
@@ -27,6 +27,7 @@
 import android.os.IBinder;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
+import android.telephony.AccessNetworkConstants;
 import android.telephony.Annotation;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellBroadcastIntents;
@@ -42,6 +43,9 @@
 import android.telephony.TelephonyManager;
 import android.telephony.UiccCardInfo;
 import android.telephony.euicc.EuiccManager;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.ImsReasonInfo;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -107,11 +111,27 @@
             new OnSubscriptionsChangedListener() {
                 @Override
                 public void onSubscriptionsChanged() {
-                    mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfo(
-                            mSubscriptionInfo.getSubscriptionId());
-                    mTelephonyManager = mTelephonyManager.createForSubscriptionId(
-                            mSubscriptionInfo.getSubscriptionId());
-                    updateNetworkProvider();
+                    final int prevSubId = (mSubscriptionInfo != null)
+                            ? mSubscriptionInfo.getSubscriptionId()
+                            : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+                    mSubscriptionInfo = getPhoneSubscriptionInfo(mSlotIndex);
+
+                    final int nextSubId = (mSubscriptionInfo != null)
+                            ? mSubscriptionInfo.getSubscriptionId()
+                            : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+                    if (prevSubId != nextSubId) {
+                        if (SubscriptionManager.isValidSubscriptionId(prevSubId)) {
+                            unregisterImsRegistrationCallback(prevSubId);
+                        }
+                        if (SubscriptionManager.isValidSubscriptionId(nextSubId)) {
+                            mTelephonyManager =
+                                    mTelephonyManager.createForSubscriptionId(nextSubId);
+                            registerImsRegistrationCallback(nextSubId);
+                        }
+                    }
+                    updateSubscriptionStatus();
                 }
             };
 
@@ -201,13 +221,17 @@
         }
 
         mPhoneStateListener = getPhoneStateListener();
+        updateLatestAreaInfo();
+        updateSubscriptionStatus();
+    }
+
+    private void updateSubscriptionStatus() {
         updateNetworkProvider();
 
         final ServiceState serviceState = mTelephonyManager.getServiceState();
         final SignalStrength signalStrength = mTelephonyManager.getSignalStrength();
 
         updatePhoneNumber();
-        updateLatestAreaInfo();
         updateServiceState(serviceState);
         updateSignalStrength(signalStrength);
         updateNetworkType();
@@ -241,6 +265,7 @@
                         | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
                         | PhoneStateListener.LISTEN_SERVICE_STATE);
         mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
+        registerImsRegistrationCallback(mSubscriptionInfo.getSubscriptionId());
 
         if (mShowLatestAreaInfo) {
             updateAreaInfoText();
@@ -255,6 +280,7 @@
             return;
         }
 
+        unregisterImsRegistrationCallback(mSubscriptionInfo.getSubscriptionId());
         mSubscriptionManager.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
         mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
 
@@ -525,21 +551,68 @@
         }
     }
 
-    private void updateImsRegistrationState() {
+    private boolean isImsRegistrationStateShowUp() {
         final int subscriptionId = mSubscriptionInfo.getSubscriptionId();
         final PersistableBundle carrierConfig =
                 mCarrierConfigManager.getConfigForSubId(subscriptionId);
-        final boolean showImsRegState = carrierConfig == null ? false :
+        return carrierConfig == null ? false :
                 carrierConfig.getBoolean(
                         CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL);
-        if (showImsRegState) {
-            final boolean isImsRegistered = mTelephonyManager.isImsRegistered(subscriptionId);
-            mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(isImsRegistered ?
-                    R.string.ims_reg_status_registered : R.string.ims_reg_status_not_registered));
-        } else {
-            mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_LABEL_ID);
-            mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_VALUE_ID);
+    }
+
+    private void updateImsRegistrationState() {
+        if (isImsRegistrationStateShowUp()) {
+            return;
         }
+        mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_LABEL_ID);
+        mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_VALUE_ID);
+    }
+
+    private ImsMmTelManager.RegistrationCallback mImsRegStateCallback =
+            new ImsMmTelManager.RegistrationCallback() {
+        @Override
+        public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) {
+            mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(
+                    R.string.ims_reg_status_registered));
+        }
+        @Override
+        public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) {
+            mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(
+                    R.string.ims_reg_status_not_registered));
+        }
+        @Override
+        public void onUnregistered(@Nullable ImsReasonInfo info) {
+            mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(
+                    R.string.ims_reg_status_not_registered));
+        }
+        @Override
+        public void onTechnologyChangeFailed(
+                @AccessNetworkConstants.TransportType int imsTransportType,
+                @Nullable ImsReasonInfo info) {
+            mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(
+                    R.string.ims_reg_status_not_registered));
+        }
+    };
+
+    private void registerImsRegistrationCallback(int subId) {
+        if (!isImsRegistrationStateShowUp()) {
+            return;
+        }
+        try {
+            final ImsMmTelManager imsMmTelMgr = ImsMmTelManager.createForSubscriptionId(subId);
+            imsMmTelMgr.registerImsRegistrationCallback(mDialog.getContext().getMainExecutor(),
+                    mImsRegStateCallback);
+        } catch (ImsException exception) {
+            Log.w(TAG, "fail to register IMS status for subId=" + subId, exception);
+        }
+    }
+
+    private void unregisterImsRegistrationCallback(int subId) {
+        if (!isImsRegistrationStateShowUp()) {
+            return;
+        }
+        final ImsMmTelManager imsMmTelMgr = ImsMmTelManager.createForSubscriptionId(subId);
+        imsMmTelMgr.unregisterImsRegistrationCallback(mImsRegStateCallback);
     }
 
     private SubscriptionInfo getPhoneSubscriptionInfo(int slotId) {
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java
index 851dfe0..395c8a4 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java
@@ -43,6 +43,7 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
 
 import android.content.Context;
 import android.content.pm.PackageInfo;
@@ -80,6 +81,7 @@
 import org.robolectric.Shadows;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowPackageManager;
+import org.robolectric.shadows.ShadowTelephonyManager;
 import org.robolectric.util.ReflectionHelpers;
 
 import java.util.ArrayList;
@@ -93,7 +95,6 @@
 
     @Mock
     private SimStatusDialogFragment mDialog;
-    @Mock
     private TelephonyManager mTelephonyManager;
     @Mock
     private SubscriptionInfo mSubscriptionInfo;
@@ -115,7 +116,6 @@
     private PersistableBundle mPersistableBundle;
     @Mock
     private EuiccManager mEuiccManager;
-    @Mock
     private SubscriptionManager mSubscriptionManager;
 
     private SimStatusDialogController mController;
@@ -131,10 +131,22 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
+        mContext = spy(RuntimeEnvironment.application);
         when(mDialog.getContext()).thenReturn(mContext);
         mLifecycleOwner = () -> mLifecycle;
         mLifecycle = new Lifecycle(mLifecycleOwner);
+
+        mSubscriptionManager = spy(mContext.getSystemService(SubscriptionManager.class));
+
+        mTelephonyManager = spy(mContext.getSystemService(TelephonyManager.class));
+        final ShadowTelephonyManager shadowTelephonyMgr = shadowOf(mTelephonyManager);
+        shadowTelephonyMgr.setTelephonyManagerForSubscriptionId(
+                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, mTelephonyManager);
+        doReturn(2).when(mTelephonyManager).getCardIdForDefaultEuicc();
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mTelephonyManager).getDataNetworkType();
+
+        doReturn(mEuiccManager).when(mContext).getSystemService(EuiccManager.class);
+
         mController = spy(new SimStatusDialogController(mDialog, mLifecycle, 0 /* phone id */));
         ShadowDeviceInfoUtils.setPhoneNumber("");
         //CellSignalStrength setup
@@ -156,9 +168,9 @@
         ReflectionHelpers.setField(mController, "mSubscriptionManager", mSubscriptionManager);
 
         when(mTelephonyManager.getActiveModemCount()).thenReturn(MAX_PHONE_COUNT_SINGLE_SIM);
-        when(mTelephonyManager.getUiccCardsInfo()).thenReturn(new ArrayList<UiccCardInfo>());
-        when(mTelephonyManager.getLogicalToPhysicalSlotMapping()).thenReturn(
-                new HashMap<Integer, Integer>());
+        doReturn(new ArrayList<UiccCardInfo>()).when(mTelephonyManager).getUiccCardsInfo();
+        doReturn(new HashMap<Integer, Integer>()).when(mTelephonyManager)
+                .getLogicalToPhysicalSlotMapping();
 
         when(mEuiccManager.isEnabled()).thenReturn(false);
         when(mEuiccManager.getEid()).thenReturn("");
@@ -168,7 +180,6 @@
         when(mPersistableBundle.getBoolean(
                 CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL))
                 .thenReturn(true);
-        when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
         doReturn(mServiceState).when(mTelephonyManager).getServiceState();
         doReturn(mSignalStrength).when(mTelephonyManager).getSignalStrength();
 
@@ -185,7 +196,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateNetworkProviderWithFoobarCarrier_shouldUpdateCarrierWithFoobar() {
         final CharSequence carrierName = "foobar";
         doReturn(carrierName).when(mSubscriptionInfo).getCarrierName();
@@ -196,7 +206,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updatePhoneNumberWith1111111111_shouldUpdatePhoneNumber() {
         ShadowDeviceInfoUtils.setPhoneNumber("1111111111");
 
@@ -209,7 +218,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateLatestAreaInfoWithCdmaPhone_shouldRemoveOperatorInfoSetting() {
         when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_CDMA);
 
@@ -220,7 +228,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateServiceStateWithInService_shouldUpdateTextToBeCInService() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
 
@@ -231,7 +238,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateServiceStateWithPowerOff_shouldUpdateTextAndResetSignalStrength() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_POWER_OFF);
         when(mPersistableBundle.getBoolean(
@@ -245,7 +251,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateVoiceDataOutOfService_shouldUpdateSettingAndResetSignalStrength() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState.getDataRegistrationState()).thenReturn(
@@ -261,7 +266,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateVoiceOutOfServiceDataInService_shouldUpdateTextToBeInService() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
@@ -275,7 +279,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateSignalStrengthWithLte50Wcdma40_shouldUpdateSignalStrengthTo50() {
         final int lteDbm = 50;
         final int lteAsu = 50;
@@ -293,7 +296,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateSignalStrengthWithLte50Cdma30_shouldUpdateSignalStrengthTo50() {
         final int lteDbm = 50;
         final int lteAsu = 50;
@@ -311,7 +313,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateVoiceOutOfServiceDataInService_shouldUpdateSignalStrengthTo50() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
@@ -332,7 +333,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateVoiceNetworkTypeWithEdge_shouldUpdateSettingToEdge() {
         when(mTelephonyManager.getVoiceNetworkType()).thenReturn(
                 TelephonyManager.NETWORK_TYPE_EDGE);
@@ -344,7 +344,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateDataNetworkTypeWithEdge_shouldUpdateSettingToEdge() {
         when(mTelephonyManager.getDataNetworkType()).thenReturn(
                 TelephonyManager.NETWORK_TYPE_EDGE);
@@ -356,7 +355,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateRoamingStatusIsRoaming_shouldSetSettingToRoaming() {
         when(mServiceState.getRoaming()).thenReturn(true);
 
@@ -367,7 +365,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateRoamingStatusNotRoaming_shouldSetSettingToRoamingOff() {
         when(mServiceState.getRoaming()).thenReturn(false);
 
@@ -378,7 +375,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_doNotShowIccid_shouldRemoveIccidSetting() {
         when(mPersistableBundle.getBoolean(
                 CarrierConfigManager.KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL)).thenReturn(false);
@@ -390,7 +386,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_doNotShowSignalStrength_shouldRemoveSignalStrengthSetting() {
         when(mPersistableBundle.getBoolean(
                 CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL))
@@ -403,7 +398,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_showSignalStrengthAndIccId_shouldShowSignalStrengthAndIccIdSetting() {
         // getConfigForSubId is nullable, so make sure the default behavior is correct
         when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(null);
@@ -416,7 +410,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_showIccid_shouldSetIccidToSetting() {
         final String iccid = "12351351231241";
         when(mPersistableBundle.getBoolean(
@@ -429,7 +422,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateEid_shouldNotSetEid() {
         when(mTelephonyManager.getActiveModemCount()).thenReturn(MAX_PHONE_COUNT_DUAL_SIM);
 
@@ -468,7 +460,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateEid_shouldSetEidFromCard() {
         when(mTelephonyManager.getActiveModemCount()).thenReturn(MAX_PHONE_COUNT_DUAL_SIM);
 
@@ -507,7 +498,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateEid_shouldSetEidFromManager() {
         when(mTelephonyManager.getActiveModemCount()).thenReturn(MAX_PHONE_COUNT_DUAL_SIM);
 
@@ -549,7 +539,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateEid_shouldRemoveEid() {
         when(mTelephonyManager.getActiveModemCount()).thenReturn(MAX_PHONE_COUNT_DUAL_SIM);
 
@@ -589,7 +578,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateEid_shouldNotSetEidInSingleSimMode() {
         when(mTelephonyManager.getActiveModemCount()).thenReturn(MAX_PHONE_COUNT_SINGLE_SIM);
 
@@ -619,7 +607,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateEid_shouldSetEidInSingleSimModeWithEnabledEuicc() {
         when(mTelephonyManager.getActiveModemCount()).thenReturn(MAX_PHONE_COUNT_SINGLE_SIM);
 
@@ -651,7 +638,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateEid_shouldSetEidInSingleSimModeWithDisabledEuicc() {
         when(mTelephonyManager.getActiveModemCount()).thenReturn(MAX_PHONE_COUNT_SINGLE_SIM);
 
@@ -683,7 +669,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_updateEid_shouldRemoveEidInSingleSimMode() {
         when(mTelephonyManager.getActiveModemCount()).thenReturn(MAX_PHONE_COUNT_SINGLE_SIM);
 
@@ -763,7 +748,6 @@
     }
 
     @Test
-    @Ignore
     public void initialize_nullSignalStrength_noCrash() {
         doReturn(null).when(mTelephonyManager).getSignalStrength();
         // we should not crash when running the following line