Merge "DO NOT MERGE Move IMS registration state to SIM status screen"
diff --git a/res/xml/device_info_sim_status.xml b/res/xml/device_info_sim_status.xml
index aa8896c..e95d009 100644
--- a/res/xml/device_info_sim_status.xml
+++ b/res/xml/device_info_sim_status.xml
@@ -66,6 +66,13 @@
         android:summary="@string/device_info_not_available"
         android:persistent="false" />
 
+    <Preference android:key="ims_reg_state"
+        android:enabled="false"
+        android:shouldDisableView="false"
+        android:title="@string/ims_reg_title"
+        android:summary="@string/device_info_not_available"
+        android:persistent="false" />
+
     <Preference android:key="number"
         android:enabled="false"
         android:shouldDisableView="false"
diff --git a/res/xml/device_info_status.xml b/res/xml/device_info_status.xml
index 3456f91..b381d04 100644
--- a/res/xml/device_info_status.xml
+++ b/res/xml/device_info_status.xml
@@ -89,10 +89,4 @@
         android:title="@string/status_wimax_mac_address"
         android:summary="@string/summary_placeholder"
         android:persistent="false" />
-    <Preference
-        android:key="ims_reg_state"
-        android:enabled="false"
-        android:shouldDisableView="false"
-        android:title="@string/ims_reg_title"
-        android:persistent="false" />
 </PreferenceScreen>
diff --git a/src/com/android/settings/deviceinfo/SimStatus.java b/src/com/android/settings/deviceinfo/SimStatus.java
index 2cc76e7..9a6d1cd 100644
--- a/src/com/android/settings/deviceinfo/SimStatus.java
+++ b/src/com/android/settings/deviceinfo/SimStatus.java
@@ -30,7 +30,9 @@
 import android.os.PersistableBundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellBroadcastMessage;
 import android.telephony.PhoneStateListener;
@@ -89,6 +91,9 @@
     private static final String KEY_IMEI_SV = "imei_sv";
     private static final String KEY_ICCID = "iccid";
 
+    @VisibleForTesting
+    static final String KEY_IMS_REGISTRATION_STATE = "ims_reg_state";
+
     static private final String CB_AREA_INFO_RECEIVED_ACTION =
             "com.android.cellbroadcastreceiver.CB_AREA_INFO_RECEIVED";
 
@@ -101,10 +106,10 @@
     private CarrierConfigManager mCarrierConfigManager;
     private Phone mPhone = null;
     private Resources mRes;
-    private Preference mSignalStrength;
     private SubscriptionInfo mSir;
     private boolean mShowLatestAreaInfo;
     private boolean mShowICCID;
+    private boolean mShowImsRegState;
 
     // Default summary for items
     private String mDefaultText;
@@ -148,8 +153,6 @@
 
         mRes = getResources();
         mDefaultText = mRes.getString(R.string.device_info_default);
-        // Note - missing in zaku build, be careful later...
-        mSignalStrength = findPreference(KEY_SIGNAL_STRENGTH);
     }
 
     @Override
