Merge "Adjust Wifi Privacy preference."
diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml
index e54a90d..43cadab 100644
--- a/res/xml/network_setting_fragment.xml
+++ b/res/xml/network_setting_fragment.xml
@@ -73,7 +73,8 @@
 
     <Preference
         android:key="carrier_settings_euicc_key"
-        android:title="@string/carrier_settings_euicc" />
+        android:title="@string/carrier_settings_euicc"
+        settings:controller="com.android.settings.network.telephony.EuiccPreferenceController" />
 
     <PreferenceCategory
         android:key="calling"
@@ -81,20 +82,20 @@
 
         <PreferenceScreen
             android:key="wifi_calling_key"
-            android:title="@string/wifi_calling_settings_title">
-
+            android:title="@string/wifi_calling_settings_title"
+            settings:controller="com.android.settings.network.telephony.WifiCallingPreferenceController" >
             <intent android:action="android.intent.action.MAIN"
                     android:targetPackage="com.android.settings"
                     android:targetClass="com.android.settings.Settings$WifiCallingSettingsActivity">
                         <extra android:name="show_drawer_menu" android:value="true" />
             </intent>
-
         </PreferenceScreen>
 
         <SwitchPreference
             android:key="video_calling_key"
             android:title="@string/video_calling_settings_title"
-            android:persistent="true"/>
+            android:persistent="true"
+            settings:controller="com.android.settings.network.telephony.VideoCallingPreferenceController" />
 
     </PreferenceCategory>
 
diff --git a/src/com/android/settings/homepage/ContextualCardManager.java b/src/com/android/settings/homepage/ContextualCardManager.java
index 87b048e..6acf7b1 100644
--- a/src/com/android/settings/homepage/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/ContextualCardManager.java
@@ -115,10 +115,6 @@
 
     @Override
     public void onContextualCardUpdated(Map<Integer, List<ContextualCard>> updateList) {
-        //TODO(b/112245748): Should implement a DiffCallback.
-        //Keep the old list for comparison.
-        final List<ContextualCard> prevCards = mContextualCards;
-
         final Set<Integer> cardTypes = updateList.keySet();
         //Remove the existing data that matches the certain cardType before inserting new data.
         final List<ContextualCard> cardsToKeep = mContextualCards
diff --git a/src/com/android/settings/homepage/ContextualCardsAdapter.java b/src/com/android/settings/homepage/ContextualCardsAdapter.java
index 81cae39..8e6f805 100644
--- a/src/com/android/settings/homepage/ContextualCardsAdapter.java
+++ b/src/com/android/settings/homepage/ContextualCardsAdapter.java
@@ -17,11 +17,13 @@
 package com.android.settings.homepage;
 
 import android.content.Context;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
 import androidx.lifecycle.LifecycleOwner;
+import androidx.recyclerview.widget.DiffUtil;
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
@@ -108,14 +110,15 @@
     @Override
     public void onContextualCardUpdated(Map<Integer, List<ContextualCard>> cards) {
         final List<ContextualCard> contextualCards = cards.get(ContextualCard.CardType.DEFAULT);
-        //TODO(b/112245748): Should implement a DiffCallback so we can use notifyItemChanged()
-        // instead.
         if (contextualCards == null) {
             mContextualCards.clear();
+            notifyDataSetChanged();
         } else {
+            final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(
+                    new ContextualCardsDiffCallback(mContextualCards, contextualCards));
             mContextualCards.clear();
             mContextualCards.addAll(contextualCards);
+            diffResult.dispatchUpdatesTo(this);
         }
-        notifyDataSetChanged();
     }
 }
diff --git a/src/com/android/settings/homepage/ContextualCardsDiffCallback.java b/src/com/android/settings/homepage/ContextualCardsDiffCallback.java
new file mode 100644
index 0000000..84c6884
--- /dev/null
+++ b/src/com/android/settings/homepage/ContextualCardsDiffCallback.java
@@ -0,0 +1,58 @@
+/*
+ * 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.homepage;
+
+import androidx.recyclerview.widget.DiffUtil;
+
+import java.util.List;
+
+//TODO(b/117816826): add test cases for DiffUtil.
+/**
+ * A DiffCallback to calculate the difference between old and new {@link ContextualCard} List.
+ */
+public class ContextualCardsDiffCallback extends DiffUtil.Callback {
+
+    private final List<ContextualCard> mOldCards;
+    private final List<ContextualCard> mNewCards;
+
+    public ContextualCardsDiffCallback(List<ContextualCard> oldCards,
+            List<ContextualCard> newCards) {
+        mOldCards = oldCards;
+        mNewCards = newCards;
+    }
+
+    @Override
+    public int getOldListSize() {
+        return mOldCards.size();
+    }
+
+    @Override
+    public int getNewListSize() {
+        return mNewCards.size();
+    }
+
+    @Override
+    public boolean areItemsTheSame(int oldCardPosition, int newCardPosition) {
+        return mOldCards.get(oldCardPosition).getName().equals(
+                mNewCards.get(newCardPosition).getName());
+    }
+
+    @Override
+    public boolean areContentsTheSame(int oldCardPosition, int newCardPosition) {
+        return mOldCards.get(oldCardPosition).equals(mNewCards.get(newCardPosition));
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java
index fbbab14..6a9c8db 100644
--- a/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java
+++ b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java
@@ -37,6 +37,8 @@
 public class ConditionContextualCardController implements ContextualCardController,
         ConditionListener, LifecycleObserver, OnStart, OnStop {
 
+    private static final String TAG = "ConditionCtxCardCtrl";
+
     private final Context mContext;
     private final ConditionManager mConditionManager;
 
diff --git a/src/com/android/settings/homepage/conditional/ConditionManager.java b/src/com/android/settings/homepage/conditional/ConditionManager.java
index d1c9a27..036695f 100644
--- a/src/com/android/settings/homepage/conditional/ConditionManager.java
+++ b/src/com/android/settings/homepage/conditional/ConditionManager.java
@@ -107,12 +107,12 @@
      */
     public void startMonitoringStateChange() {
         if (mIsListeningToStateChange) {
-            Log.d(TAG, "Already listening to condition state changes, skipping");
-            return;
-        }
-        mIsListeningToStateChange = true;
-        for (ConditionalCardController controller : mCardControllers) {
-            controller.startMonitoringStateChange();
+            Log.d(TAG, "Already listening to condition state changes, skipping monitor setup");
+        } else {
+            mIsListeningToStateChange = true;
+            for (ConditionalCardController controller : mCardControllers) {
+                controller.startMonitoringStateChange();
+            }
         }
         // Force a refresh on listener
         onConditionChanged();
diff --git a/src/com/android/settings/homepage/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/slices/SliceContextualCardRenderer.java
index 5818e18..29e9aed 100644
--- a/src/com/android/settings/homepage/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/slices/SliceContextualCardRenderer.java
@@ -91,14 +91,16 @@
         if (sliceLiveData == null) {
             sliceLiveData = SliceLiveData.fromUri(mContext, uri);
             mSliceLiveDataMap.put(uri.toString(), sliceLiveData);
-            sliceLiveData.observe(mLifecycleOwner, slice -> {
-                if (slice == null) {
-                    Log.w(TAG, "Slice is null");
-                }
-                cardHolder.sliceView.setSlice(slice);
-            });
         }
 
+        sliceLiveData.removeObservers(mLifecycleOwner);
+        sliceLiveData.observe(mLifecycleOwner, slice -> {
+            if (slice == null) {
+                Log.w(TAG, "Slice is null");
+            }
+            cardHolder.sliceView.setSlice(slice);
+        });
+
         // Set this listener so we can log the interaction users make on the slice
         cardHolder.sliceView.setOnSliceActionListener(this);
     }
diff --git a/src/com/android/settings/network/telephony/CarrierPreferenceController.java b/src/com/android/settings/network/telephony/CarrierPreferenceController.java
index 957eaaa..406ef7b 100644
--- a/src/com/android/settings/network/telephony/CarrierPreferenceController.java
+++ b/src/com/android/settings/network/telephony/CarrierPreferenceController.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -37,6 +38,7 @@
     public CarrierPreferenceController(Context context, String key) {
         super(context, key);
         mCarrierConfigManager = new CarrierConfigManager(context);
+        mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     }
 
     public void init(int subId) {
diff --git a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java
index 07c58c1..b94f7e5 100644
--- a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java
+++ b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java
@@ -43,6 +43,7 @@
 
     public DataUsagePreferenceController(Context context, String key) {
         super(context, key);
+        mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     }
 
     @Override
diff --git a/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java b/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java
index d6773ed..cc8e78d 100644
--- a/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java
+++ b/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java
@@ -17,6 +17,7 @@
 package com.android.settings.network.telephony;
 
 import android.content.Context;
+import android.os.Looper;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneStateListener;
@@ -35,6 +36,9 @@
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Preference controller for "Enhanced 4G LTE"
  */
@@ -48,13 +52,15 @@
     @VisibleForTesting
     ImsManager mImsManager;
     private PhoneCallStateListener mPhoneStateListener;
+    private final List<On4gLteUpdateListener> m4gLteListeners;
     private int mSubId;
 
     public Enhanced4gLtePreferenceController(Context context, String key) {
         super(context, key);
         mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
-        mPhoneStateListener = new PhoneCallStateListener();
-        mSubId =  SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        m4gLteListeners = new ArrayList<>();
+        mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper());
+        mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     }
 
     @Override
@@ -104,6 +110,9 @@
     @Override
     public boolean setChecked(boolean isChecked) {
         mImsManager.setEnhanced4gLteModeSetting(isChecked);
+        for (final On4gLteUpdateListener lsn : m4gLteListeners) {
+            lsn.on4gLteUpdated();
+        }
         return true;
     }
 
@@ -112,13 +121,20 @@
         return mImsManager.isEnhanced4gLteModeSettingEnabledByUser();
     }
 
-    public void init(int subId) {
+    public Enhanced4gLtePreferenceController init(int subId) {
         mSubId = subId;
         mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
         mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
         if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
             mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId));
         }
+
+        return this;
+    }
+
+    public Enhanced4gLtePreferenceController addListener(On4gLteUpdateListener lsn) {
+        m4gLteListeners.add(lsn);
+        return this;
     }
 
     private boolean is4gLtePrefEnabled() {
@@ -131,6 +147,11 @@
     }
 
     private class PhoneCallStateListener extends PhoneStateListener {
+
+        public PhoneCallStateListener(Looper looper) {
+            super(looper);
+        }
+
         @Override
         public void onCallStateChanged(int state, String incomingNumber) {
             updateState(mPreference);
@@ -145,4 +166,11 @@
             mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
         }
     }
+
+    /**
+     * Update other preferences when 4gLte state is changed
+     */
+    public interface On4gLteUpdateListener {
+        void on4gLteUpdated();
+    }
 }