@@ -202,10 +205,11 @@
     public void onResume() {
         super.onResume();
         if (mPhone != null) {
-            updatePreference();
+            updatePreference(false /* isTabChanged */);
 
             updateSignalStrength(mPhone.getSignalStrength());
             updateServiceState(mPhone.getServiceState());
+            updateImsRegistrationState();
             updateDataState();
             mTelephonyManager.listen(mPhoneStateListener,
                     PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
@@ -323,7 +327,7 @@
                 break;
             case ServiceState.STATE_OUT_OF_SERVICE:
                 // Set signal strength to 0 when service state is STATE_OUT_OF_SERVICE
-                mSignalStrength.setSummary("0");
+                setSummaryText(KEY_SIGNAL_STRENGTH, "0");
             case ServiceState.STATE_EMERGENCY_ONLY:
                 // Set summary string of service state to radioInfo_service_out when
                 // service state is both STATE_OUT_OF_SERVICE & STATE_EMERGENCY_ONLY
@@ -332,7 +336,7 @@
             case ServiceState.STATE_POWER_OFF:
                 display = mRes.getString(R.string.radioInfo_service_off);
                 // Also set signal strength to 0
-                mSignalStrength.setSummary("0");
+                setSummaryText(KEY_SIGNAL_STRENGTH, "0");
                 break;
         }
 
@@ -353,32 +357,46 @@
     }
 
     void updateSignalStrength(SignalStrength signalStrength) {
-        if (mSignalStrength != null) {
-            final int state = mPhone.getServiceState().getState();
+        final int state = mPhone.getServiceState().getState();
 
-            if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
-                    (ServiceState.STATE_POWER_OFF == state)) {
-                mSignalStrength.setSummary("0");
-                return;
-            }
-
-            int signalDbm = signalStrength.getDbm();
-            int signalAsu = signalStrength.getAsuLevel();
-
-            if (-1 == signalDbm) {
-                signalDbm = 0;
-            }
-
-            if (-1 == signalAsu) {
-                signalAsu = 0;
-            }
-
-            mSignalStrength.setSummary(mRes.getString(R.string.sim_signal_strength,
-                        signalDbm, signalAsu));
+        if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
+                (ServiceState.STATE_POWER_OFF == state)) {
+            setSummaryText(KEY_SIGNAL_STRENGTH, "0");
+            return;
         }
+
+        int signalDbm = signalStrength.getDbm();
+        int signalAsu = signalStrength.getAsuLevel();
+
+        if (-1 == signalDbm) {
+            signalDbm = 0;
+        }
+
+        if (-1 == signalAsu) {
+            signalAsu = 0;
+        }
+
+        setSummaryText(KEY_SIGNAL_STRENGTH, mRes.getString(R.string.sim_signal_strength, signalDbm,
+                signalAsu));
     }
 
-    private void updatePreference() {
+    @VisibleForTesting
+    void updateImsRegistrationState() {
+        boolean isImsRegistered = mTelephonyManager.isImsRegistered(mSir.getSubscriptionId());
+        setSummaryText(KEY_IMS_REGISTRATION_STATE, mRes.getString(isImsRegistered ?
+                R.string.ims_reg_status_registered : R.string.ims_reg_status_not_registered));
+    }
+
+    @VisibleForTesting
+    void updatePreference(boolean isTabChanged) {
+        if (isTabChanged) {
+            PreferenceScreen preferenceScreen = getPreferenceScreen();
+            if (preferenceScreen != null) {
+                preferenceScreen.removeAll();
+                addPreferencesFromResource(R.xml.device_info_sim_status);
+            }
+        }
+
         if (mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) {
             mShowLatestAreaInfo = Resources.getSystem().getBoolean(
                     com.android.internal.R.bool.config_showAreaUpdateInfoSettings);
@@ -387,7 +405,8 @@
                 mSir.getSubscriptionId());
         mShowICCID = carrierConfig.getBoolean(
                 CarrierConfigManager.KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL);
-
+        mShowImsRegState = carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL);
 
         // If formattedNumber is null or empty, it'll display as "Unknown".
         setSummaryText(KEY_PHONE_NUMBER,
@@ -412,6 +431,10 @@
         if (hideSignalStrength) {
             removePreferenceFromScreen(KEY_SIGNAL_STRENGTH);
         }
+
+        if (!mShowImsRegState) {
+            removePreferenceFromScreen(KEY_IMS_REGISTRATION_STATE);
+        }
     }
 
     private void updatePhoneInfos() {
@@ -448,29 +471,36 @@
                     @Override
                     public void onServiceStateChanged(ServiceState serviceState) {
                         updateServiceState(serviceState);
+                        updateImsRegistrationState();
                     }
                 };
             }
         }
     }
+
     private OnTabChangeListener mTabListener = new OnTabChangeListener() {
         @Override
         public void onTabChanged(String tabId) {
-            final int slotId = Integer.parseInt(tabId);
-            mSir = mSelectableSubInfos.get(slotId);
-
-            // The User has changed tab; update the SIM information.
-            updatePhoneInfos();
-            mTelephonyManager.listen(mPhoneStateListener,
-                    PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
-                    | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
-                    | PhoneStateListener.LISTEN_SERVICE_STATE);
-            updateDataState();
-            updateNetworkType();
-            updatePreference();
+            doTabChanged(tabId);
         }
     };
 