diff --git a/src/com/android/settings/network/telephony/EuiccPreferenceController.java b/src/com/android/settings/network/telephony/EuiccPreferenceController.java
new file mode 100644
index 0000000..8d03908
--- /dev/null
+++ b/src/com/android/settings/network/telephony/EuiccPreferenceController.java
@@ -0,0 +1,74 @@
+/*
+ * 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.network.telephony;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.PersistableBundle;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccManager;
+import android.text.TextUtils;
+
+import androidx.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+
+/**
+ * Preference controller for "Euicc preference"
+ */
+public class EuiccPreferenceController extends BasePreferenceController {
+
+    private TelephonyManager mTelephonyManager;
+    private int mSubId;
+
+    public EuiccPreferenceController(Context context, String key) {
+        super(context, key);
+        mTelephonyManager = context.getSystemService(TelephonyManager.class);
+        mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return MobileNetworkUtils.showEuiccSettings(mContext)
+                ? AVAILABLE
+                : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        return mTelephonyManager.getSimOperatorName();
+    }
+
+    public void init(int subId) {
+        mSubId = subId;
+        mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+            Intent intent = new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
+            mContext.startActivity(intent);
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
index 6958a11..065f182 100644
--- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
+++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
@@ -61,6 +61,7 @@
         super(context, key);
         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
         mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper()));
+        mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     }
 
     @Override
diff --git a/src/com/android/settings/network/telephony/MobileNetworkFragment.java b/src/com/android/settings/network/telephony/MobileNetworkFragment.java
index cb54e5b..b31c1a1 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkFragment.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkFragment.java
@@ -26,22 +26,17 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.Message;
 import android.os.PersistableBundle;
 import android.os.UserManager;
 import android.provider.SearchIndexableResource;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 import android.telephony.CarrierConfigManager;
-import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.euicc.EuiccManager;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.MenuItem;
@@ -51,9 +46,7 @@
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
 
-import com.android.ims.ImsConfig;
 import com.android.ims.ImsManager;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
@@ -93,8 +86,6 @@
     private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key";
     private static final String BUTTON_CARRIER_SETTINGS_EUICC_KEY =
             "carrier_settings_euicc_key";
-    private static final String BUTTON_WIFI_CALLING_KEY = "wifi_calling_key";
-    private static final String BUTTON_VIDEO_CALLING_KEY = "video_calling_key";
     private static final String BUTTON_MOBILE_DATA_ENABLE_KEY = "mobile_data_enable";
     private static final String BUTTON_DATA_USAGE_KEY = "data_usage_summary";
     private static final String BUTTON_ADVANCED_OPTIONS_KEY = "advanced_options";
@@ -120,14 +111,6 @@
     private CarrierConfigManager mCarrierConfigManager;
     private int mSubId;
 
-    //UI objects
-    private SwitchPreference mButton4glte;
-    private Preference mEuiccSettingsPref;
-    private PreferenceCategory mCallingCategory;
-    private Preference mWiFiCallingPref;
-    private SwitchPreference mVideoCallingPref;
-    private NetworkSelectListPreference mButtonNetworkSelect;
-
     private CdmaSystemSelectPreferenceController mCdmaSystemSelectPreferenceController;
     private CdmaSubscriptionPreferenceController mCdmaSubscriptionPreferenceController;
 
@@ -148,44 +131,6 @@
     private boolean mOnlyAutoSelectInHomeNW;
     private boolean mUnavailable;
 
-    private class PhoneCallStateListener extends PhoneStateListener {
-        /*
-         * Enable/disable the 'Enhanced 4G LTE Mode' when in/out of a call
-         * and depending on TTY mode and TTY support over VoLTE.
-         * @see android.telephony.PhoneStateListener#onCallStateChanged(int,
-         * java.lang.String)
-         */
-        @Override
-        public void onCallStateChanged(int state, String incomingNumber) {
-            if (DBG) log("PhoneStateListener.onCallStateChanged: state=" + state);
-
-            updateWiFiCallState();
-            updateVideoCallState();
-            updatePreferredNetworkType();
-        }
-
-        /**
-         * Listen to different subId if it's changed.
-         */
-        protected void updateSubscriptionId(Integer subId) {
-            if (subId.equals(PhoneCallStateListener.this.mSubId)) {
-                return;
-            }
-
-            PhoneCallStateListener.this.mSubId = subId;
-
-            mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
-
-            // Now, listen to new subId if it's valid.
-            if (SubscriptionManager.isValidSubscriptionId(subId)) {
-                mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE);
-            }
-        }
-    }
-
-    private final PhoneCallStateListener
-            mPhoneStateListener = new PhoneCallStateListener();
-
     @Override
     public int getMetricsCategory() {
         //TODO(b/114749736): add metrics id for it
@@ -222,15 +167,9 @@
                         REQUEST_CODE_EXIT_ECM);
             }
             return true;
-        } else if (preference == mEuiccSettingsPref) {
-            Intent intent = new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
-            startActivity(intent);
-            return true;
-        } else if (preference == mWiFiCallingPref || preference == mVideoCallingPref) {
-            return false;
         }
 
-        return true;
+        return false;
     }
 
     private final SubscriptionManager.OnSubscriptionsChangedListener
@@ -260,8 +199,6 @@
                     SubscriptionManager.getPhoneId(mSubId));
             mTelephonyManager = new TelephonyManager(getContext(), mSubId);
         }
-
-        mPhoneStateListener.updateSubscriptionId(mSubId);
     }
 
     @Override
@@ -277,13 +214,19 @@
         use(DataUsagePreferenceController.class).init(mSubId);
         use(PreferredNetworkModePreferenceController.class).init(mSubId);
         use(EnabledNetworkModePreferenceController.class).init(mSubId);
-        use(Enhanced4gLtePreferenceController.class).init(mSubId);
         use(DataServiceSetupPreferenceController.class).init(mSubId);
+        use(EuiccPreferenceController.class).init(mSubId);
+        use(WifiCallingPreferenceController.class).init(mSubId);
 
         mCdmaSystemSelectPreferenceController = use(CdmaSystemSelectPreferenceController.class);
         mCdmaSystemSelectPreferenceController.init(getPreferenceManager(), mSubId);
         mCdmaSubscriptionPreferenceController = use(CdmaSubscriptionPreferenceController.class);
         mCdmaSubscriptionPreferenceController.init(getPreferenceManager(), mSubId);
+
+        final VideoCallingPreferenceController videoCallingPreferenceController =
+                use(VideoCallingPreferenceController.class).init(mSubId);
+        use(Enhanced4gLtePreferenceController.class).init(mSubId)
+                .addListener(videoCallingPreferenceController);
     }
 
     @Override
@@ -303,12 +246,6 @@
                 Context.TELEPHONY_SERVICE);
         mCarrierConfigManager = new CarrierConfigManager(getContext());
 
-        mButton4glte = (SwitchPreference)findPreference(BUTTON_4G_LTE_KEY);
-
-        mCallingCategory = (PreferenceCategory) findPreference(CATEGORY_CALLING_KEY);
-        mWiFiCallingPref = findPreference(BUTTON_WIFI_CALLING_KEY);
-        mVideoCallingPref = (SwitchPreference) findPreference(BUTTON_VIDEO_CALLING_KEY);
-
         try {
             Context con = context.createPackageContext("com.android.systemui", 0);
             int id = con.getResources().getIdentifier("config_show4GForLTE",
@@ -319,12 +256,6 @@
             mShow4GForLTE = false;
         }
 
-        //get UI object references
-        PreferenceScreen prefSet = getPreferenceScreen();
-
-        mEuiccSettingsPref = prefSet.findPreference(BUTTON_CARRIER_SETTINGS_EUICC_KEY);
-        mEuiccSettingsPref.setOnPreferenceChangeListener(this);
-
         // Initialize mActiveSubInfo
         int max = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
         mActiveSubInfos = mSubscriptionManager.getActiveSubscriptionInfoList();
@@ -388,11 +319,6 @@
         // preferences.
         getPreferenceScreen().setEnabled(true);
 
-        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
-
-        // Video calling and WiFi calling state might have changed.
-        updateCallingCategory();
-
         mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
 
         final Context context = getContext();
@@ -450,12 +376,6 @@
 
         if (hasActiveSubscriptions) {
             updateBodyAdvancedFields(activity, prefSet, mSubId, hasActiveSubscriptions);
-        } else {
-            // Shows the "Carrier" preference that allows user to add a e-sim profile.
-            if (MobileNetworkUtils.showEuiccSettings(getContext())) {
-                mEuiccSettingsPref.setSummary(null /* summary */);
-                prefSet.addPreference(mEuiccSettingsPref);
-            }
         }
     }
 
@@ -468,16 +388,6 @@
             log("updateBody: isLteOnCdma=" + isLteOnCdma + " phoneSubId=" + phoneSubId);
         }
 
-        if (MobileNetworkUtils.showEuiccSettings(getContext())) {
-            prefSet.addPreference(mEuiccSettingsPref);
-            String spn = mTelephonyManager.getSimOperatorName();
-            if (TextUtils.isEmpty(spn)) {
-                mEuiccSettingsPref.setSummary(null);
-            } else {
-                mEuiccSettingsPref.setSummary(spn);
-            }
-        }
-
         int settingsNetworkMode = android.provider.Settings.Global.getInt(
                 getContext().getContentResolver(),
                 android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
@@ -518,9 +428,6 @@
                 android.provider.Settings.Global.getString(activity.getContentResolver(),
                         android.provider.Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL));
 
-        updatePreferredNetworkType();
-        updateCallingCategory();
-
         // Enable link to CMAS app settings depending on the value in config.xml.
         final boolean isCellBroadcastAppLinkEnabled = activity.getResources().getBoolean(
                 com.android.internal.R.bool.config_cellBroadcastAppLinks);
@@ -581,8 +488,6 @@
         super.onPause();
         if (DBG) log("onPause:+");
 
-        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
-
         mSubscriptionManager
                 .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
 
@@ -602,18 +507,6 @@
      */
     public boolean onPreferenceChange(Preference preference, Object objValue) {
         sendMetricsEventPreferenceChanged(getPreferenceScreen(), preference, objValue);
-        if (preference == mVideoCallingPref) {
-            // If mButton4glte is not checked, mVideoCallingPref should be disabled.
-            // So it only makes sense to call phoneMgr.enableVideoCalling if it's checked.
-            if (mButton4glte.isChecked()) {
-                mImsMgr.setVtSetting((boolean) objValue);
-                return true;
-            } else {
-                loge("mVideoCallingPref should be disabled if mButton4glte is not checked.");
-                mVideoCallingPref.setEnabled(false);
-                return false;
-            }
-        }
 
         updateBody();
         // always let the preference setting proceed.
@@ -655,111 +548,6 @@
         }
     }
 