+    @VisibleForTesting
+    void doTabChanged(String tabId) {
+        final int slotId = Integer.parseInt(tabId);
+        mSir = mSelectableSubInfos.get(slotId);
+
+        // The User has changed tab; update the SIM information.
+        updatePhoneInfos();
+        updatePreference(true /* isTabChanged */);
+        mTelephonyManager.listen(mPhoneStateListener,
+                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+                | PhoneStateListener.LISTEN_SERVICE_STATE);
+        updateDataState();
+        updateNetworkType();
+    }
+
     private TabContentFactory mEmptyTabContent = new TabContentFactory() {
         @Override
         public View createTabContent(String tag) {
diff --git a/src/com/android/settings/deviceinfo/Status.java b/src/com/android/settings/deviceinfo/Status.java
index 228774f..8073304 100644
--- a/src/com/android/settings/deviceinfo/Status.java
+++ b/src/com/android/settings/deviceinfo/Status.java
@@ -28,16 +28,12 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
-import android.os.PersistableBundle;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserManager;
 import android.provider.SearchIndexableResource;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
-import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -65,7 +61,6 @@
     private static final String KEY_WIMAX_MAC_ADDRESS = "wimax_mac_address";
     private static final String KEY_SIM_STATUS = "sim_status";
     private static final String KEY_IMEI_INFO = "imei_info";
-    private static final String KEY_IMS_REGISTRATION_STATE = "ims_reg_state";
 
     // Broadcasts to listen to for connectivity changes.
     private static final String[] CONNECTIVITY_INTENTS = {
@@ -95,7 +90,6 @@
     private Preference mIpAddress;
     private Preference mWifiMacAddress;
     private Preference mWimaxMacAddress;
-    private Preference mImsStatus;
 
     private Handler mHandler;
 
@@ -174,7 +168,6 @@
         mWifiMacAddress = findPreference(KEY_WIFI_MAC_ADDRESS);
         mWimaxMacAddress = findPreference(KEY_WIMAX_MAC_ADDRESS);
         mIpAddress = findPreference(KEY_IP_ADDRESS);
-        mImsStatus = findPreference(KEY_IMS_REGISTRATION_STATE);
 
         mRes = getResources();
         mUnavailable = mRes.getString(R.string.status_unavailable);
@@ -282,31 +275,11 @@
         }
     }
 
-    private void setImsRegistrationStatus() {
-        CarrierConfigManager configManager = (CarrierConfigManager)
-                getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        int subId = SubscriptionManager.getDefaultDataSubscriptionId();
-        PersistableBundle config = null;
-        if (configManager != null) {
-            config = configManager.getConfigForSubId(subId);
-        }
-        if (config != null && config.getBoolean(
-                CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL)) {
-            TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
-            mImsStatus.setSummary((tm != null && tm.isImsRegistered(subId)) ?
-                    R.string.ims_reg_status_registered : R.string.ims_reg_status_not_registered);
-        } else {
-            removePreferenceFromScreen(KEY_IMS_REGISTRATION_STATE);
-            mImsStatus = null;
-        }
-    }
-
     void updateConnectivity() {
         setWimaxStatus();
         setWifiStatus();
         setBtStatus();
         setIpAddressStatus();
-        setImsRegistrationStatus();
     }
 
     void updateTimes() {
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/SimStatusTest.java b/tests/robotests/src/com/android/settings/deviceinfo/SimStatusTest.java
new file mode 100644
index 0000000..4bcd104
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/SimStatusTest.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.PersistableBundle;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.telephony.Phone;
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowPhoneFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+        shadows = {
+                ShadowPhoneFactory.class
+        })
+public class SimStatusTest {
+    @Mock
+    private CarrierConfigManager mCarrierConfigManager;
+    @Mock
+    private Phone mPhone;
+    @Mock
+    private SubscriptionInfo mSubscriptionInfo;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private PreferenceScreen mMockScreen;
+    @Mock
+    private Preference mMockImsRegistrationStatePreference;
+    @Mock
+    private UserManager mMockUserManager;
+    @Mock
+    private Activity mMockActivity;
+
+    private Context mContext;
+    private Resources mResources;
+    private PersistableBundle mBundle;
+    private SimStatus mFragment;
+
+    private String mImsRegSummaryText;
+    private boolean mImsRegRemoved;
+    private boolean mResourceUpdated;
+    private List<SubscriptionInfo> mSelectableSubInfos = new ArrayList<>();
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mResources = spy(mContext.getResources());
+        mBundle = new PersistableBundle();
+        mFragment = spy(new SimStatus());
+
+        doReturn(mContext).when(mFragment).getContext();
+        doReturn(mMockScreen).when(mFragment).getPreferenceScreen();
+        doReturn(mMockImsRegistrationStatePreference).when(mFragment).findPreference(
+                SimStatus.KEY_IMS_REGISTRATION_STATE);
+        doReturn(mMockActivity).when(mFragment).getActivity();
+        doReturn(mMockUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
+        doReturn(mResources).when(mContext).getResources();
+        doReturn(0).when(mResources).getIdentifier(anyString(), anyString(), anyString());
+        doReturn(false).when(mResources).getBoolean(0);
+
+        doNothing().when(mFragment).addPreferencesFromResource(anyInt());
+
+        ReflectionHelpers.setField(mFragment, "mCarrierConfigManager", mCarrierConfigManager);
+        ReflectionHelpers.setField(mFragment, "mPhone", mPhone);
+        ReflectionHelpers.setField(mFragment, "mRes", mResources);
+        ReflectionHelpers.setField(mFragment, "mSir", mSubscriptionInfo);
+        ReflectionHelpers.setField(mFragment, "mTelephonyManager", mTelephonyManager);
+        mSelectableSubInfos.add(mSubscriptionInfo);
+        ReflectionHelpers.setField(mFragment, "mSelectableSubInfos", mSelectableSubInfos);
+
+        when(mSubscriptionInfo.getSubscriptionId()).thenReturn(0);
+        when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mBundle);
+        when(mMockActivity.createPackageContext(anyString(), anyInt())).thenReturn(mContext);
+
+        ShadowPhoneFactory.setPhone(mPhone);
+    }
+
+    @Test
+    public void updateImsRegistrationState_imsRegistered_shouldSetSummaryToRegisterd() {
+        when(mTelephonyManager.isImsRegistered(anyInt())).thenReturn(true);
+
+        mFragment.updateImsRegistrationState();
+
+        // Check "Registered" is set in the summary text
+        verify(mMockImsRegistrationStatePreference).setSummary(mContext.getString(
+                R.string.ims_reg_status_registered));
+    }
+
+    @Test
+    public void updateImsRegistrationState_imsNotRegistered_shouldSetSummaryToNotRegisterd() {
+        when(mTelephonyManager.isImsRegistered(anyInt())).thenReturn(false);
+
+        mFragment.updateImsRegistrationState();
+
+        // Check "Not registered" is set in the summary text
+        verify(mMockImsRegistrationStatePreference).setSummary(mContext.getString(
+                R.string.ims_reg_status_not_registered));
+    }
+
+    @Test
+    public void updatePreference_configTrue_shouldNotRemoveImsStatusPreference() {
+        mBundle.putBoolean(CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, true);
+
+        mFragment.updatePreference(false);
+
+        // Check the preference is not removed if the config is true
+        verify(mMockScreen, never()).removePreference(mMockImsRegistrationStatePreference);
+    }
+
+    @Test
+    public void updatePreference_configFalse_shouldRemoveImsStatusPreference() {
+        mBundle.putBoolean(CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false);
+
+        mFragment.updatePreference(false);
+
+        // Check the preference is removed if the config is false
+        verify(mMockScreen).removePreference(mMockImsRegistrationStatePreference);
+    }
+
+    @Test
+    public void updatePreference_tabChanged_shouldRemoveAndAddPreferences() {
+        mFragment.updatePreference(true);
+
+        // Check all preferences are removed once and added again
+        verify(mMockScreen).removeAll();
+        verify(mFragment).addPreferencesFromResource(R.xml.device_info_sim_status);
+    }
+
+    @Test
+    public void doTabChanged_shouldRemoveAndAddPreferences() {
+        mFragment.doTabChanged("0");
+
+        // Check all preferences are removed once and added again
+        verify(mMockScreen).removeAll();
+        verify(mFragment).addPreferencesFromResource(R.xml.device_info_sim_status);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPhoneFactory.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPhoneFactory.java
new file mode 100644
index 0000000..33017d1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPhoneFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.testutils.shadow;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(PhoneFactory.class)
+public class ShadowPhoneFactory {
+    private static Phone sMockPhone;
+
+    public static void setPhone(Phone phone) {
+        sMockPhone = phone;
+    }
+
+    @Implementation
+    public static Phone getPhone(int phoneId) {
+        return sMockPhone;
+    }
+}