-    private void updateWiFiCallState() {
-        if (mWiFiCallingPref == null || mCallingCategory == null) {
-            return;
-        }
-
-        // Removes the preference if the wifi calling is disabled.
-        if (!MobileNetworkUtils.isWifiCallingEnabled(getContext(),
-                SubscriptionManager.getPhoneId(mSubId))) {
-            mCallingCategory.removePreference(mWiFiCallingPref);
-            return;
-        }
-
-        final PhoneAccountHandle simCallManager =
-                TelecomManager.from(getContext()).getSimCallManager();
-
-        if (simCallManager != null) {
-            Intent intent = buildPhoneAccountConfigureIntent(getContext(), simCallManager);
-            PackageManager pm = getContext().getPackageManager();
-            List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0);
-            mWiFiCallingPref.setTitle(resolutions.get(0).loadLabel(pm));
-            mWiFiCallingPref.setSummary(null);
-            mWiFiCallingPref.setIntent(intent);
-        } else {
-            int resId = com.android.internal.R.string.wifi_calling_off_summary;
-            if (mImsMgr.isWfcEnabledByUser()) {
-                boolean isRoaming = mTelephonyManager.isNetworkRoaming();
-                int wfcMode = mImsMgr.getWfcMode(isRoaming);
-
-                switch (wfcMode) {
-                    case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
-                        resId = com.android.internal.R.string.wfc_mode_wifi_only_summary;
-                        break;
-                    case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED:
-                        resId = com.android.internal.R.string
-                                .wfc_mode_cellular_preferred_summary;
-                        break;
-                    case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED:
-                        resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary;
-                        break;
-                    default:
-                        if (DBG) log("Unexpected WFC mode value: " + wfcMode);
-                }
-            }
-            mWiFiCallingPref.setSummary(resId);
-        }
-
-        mCallingCategory.addPreference(mWiFiCallingPref);
-        mWiFiCallingPref.setEnabled(mTelephonyManager.getCallState(mSubId)
-                == TelephonyManager.CALL_STATE_IDLE && hasActiveSubscriptions());
-    }
-
-    private void updateVideoCallState() {
-        if (mVideoCallingPref == null || mCallingCategory == null) {
-            return;
-        }
-
-        PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
-
-        if (mImsMgr != null
-                && mImsMgr.isVtEnabledByPlatform()
-                && mImsMgr.isVtProvisionedOnDevice()
-                && MobileNetworkUtils.isImsServiceStateReady(mImsMgr)
-                && (carrierConfig.getBoolean(
-                CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
-                || mTelephonyManager.isDataEnabled())) {
-            mCallingCategory.addPreference(mVideoCallingPref);
-            if (!mButton4glte.isChecked()) {
-                mVideoCallingPref.setEnabled(false);
-                mVideoCallingPref.setChecked(false);
-            } else {
-                mVideoCallingPref.setEnabled(mTelephonyManager.getCallState(mSubId)
-                        == TelephonyManager.CALL_STATE_IDLE && hasActiveSubscriptions());
-                mVideoCallingPref.setChecked(mImsMgr.isVtEnabledByUser());
-                mVideoCallingPref.setOnPreferenceChangeListener(this);
-            }
-        } else {
-            mCallingCategory.removePreference(mVideoCallingPref);
-        }
-    }
-
-    private void updatePreferredNetworkType() {
-        boolean enabled = mTelephonyManager.getCallState(
-                mSubId) == TelephonyManager.CALL_STATE_IDLE
-                && hasActiveSubscriptions();
-        Log.i(LOG_TAG, "updatePreferredNetworkType: " + enabled);
-    }
-
-    private void updateCallingCategory() {
-        if (mCallingCategory == null) {
-            return;
-        }
-
-        updateWiFiCallState();
-        updateVideoCallState();
-
-        // If all items in calling category is removed, we remove it from
-        // the screen. Otherwise we'll see title of the category but nothing
-        // is in there.
-        if (mCallingCategory.getPreferenceCount() == 0) {
-            getPreferenceScreen().removePreference(mCallingCategory);
-        } else {
-            getPreferenceScreen().addPreference(mCallingCategory);
-        }
-    }
-
     private static void log(String msg) {
         Log.d(LOG_TAG, msg);
     }
@@ -880,9 +668,7 @@
         // For ListPreferences, we log it here without a value, only indicating it's clicked to
         // open the list dialog. When a value is chosen, another MetricsEvent is logged with
         // new value in onPreferenceChange.
-        if (preference == mEuiccSettingsPref
-                || preference == mWiFiCallingPref
-                || preference == preferenceScreen.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
+        if (preference == preferenceScreen.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
                 || preference == preferenceScreen.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)
                 || preference == preferenceScreen.findPreference(BUTTON_GSM_APN_EXPAND_KEY)
                 || preference == preferenceScreen.findPreference(BUTTON_CDMA_APN_EXPAND_KEY)
@@ -899,9 +685,7 @@
         }
 
         // MetricsEvent logging with new value, for SwitchPreferences and ListPreferences.
-        if (preference == mVideoCallingPref) {
-            MetricsLogger.action(getContext(), category, (Boolean) newValue);
-        } else if (preference == preferenceScreen
+        if (preference == preferenceScreen
                 .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
                 || preference == preferenceScreen
                 .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
@@ -915,12 +699,6 @@
 
         if (preference == null) {
             return MetricsProto.MetricsEvent.VIEW_UNKNOWN;
-        } else if (preference == mEuiccSettingsPref) {
-            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_EUICC_SETTING;
-        } else if (preference == mWiFiCallingPref) {
-            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_WIFI_CALLING;
-        } else if (preference == mVideoCallingPref) {
-            return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_VIDEO_CALLING_TOGGLE;
         } else if (preference == preferenceScreen
                 .findPreference(NetworkOperators.BUTTON_AUTO_SELECT_KEY)) {
             return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_AUTO_SELECT_NETWORK_TOGGLE;
@@ -1024,31 +802,4 @@
                     return result;
                 }
             };
-
-    private static final class SetPreferredNetworkAsyncTask extends AsyncTask<Void, Void, Boolean> {
-
-        private final TelephonyManager mTelephonyManager;
-        private final int mSubId;
-        private final int mNetworkType;
-        private final Message mCallback;
-
-        SetPreferredNetworkAsyncTask(
-                TelephonyManager tm, int subId, int networkType, Message callback) {
-            mTelephonyManager = tm;
-            mSubId = subId;
-            mNetworkType = networkType;
-            mCallback = callback;
-        }
-
-        @Override
-        protected Boolean doInBackground(Void... voids) {
-            return mTelephonyManager.setPreferredNetworkType(mSubId, mNetworkType);
-        }
-
-        @Override
-        protected void onPostExecute(Boolean isSuccessed) {
-            mCallback.obj = isSuccessed;
-            mCallback.sendToTarget();
-        }
-    }
 }
diff --git a/src/com/android/settings/network/telephony/RoamingPreferenceController.java b/src/com/android/settings/network/telephony/RoamingPreferenceController.java
index 3c1741b..b2eba08 100644
--- a/src/com/android/settings/network/telephony/RoamingPreferenceController.java
+++ b/src/com/android/settings/network/telephony/RoamingPreferenceController.java
@@ -61,6 +61,7 @@
         super(context, key);
         mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
         mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper()));
+        mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     }
 
     @Override
diff --git a/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java b/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java
new file mode 100644
index 0000000..1007ef8
--- /dev/null
+++ b/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java
@@ -0,0 +1,197 @@
+/*
+ * 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.network.telephony;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.ims.ImsManager;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+/**
+ * Preference controller for "Video Calling"
+ */
+public class VideoCallingPreferenceController extends TogglePreferenceController implements
+        LifecycleObserver, OnStart, OnStop,
+        Enhanced4gLtePreferenceController.On4gLteUpdateListener {
+
+    private Preference mPreference;
+    private TelephonyManager mTelephonyManager;
+    private CarrierConfigManager mCarrierConfigManager;
+    private PersistableBundle mCarrierConfig;
+    @VisibleForTesting
+    ImsManager mImsManager;
+    private PhoneCallStateListener mPhoneStateListener;
+    private DataContentObserver mDataContentObserver;
+    private int mSubId;
+
+    public VideoCallingPreferenceController(Context context, String key) {
+        super(context, key);
+        mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
+        mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper()));
+        mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper());
+        mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                && MobileNetworkUtils.isWifiCallingEnabled(mContext,
+                SubscriptionManager.getPhoneId(mSubId))
+                && isVideoCallEnabled()
+                ? AVAILABLE
+                : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public void onStart() {
+        mPhoneStateListener.register(mSubId);
+        mDataContentObserver.register(mContext, mSubId);
+    }
+
+    @Override
+    public void onStop() {
+        mPhoneStateListener.unregister();
+        mDataContentObserver.unRegister(mContext);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        final SwitchPreference switchPreference = (SwitchPreference) preference;
+        final boolean videoCallEnabled = isVideoCallEnabled();
+        switchPreference.setVisible(videoCallEnabled);
+        if (videoCallEnabled) {
+            final boolean is4gLteEnabled = mImsManager.isEnhanced4gLteModeSettingEnabledByUser()
+                    && mImsManager.isNonTtyOrTtyOnVolteEnabled();
+            preference.setEnabled(is4gLteEnabled &&
+                    mTelephonyManager.getCallState(mSubId) == TelephonyManager.CALL_STATE_IDLE);
+            switchPreference.setChecked(is4gLteEnabled && mImsManager.isVtEnabledByUser());
+        }
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        mImsManager.setVtSetting(isChecked);
+        return true;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return mImsManager.isVtEnabledByUser();
+    }
+
+    public VideoCallingPreferenceController init(int subId) {
+        mSubId = subId;
+        mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+        mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId));
+        }
+
+        return this;
+    }
+
+    @VisibleForTesting
+    boolean isVideoCallEnabled() {
+        return mCarrierConfig != null && mImsManager != null
+                && mImsManager.isVtEnabledByPlatform()
+                && mImsManager.isVtProvisionedOnDevice()
+                && MobileNetworkUtils.isImsServiceStateReady(mImsManager)
+                && (mCarrierConfig.getBoolean(
+                CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
+                || mTelephonyManager.isDataEnabled());
+    }
+
+    @Override
+    public void on4gLteUpdated() {
+        updateState(mPreference);
+    }
+
+    private class PhoneCallStateListener extends PhoneStateListener {
+
+        public PhoneCallStateListener(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void onCallStateChanged(int state, String incomingNumber) {
+            updateState(mPreference);
+        }
+
+        public void register(int subId) {
+            mSubId = subId;
+            mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE);
+        }
+
+        public void unregister() {
+            mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
+        }
+    }
+
+    /**
+     * Listener that listens mobile data state change.
+     */
+    public class DataContentObserver extends ContentObserver {
+
+        public DataContentObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            super.onChange(selfChange);
+            updateState(mPreference);
+        }
+
+        public void register(Context context, int subId) {
+            Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
+            if (TelephonyManager.getDefault().getSimCount() != 1) {
+                uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId);
+            }
+            context.getContentResolver().registerContentObserver(uri,
+                    false /* notifyForDescendants */, this /* observer */);
+        }
+
+        public void unRegister(Context context) {
+            context.getContentResolver().unregisterContentObserver(this);
+        }
+    }
+}
diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java
new file mode 100644
index 0000000..09bf2d7
--- /dev/null
+++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java
@@ -0,0 +1,155 @@
+/*
+ * 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.network.telephony;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Looper;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+import java.util.List;
+
+/**
+ * Preference controller for "Wifi Calling"
+ */
+public class WifiCallingPreferenceController extends BasePreferenceController implements
+        LifecycleObserver, OnStart, OnStop {
+
+    private TelephonyManager mTelephonyManager;
+    @VisibleForTesting
+    ImsManager mImsManager;
+    @VisibleForTesting
+    PhoneAccountHandle mSimCallManager;
+    private PhoneCallStateListener mPhoneStateListener;
+    private Preference mPreference;
+    private int mSubId;
+
+    public WifiCallingPreferenceController(Context context, String key) {
+        super(context, key);
+        mTelephonyManager = context.getSystemService(TelephonyManager.class);
+        mSimCallManager = context.getSystemService(TelecomManager.class).getSimCallManager();
+        mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper());
+        mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                && MobileNetworkUtils.isWifiCallingEnabled(mContext,
+                SubscriptionManager.getPhoneId(mSubId))
+                ? AVAILABLE
+                : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    @Override
+    public void onStart() {
+        mPhoneStateListener.register(mSubId);
+    }
+
+    @Override
+    public void onStop() {
+        mPhoneStateListener.unregister();
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        if (mSimCallManager != null) {
+            Intent intent = MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext,
+                    mSimCallManager);
+            final PackageManager pm = mContext.getPackageManager();
+            List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0);
+            preference.setTitle(resolutions.get(0).loadLabel(pm));
+            preference.setSummary(null);
+            preference.setIntent(intent);
+        } else {
+            int resId = com.android.internal.R.string.wifi_calling_off_summary;
+            if (mImsManager.isWfcEnabledByUser()) {
+                final boolean isRoaming = mTelephonyManager.isNetworkRoaming();
+                int wfcMode = mImsManager.getWfcMode(isRoaming);
+
+                switch (wfcMode) {
+                    case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
+                        resId = com.android.internal.R.string.wfc_mode_wifi_only_summary;
+                        break;
+                    case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED:
+                        resId = com.android.internal.R.string
+                                .wfc_mode_cellular_preferred_summary;
+                        break;
+                    case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED:
+                        resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary;
+                        break;
+                    default:
+                        break;
+                }
+            }
+            preference.setSummary(resId);
+        }
+        preference.setEnabled(
+                mTelephonyManager.getCallState(mSubId) == TelephonyManager.CALL_STATE_IDLE);
+    }
+
+    public void init(int subId) {
+        mSubId = subId;
+        mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+        mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId));
+    }
+
+    private class PhoneCallStateListener extends PhoneStateListener {
+
+        public PhoneCallStateListener(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void onCallStateChanged(int state, String incomingNumber) {
+            updateState(mPreference);
+        }
+
+        public void register(int subId) {
+            mSubId = subId;
+            mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE);
+        }
+
+        public void unregister() {
+            mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionManagerTest.java b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionManagerTest.java
index 014a4a1..3fbac17 100644
--- a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionManagerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionManagerTest.java
@@ -19,6 +19,8 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -53,7 +55,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
-        mManager = new ConditionManager(mContext, mConditionListener);
+        mManager = spy(new ConditionManager(mContext, mConditionListener));
 
         assertThat(mManager.mCandidates.size()).isEqualTo(mManager.mCardControllers.size());
 
@@ -94,11 +96,13 @@
 
     @Test
     public void startMonitoringStateChange_multipleTimes_shouldRegisterOnce() {
-        mManager.startMonitoringStateChange();
-        mManager.startMonitoringStateChange();
-        mManager.startMonitoringStateChange();
+        final int loopCount = 10;
+        for (int i = 0; i < loopCount; i++) {
+            mManager.startMonitoringStateChange();
+        }
 
         verify(mController).startMonitoringStateChange();
+        verify(mManager, times(loopCount)).onConditionChanged();
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java
index c5ca8d7..b8f8415 100644
--- a/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java
@@ -18,7 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 import android.content.Context;
 import android.net.Uri;
@@ -26,8 +26,10 @@
 import android.view.View;
 
 import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
+import androidx.slice.Slice;
 
 import com.android.settings.homepage.ContextualCard;
 import com.android.settings.homepage.PersonalSettingsFragment;
@@ -36,12 +38,16 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class SliceContextualCardRendererTest {
 
+    @Mock
+    private LiveData<Slice> mSliceLiveData;
+
     private Context mContext;
     private SliceContextualCardRenderer mRenderer;
     private LifecycleOwner mLifecycleOwner;
@@ -96,6 +102,16 @@
         assertThat(mRenderer.mSliceLiveDataMap.get(sliceUri).hasObservers()).isTrue();
     }
 
+    @Test
+    public void bindview_sliceLiveDataShouldRemoveObservers() {
+        final String sliceUri = "content://com.android.settings.slices/action/flashlight";
+        mRenderer.mSliceLiveDataMap.put(sliceUri, mSliceLiveData);
+
+        mRenderer.bindView(getSliceViewHolder(), buildContextualCard(sliceUri));
+
+        verify(mSliceLiveData).removeObservers(mLifecycleOwner);
+    }
+
     private RecyclerView.ViewHolder getSliceViewHolder() {
         final int viewType = mRenderer.getViewType();
         final RecyclerView recyclerView = new RecyclerView(mContext);
diff --git a/tests/robotests/src/com/android/settings/network/telephony/EuiccPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/EuiccPreferenceControllerTest.java
new file mode 100644
index 0000000..89e299c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/telephony/EuiccPreferenceControllerTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.network.telephony;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccManager;
+
+import androidx.preference.Preference;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class EuiccPreferenceControllerTest {
+    private static final int SUB_ID = 2;
+
+    @Mock
+    private TelephonyManager mTelephonyManager;
+
+    private EuiccPreferenceController mController;
+    private Preference mPreference;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+
+        mPreference = new Preference(mContext);
+        mController = new EuiccPreferenceController(mContext, "euicc");
+        mController.init(SUB_ID);
+        mPreference.setKey(mController.getPreferenceKey());
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_startActivity() {
+        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verify(mContext).startActivity(captor.capture());
+        assertThat(captor.getValue().getAction()).isEqualTo(
+                EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java
new file mode 100644
index 0000000..e50e264
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.network.telephony;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.telephony.ims.feature.ImsFeature;
+
+import androidx.preference.SwitchPreference;
+
+import com.android.ims.ImsManager;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class VideoCallingPreferenceControllerTest {
+    private static final int SUB_ID = 2;
+
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private ImsManager mImsManager;
+    @Mock
+    private CarrierConfigManager mCarrierConfigManager;
+
+    private VideoCallingPreferenceController mController;
+    private PersistableBundle mCarrierConfig;
+    private SwitchPreference mPreference;
+    private Context mContext;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(mTelephonyManager).when(mContext).getSystemService(TelephonyManager.class);
+        doReturn(mCarrierConfigManager).when(mContext).getSystemService(CarrierConfigManager.class);
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+
+        mCarrierConfig = new PersistableBundle();
+        mCarrierConfig.putBoolean(
+                CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true);
+        doReturn(mCarrierConfig).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
+
+        mPreference = new SwitchPreference(mContext);
+        mController = new VideoCallingPreferenceController(mContext, "wifi_calling");
+        mController.init(SUB_ID);
+        mController.mImsManager = mImsManager;
+        mPreference.setKey(mController.getPreferenceKey());
+
+        doReturn(true).when(mImsManager).isVtEnabledByPlatform();
+        doReturn(true).when(mImsManager).isVtProvisionedOnDevice();
+        doReturn(ImsFeature.STATE_READY).when(mImsManager).getImsServiceState();
+        doReturn(true).when(mTelephonyManager).isDataEnabled();
+    }
+
+    @Test
+    public void isVideoCallEnabled_allFlagsOn_returnTrue() {
+        assertThat(mController.isVideoCallEnabled()).isTrue();
+    }
+
+    @Test
+    public void isVideoCallEnabled_disabledByPlatform_returnFalse() {
+        doReturn(false).when(mImsManager).isVtEnabledByPlatform();
+
+        assertThat(mController.isVideoCallEnabled()).isFalse();
+    }
+
+    @Test
+    public void isVideoCallEnabled_dataDisabled_returnFalse() {
+        mCarrierConfig.putBoolean(
+                CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, false);
+        doReturn(false).when(mTelephonyManager).isDataEnabled();
+
+        assertThat(mController.isVideoCallEnabled()).isFalse();
+    }
+
+    @Test
+    public void updateState_4gLteOff_disabled() {
+        doReturn(false).when(mImsManager).isEnhanced4gLteModeSettingEnabledByUser();
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isFalse();
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void updateState_4gLteOnWithoutCall_checked() {
+        doReturn(true).when(mImsManager).isVtEnabledByUser();
+        doReturn(true).when(mImsManager).isEnhanced4gLteModeSettingEnabledByUser();
+        doReturn(true).when(mImsManager).isNonTtyOrTtyOnVolteEnabled();
+        doReturn(TelephonyManager.CALL_STATE_IDLE).when(mTelephonyManager).getCallState(SUB_ID);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isTrue();
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java
new file mode 100644
index 0000000..35297bd
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.network.telephony;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.TelephonyManager;
+
+import androidx.preference.Preference;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class WifiCallingPreferenceControllerTest {
+    private static final int SUB_ID = 2;
+
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private ImsManager mImsManager;
+
+    private WifiCallingPreferenceController mController;
+    private Preference mPreference;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+
+        mPreference = new Preference(mContext);
+        mController = new WifiCallingPreferenceController(mContext, "wifi_calling");
+        mController.init(SUB_ID);
+        mController.mImsManager = mImsManager;
+        mPreference.setKey(mController.getPreferenceKey());
+    }
+
+    @Test
+    public void updateState_noSimCallManager_setCorrectSummary() {
+        mController.mSimCallManager = null;
+        doReturn(true).when(mImsManager).isWfcEnabledByUser();
+        doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY).when(mImsManager).getWfcMode(
+                anyBoolean());
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getSummary()).isEqualTo(
+                mContext.getString(com.android.internal.R.string.wfc_mode_wifi_only_summary));
+    }
+
+    @Test
+    public void updateState_notCallIdle_disable() {
+        doReturn(TelephonyManager.CALL_STATE_RINGING).when(mTelephonyManager).getCallState(SUB_ID);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+
+}