MSIM support for Wi-Fi calling setting.

UI change to support Wi-Fi calling settings for multi-SIM devices.

Bug: b/65648147
Test: manual
Change-Id: Ia2e3a835400873bf6d8bfc7a7690d98e74049076
diff --git a/res/layout/wifi_calling_settings_preferences.xml b/res/layout/wifi_calling_settings_preferences.xml
new file mode 100644
index 0000000..4e64f40
--- /dev/null
+++ b/res/layout/wifi_calling_settings_preferences.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/tabs_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <com.android.settings.widget.SwitchBar
+        android:id="@+id/switch_bar"
+        android:layout_height="?android:attr/actionBarSize"
+        android:layout_width="match_parent"
+        android:background="@drawable/switchbar_background"
+        android:theme="?attr/switchBarTheme" />
+
+    <FrameLayout
+        android:id="@android:id/tabcontent"
+        android:layout_width="0dip"
+        android:layout_height="0dip" />
+
+    <FrameLayout
+        android:id="@+id/prefs_container"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:clipChildren="false"
+        android:clipToPadding="false"
+        android:smoothScrollbar="false" />
+
+</LinearLayout>
diff --git a/res/layout/wifi_calling_settings_tabs.xml b/res/layout/wifi_calling_settings_tabs.xml
new file mode 100644
index 0000000..1e27b47
--- /dev/null
+++ b/res/layout/wifi_calling_settings_tabs.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/tabs_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <com.android.settings.widget.SlidingTabLayout
+            xmlns:android="http://schemas.android.com/apk/res/android"
+            android:id="@+id/sliding_tabs"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:scrollbars="none"
+            android:fillViewport="true"/>
+
+        <com.android.settings.widget.RtlCompatibleViewPager
+            android:id="@+id/view_pager"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+
+</LinearLayout>
diff --git a/src/com/android/settings/WifiCallingSettings.java b/src/com/android/settings/WifiCallingSettings.java
index cb661ed..e872fb8 100644
--- a/src/com/android/settings/WifiCallingSettings.java
+++ b/src/com/android/settings/WifiCallingSettings.java
@@ -16,190 +16,38 @@
 
 package com.android.settings;
 
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
+import android.app.Fragment;
+import android.app.FragmentManager;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.os.Bundle;
-import android.os.PersistableBundle;
-import android.support.v7.preference.ListPreference;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceClickListener;
-import android.support.v7.preference.PreferenceScreen;
-import android.telephony.CarrierConfigManager;
-import android.telephony.PhoneStateListener;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
 import android.util.Log;
-import android.widget.Switch;
-import android.widget.TextView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
 
 import com.android.ims.ImsConfig;
 import com.android.ims.ImsManager;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.telephony.Phone;
-import com.android.settings.widget.SwitchBar;
+import com.android.settings.widget.RtlCompatibleViewPager;
+import com.android.settings.widget.SlidingTabLayout;
+
+import java.util.List;
 
 /**
- * "Wi-Fi Calling settings" screen.  This preference screen lets you
- * enable/disable Wi-Fi Calling and change Wi-Fi Calling mode.
+ * "Wi-Fi Calling settings" screen. This is the container fragment which holds
+ * {@link WifiCallingSettingsForSub} fragments.
  */
-public class WifiCallingSettings extends SettingsPreferenceFragment
-        implements SwitchBar.OnSwitchChangeListener,
-        Preference.OnPreferenceChangeListener {
-
+public class WifiCallingSettings extends SettingsPreferenceFragment {
     private static final String TAG = "WifiCallingSettings";
-
-    //String keys for preference lookup
-    private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
-    private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
-    private static final String PREFERENCE_EMERGENCY_ADDRESS = "emergency_address_key";
-
-    private static final int REQUEST_CHECK_WFC_EMERGENCY_ADDRESS = 1;
-
-    public static final String EXTRA_LAUNCH_CARRIER_APP = "EXTRA_LAUNCH_CARRIER_APP";
-
-    public static final int LAUCH_APP_ACTIVATE = 0;
-    public static final int LAUCH_APP_UPDATE = 1;
+    private List<SubscriptionInfo> mSil;
 
     //UI objects
-    private SwitchBar mSwitchBar;
-    private Switch mSwitch;
-    private ListPreference mButtonWfcMode;
-    private ListPreference mButtonWfcRoamingMode;
-    private Preference mUpdateAddress;
-    private TextView mEmptyView;
-
-    private boolean mValidListener = false;
-    private boolean mEditableWfcMode = true;
-    private boolean mEditableWfcRoamingMode = true;
-
-    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
-        /*
-         * Enable/disable controls 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) {
-            final SettingsActivity activity = (SettingsActivity) getActivity();
-            boolean isNonTtyOrTtyOnVolteEnabled = ImsManager
-                    .isNonTtyOrTtyOnVolteEnabled(activity);
-            final SwitchBar switchBar = activity.getSwitchBar();
-            boolean isWfcEnabled = switchBar.getSwitch().isChecked()
-                    && isNonTtyOrTtyOnVolteEnabled;
-
-            switchBar.setEnabled((state == TelephonyManager.CALL_STATE_IDLE)
-                    && isNonTtyOrTtyOnVolteEnabled);
-
-            boolean isWfcModeEditable = true;
-            boolean isWfcRoamingModeEditable = false;
-            final CarrierConfigManager configManager = (CarrierConfigManager)
-                    activity.getSystemService(Context.CARRIER_CONFIG_SERVICE);
-            if (configManager != null) {
-                PersistableBundle b = configManager.getConfig();
-                if (b != null) {
-                    isWfcModeEditable = b.getBoolean(
-                            CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
-                    isWfcRoamingModeEditable = b.getBoolean(
-                            CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
-                }
-            }
-
-            Preference pref = getPreferenceScreen().findPreference(BUTTON_WFC_MODE);
-            if (pref != null) {
-                pref.setEnabled(isWfcEnabled && isWfcModeEditable
-                        && (state == TelephonyManager.CALL_STATE_IDLE));
-            }
-            Preference pref_roam = getPreferenceScreen().findPreference(BUTTON_WFC_ROAMING_MODE);
-            if (pref_roam != null) {
-                pref_roam.setEnabled(isWfcEnabled && isWfcRoamingModeEditable
-                        && (state == TelephonyManager.CALL_STATE_IDLE));
-            }
-        }
-    };
-
-    private final OnPreferenceClickListener mUpdateAddressListener =
-            new OnPreferenceClickListener() {
-                /*
-                 * Launch carrier emergency address managemnent activity
-                 */
-                @Override
-                public boolean onPreferenceClick(Preference preference) {
-                    final Context context = getActivity();
-                    Intent carrierAppIntent = getCarrierActivityIntent(context);
-                    if (carrierAppIntent != null) {
-                        carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_UPDATE);
-                        startActivity(carrierAppIntent);
-                    }
-                    return true;
-                }
-    };
-
-    @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-
-        final SettingsActivity activity = (SettingsActivity) getActivity();
-
-        mSwitchBar = activity.getSwitchBar();
-        mSwitch = mSwitchBar.getSwitch();
-        mSwitchBar.show();
-
-        mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
-        setEmptyView(mEmptyView);
-        String emptyViewText = activity.getString(R.string.wifi_calling_off_explanation)
-                + activity.getString(R.string.wifi_calling_off_explanation_2);
-        mEmptyView.setText(emptyViewText);
-    }
-
-    @Override
-    public void onDestroyView() {
-        super.onDestroyView();
-        mSwitchBar.hide();
-    }
-
-    private void showAlert(Intent intent) {
-        Context context = getActivity();
-
-        CharSequence title = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_TITLE);
-        CharSequence message = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_MESSAGE);
-
-        AlertDialog.Builder builder = new AlertDialog.Builder(context);
-        builder.setMessage(message)
-                .setTitle(title)
-                .setIcon(android.R.drawable.ic_dialog_alert)
-                .setPositiveButton(android.R.string.ok, null);
-        AlertDialog dialog = builder.create();
-        dialog.show();
-    }
-
-    private IntentFilter mIntentFilter;
-
-    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (action.equals(ImsManager.ACTION_IMS_REGISTRATION_ERROR)) {
-                // If this fragment is active then we are immediately
-                // showing alert on screen. There is no need to add
-                // notification in this case.
-                //
-                // In order to communicate to ImsPhone that it should
-                // not show notification, we are changing result code here.
-                setResultCode(Activity.RESULT_CANCELED);
-
-                // UX requirement is to disable WFC in case of "permanent" registration failures.
-                mSwitch.setChecked(false);
-
-                showAlert(intent);
-            }
-        }
-    };
+    private RtlCompatibleViewPager mViewPager;
+    private WifiCallingViewPagerAdapter mPagerAdapter;
+    private SlidingTabLayout mTabLayout;
 
     @Override
     public int getMetricsCategory() {
@@ -207,242 +55,81 @@
     }
 
     @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View view = inflater.inflate(R.layout.wifi_calling_settings_tabs, container, false);
 
-        addPreferencesFromResource(R.xml.wifi_calling_settings);
+        mTabLayout = view.findViewById(R.id.sliding_tabs);
+        mViewPager = (RtlCompatibleViewPager) view.findViewById(R.id.view_pager);
 
-        mButtonWfcMode = (ListPreference) findPreference(BUTTON_WFC_MODE);
-        mButtonWfcMode.setOnPreferenceChangeListener(this);
+        mPagerAdapter = new WifiCallingViewPagerAdapter(getChildFragmentManager(), mViewPager);
+        mViewPager.setAdapter(mPagerAdapter);
 
-        mButtonWfcRoamingMode = (ListPreference) findPreference(BUTTON_WFC_ROAMING_MODE);
-        mButtonWfcRoamingMode.setOnPreferenceChangeListener(this);
-
-        mUpdateAddress = (Preference) findPreference(PREFERENCE_EMERGENCY_ADDRESS);
-        mUpdateAddress.setOnPreferenceClickListener(mUpdateAddressListener);
-
-        mIntentFilter = new IntentFilter();
-        mIntentFilter.addAction(ImsManager.ACTION_IMS_REGISTRATION_ERROR);
-
-        CarrierConfigManager configManager = (CarrierConfigManager)
-                getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        boolean isWifiOnlySupported = true;
-        if (configManager != null) {
-            PersistableBundle b = configManager.getConfig();
-            if (b != null) {
-                mEditableWfcMode = b.getBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
-                mEditableWfcRoamingMode = b.getBoolean(
-                        CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
-                isWifiOnlySupported = b.getBoolean(
-                        CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, true);
-            }
-        }
-
-        if (!isWifiOnlySupported) {
-            mButtonWfcMode.setEntries(R.array.wifi_calling_mode_choices_without_wifi_only);
-            mButtonWfcMode.setEntryValues(R.array.wifi_calling_mode_values_without_wifi_only);
-            mButtonWfcRoamingMode.setEntries(
-                    R.array.wifi_calling_mode_choices_v2_without_wifi_only);
-            mButtonWfcRoamingMode.setEntryValues(
-                    R.array.wifi_calling_mode_values_without_wifi_only);
-        }
+        return view;
     }
 
     @Override
-    public void onResume() {
-        super.onResume();
-
-        final Context context = getActivity();
-
-        // NOTE: Buttons will be enabled/disabled in mPhoneStateListener
-        boolean wfcEnabled = ImsManager.isWfcEnabledByUser(context)
-                && ImsManager.isNonTtyOrTtyOnVolteEnabled(context);
-        mSwitch.setChecked(wfcEnabled);
-        int wfcMode = ImsManager.getWfcMode(context, false);
-        int wfcRoamingMode = ImsManager.getWfcMode(context, true);
-        mButtonWfcMode.setValue(Integer.toString(wfcMode));
-        mButtonWfcRoamingMode.setValue(Integer.toString(wfcRoamingMode));
-        updateButtonWfcMode(context, wfcEnabled, wfcMode, wfcRoamingMode);
-
-        if (ImsManager.isWfcEnabledByPlatform(context)) {
-            TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
-            tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
-
-            mSwitchBar.addOnSwitchChangeListener(this);
-
-            mValidListener = true;
-        }
-
-        context.registerReceiver(mIntentReceiver, mIntentFilter);
-
-        Intent intent = getActivity().getIntent();
-        if (intent.getBooleanExtra(Phone.EXTRA_KEY_ALERT_SHOW, false)) {
-            showAlert(intent);
-        }
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        // TODO: besides in onCreate, we should also update subList when SIM / Sub status
+        // changes.
+        updateSubList();
     }
 
     @Override
-    public void onPause() {
-        super.onPause();
+    public void onStart() {
+        super.onStart();
 
-        final Context context = getActivity();
-
-        if (mValidListener) {
-            mValidListener = false;
-
-            TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
-            tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
-
-            mSwitchBar.removeOnSwitchChangeListener(this);
-        }
-
-        context.unregisterReceiver(mIntentReceiver);
-    }
-
-    /**
-     * Listens to the state change of the switch.
-     */
-    @Override
-    public void onSwitchChanged(Switch switchView, boolean isChecked) {
-        final Context context = getActivity();
-        Log.d(TAG, "onSwitchChanged(" + isChecked + ")");
-
-        if (!isChecked) {
-            updateWfcMode(context, false);
-            return;
-        }
-
-        // Call address management activity before turning on WFC
-        Intent carrierAppIntent = getCarrierActivityIntent(context);
-        if (carrierAppIntent != null) {
-            carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_ACTIVATE);
-            startActivityForResult(carrierAppIntent, REQUEST_CHECK_WFC_EMERGENCY_ADDRESS);
+        if (mSil != null && mSil.size() > 1) {
+            mTabLayout.setViewPager(mViewPager);
         } else {
-            updateWfcMode(context, true);
+            mTabLayout.setVisibility(View.GONE);
         }
     }
 
-    /*
-     * Get the Intent to launch carrier emergency address management activity.
-     * Return null when no activity found.
-     */
-    private static Intent getCarrierActivityIntent(Context context) {
-        // Retrive component name from carrirt config
-        CarrierConfigManager configManager = context.getSystemService(CarrierConfigManager.class);
-        if (configManager == null) return null;
+    private final class WifiCallingViewPagerAdapter extends FragmentPagerAdapter {
+        private final RtlCompatibleViewPager mViewPager;
 
-        PersistableBundle bundle = configManager.getConfig();
-        if (bundle == null) return null;
-
-        String carrierApp = bundle.getString(
-                CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING);
-        if (TextUtils.isEmpty(carrierApp)) return null;
-
-        ComponentName componentName = ComponentName.unflattenFromString(carrierApp);
-        if (componentName == null) return null;
-
-        // Build and return intent
-        Intent intent = new Intent();
-        intent.setComponent(componentName);
-        return intent;
-    }
-
-    /*
-     * Turn on/off WFC mode with ImsManager and update UI accordingly
-     */
-    private void updateWfcMode(Context context, boolean wfcEnabled) {
-        Log.i(TAG, "updateWfcMode(" + wfcEnabled + ")");
-        ImsManager.setWfcSetting(context, wfcEnabled);
-
-        int wfcMode = ImsManager.getWfcMode(context, false);
-        int wfcRoamingMode = ImsManager.getWfcMode(context, true);
-        updateButtonWfcMode(context, wfcEnabled, wfcMode, wfcRoamingMode);
-        if (wfcEnabled) {
-            mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), wfcMode);
-        } else {
-            mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), -1);
+        public WifiCallingViewPagerAdapter(FragmentManager fragmentManager,
+                RtlCompatibleViewPager viewPager) {
+            super(fragmentManager);
+            mViewPager = viewPager;
         }
-    }
 
-    @Override
-    public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-
-        final Context context = getActivity();
-
-        if (requestCode == REQUEST_CHECK_WFC_EMERGENCY_ADDRESS) {
-            Log.d(TAG, "WFC emergency address activity result = " + resultCode);
-
-            if (resultCode == Activity.RESULT_OK) {
-                updateWfcMode(context, true);
-            }
+        @Override
+        public CharSequence getPageTitle(int position) {
+            return String.valueOf(mSil.get(position).getDisplayName());
         }
-    }
 
-    private void updateButtonWfcMode(Context context, boolean wfcEnabled,
-                                     int wfcMode, int wfcRoamingMode) {
-        mButtonWfcMode.setSummary(getWfcModeSummary(context, wfcMode));
-        mButtonWfcMode.setEnabled(wfcEnabled && mEditableWfcMode);
-        // mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value.
-        mButtonWfcRoamingMode.setEnabled(wfcEnabled && mEditableWfcRoamingMode);
+        @Override
+        public Fragment getItem(int position) {
+            Log.d(TAG, "Adapter getItem " + position);
+            final Bundle args = new Bundle();
+            args.putInt(WifiCallingSettingsForSub.FRAGMENT_BUNDLE_SUBID,
+                    mSil.get(position).getSubscriptionId());
+            WifiCallingSettingsForSub fragment = new WifiCallingSettingsForSub();
+            fragment.setArguments(args);
 
-        final PreferenceScreen preferenceScreen = getPreferenceScreen();
-        boolean updateAddressEnabled = (getCarrierActivityIntent(context) != null);
-        if (wfcEnabled) {
-            if (mEditableWfcMode) {
-                preferenceScreen.addPreference(mButtonWfcMode);
+            return fragment;
+        }
+
+        @Override
+        public Object instantiateItem(ViewGroup container, int position) {
+            Log.d(TAG, "Adapter instantiateItem " + position);
+            return super.instantiateItem(container,
+                    mViewPager.getRtlAwareIndex(position));
+        }
+
+        @Override
+        public int getCount() {
+            if (mSil == null) {
+                Log.d(TAG, "Adapter getCount null mSil ");
+                return 0;
             } else {
-                // Don't show WFC (home) preference if it's not editable.
-                preferenceScreen.removePreference(mButtonWfcMode);
-            }
-            if (mEditableWfcRoamingMode) {
-                preferenceScreen.addPreference(mButtonWfcRoamingMode);
-            } else {
-                // Don't show WFC roaming preference if it's not editable.
-                preferenceScreen.removePreference(mButtonWfcRoamingMode);
-            }
-            if (updateAddressEnabled) {
-                preferenceScreen.addPreference(mUpdateAddress);
-            } else {
-                preferenceScreen.removePreference(mUpdateAddress);
-            }
-        } else {
-            preferenceScreen.removePreference(mButtonWfcMode);
-            preferenceScreen.removePreference(mButtonWfcRoamingMode);
-            preferenceScreen.removePreference(mUpdateAddress);
-        }
-    }
-
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        final Context context = getActivity();
-        if (preference == mButtonWfcMode) {
-            mButtonWfcMode.setValue((String) newValue);
-            int buttonMode = Integer.valueOf((String) newValue);
-            int currentWfcMode = ImsManager.getWfcMode(context, false);
-            if (buttonMode != currentWfcMode) {
-                ImsManager.setWfcMode(context, buttonMode, false);
-                mButtonWfcMode.setSummary(getWfcModeSummary(context, buttonMode));
-                mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), buttonMode);
-            }
-            if (!mEditableWfcRoamingMode) {
-                int currentWfcRoamingMode = ImsManager.getWfcMode(context, true);
-                if (buttonMode != currentWfcRoamingMode) {
-                    ImsManager.setWfcMode(context, buttonMode, true);
-                    // mButtonWfcRoamingMode.setSummary is not needed; summary is selected value
-                }
-            }
-        } else if (preference == mButtonWfcRoamingMode) {
-            mButtonWfcRoamingMode.setValue((String) newValue);
-            int buttonMode = Integer.valueOf((String) newValue);
-            int currentMode = ImsManager.getWfcMode(context, true);
-            if (buttonMode != currentMode) {
-                ImsManager.setWfcMode(context, buttonMode, true);
-                // mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value.
-                mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), buttonMode);
+                Log.d(TAG, "Adapter getCount " + mSil.size());
+                return mSil.size();
             }
         }
-        return true;
     }
 
     public static int getWfcModeSummary(Context context, int wfcMode) {
@@ -464,4 +151,22 @@
         }
         return resId;
     }
+
+    private void updateSubList() {
+        mSil = SubscriptionManager.from(getActivity()).getActiveSubscriptionInfoList();
+
+        // Only config Wfc if it's enabled by platform.
+        if (mSil == null) {
+            return;
+        }
+        for (int i = 0; i < mSil.size();) {
+            ImsManager imsManager = ImsManager.getInstance(getActivity(),
+                    mSil.get(i).getSimSlotIndex());
+            if (!imsManager.isWfcEnabledByPlatform()) {
+                mSil.remove(i);
+            } else {
+                i++;
+            }
+        }
+    }
 }
diff --git a/src/com/android/settings/WifiCallingSettingsForSub.java b/src/com/android/settings/WifiCallingSettingsForSub.java
new file mode 100644
index 0000000..57a4ab2
--- /dev/null
+++ b/src/com/android/settings/WifiCallingSettingsForSub.java
@@ -0,0 +1,521 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.PersistableBundle;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceClickListener;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.telephony.Phone;
+import com.android.settings.widget.SwitchBar;
+
+/**
+ * This is the inner class of {@link WifiCallingSettings} fragment.
+ * The preference screen lets you enable/disable Wi-Fi Calling and change Wi-Fi Calling mode.
+ */
+public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
+        implements SwitchBar.OnSwitchChangeListener,
+        Preference.OnPreferenceChangeListener {
+    private static final String TAG = "WifiCallingSettingsForSub";
+
+    //String keys for preference lookup
+    private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
+    private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
+    private static final String PREFERENCE_EMERGENCY_ADDRESS = "emergency_address_key";
+
+    private static final int REQUEST_CHECK_WFC_EMERGENCY_ADDRESS = 1;
+
+    public static final String EXTRA_LAUNCH_CARRIER_APP = "EXTRA_LAUNCH_CARRIER_APP";
+
+    protected static final String FRAGMENT_BUNDLE_SUBID = "subId";
+
+    public static final int LAUCH_APP_ACTIVATE = 0;
+    public static final int LAUCH_APP_UPDATE = 1;
+
+    //UI objects
+    private SwitchBar mSwitchBar;
+    private Switch mSwitch;
+    private ListPreference mButtonWfcMode;
+    private ListPreference mButtonWfcRoamingMode;
+    private Preference mUpdateAddress;
+    private TextView mEmptyView;
+
+    private boolean mValidListener = false;
+    private boolean mEditableWfcMode = true;
+    private boolean mEditableWfcRoamingMode = true;
+
+    private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    private ImsManager mImsManager;
+
+    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+        /*
+         * Enable/disable controls 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) {
+            final SettingsActivity activity = (SettingsActivity) getActivity();
+            boolean isNonTtyOrTtyOnVolteEnabled = mImsManager.isNonTtyOrTtyOnVolteEnabled();
+            boolean isWfcEnabled = mSwitchBar.isChecked()
+                    && isNonTtyOrTtyOnVolteEnabled;
+
+            mSwitchBar.setEnabled((state == TelephonyManager.CALL_STATE_IDLE)
+                    && isNonTtyOrTtyOnVolteEnabled);
+
+            boolean isWfcModeEditable = true;
+            boolean isWfcRoamingModeEditable = false;
+            final CarrierConfigManager configManager = (CarrierConfigManager)
+                    activity.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+            if (configManager != null) {
+                PersistableBundle b = configManager.getConfigForSubId(mSubId);
+                if (b != null) {
+                    isWfcModeEditable = b.getBoolean(
+                            CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
+                    isWfcRoamingModeEditable = b.getBoolean(
+                            CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
+                }
+            }
+
+            Preference pref = getPreferenceScreen().findPreference(BUTTON_WFC_MODE);
+            if (pref != null) {
+                pref.setEnabled(isWfcEnabled && isWfcModeEditable
+                        && (state == TelephonyManager.CALL_STATE_IDLE));
+            }
+            Preference pref_roam =
+                    getPreferenceScreen().findPreference(BUTTON_WFC_ROAMING_MODE);
+            if (pref_roam != null) {
+                pref_roam.setEnabled(isWfcEnabled && isWfcRoamingModeEditable
+                        && (state == TelephonyManager.CALL_STATE_IDLE));
+            }
+        }
+    };
+
+    @Override
+    protected int getHelpResource() {
+        // Helper resource is already defined in the container fragment.
+        return 0;
+    }
+
+    private final OnPreferenceClickListener mUpdateAddressListener =
+            new OnPreferenceClickListener() {
+                /*
+                 * Launch carrier emergency address managemnent activity
+                 */
+                @Override
+                public boolean onPreferenceClick(Preference preference) {
+                    Intent carrierAppIntent = getCarrierActivityIntent();
+                    if (carrierAppIntent != null) {
+                        carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_UPDATE);
+                        startActivity(carrierAppIntent);
+                    }
+                    return true;
+                }
+            };
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        final SettingsActivity activity = (SettingsActivity) getActivity();
+
+        mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
+        setEmptyView(mEmptyView);
+        String emptyViewText = activity.getString(R.string.wifi_calling_off_explanation)
+                + activity.getString(R.string.wifi_calling_off_explanation_2);
+        mEmptyView.setText(emptyViewText);
+
+        mSwitchBar = getView().findViewById(R.id.switch_bar);
+        mSwitchBar.show();
+        mSwitch = mSwitchBar.getSwitch();
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        mSwitchBar.hide();
+    }
+
+    private void showAlert(Intent intent) {
+        Context context = getActivity();
+
+        CharSequence title = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_TITLE);
+        CharSequence message = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_MESSAGE);
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setMessage(message)
+                .setTitle(title)
+                .setIcon(android.R.drawable.ic_dialog_alert)
+                .setPositiveButton(android.R.string.ok, null);
+        AlertDialog dialog = builder.create();
+        dialog.show();
+    }
+
+    private IntentFilter mIntentFilter;
+
+    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(ImsManager.ACTION_IMS_REGISTRATION_ERROR)) {
+                // If this fragment is active then we are immediately
+                // showing alert on screen. There is no need to add
+                // notification in this case.
+                //
+                // In order to communicate to ImsPhone that it should
+                // not show notification, we are changing result code here.
+                setResultCode(Activity.RESULT_CANCELED);
+
+                // UX requirement is to disable WFC in case of "permanent" registration failures.
+                mSwitch.setChecked(false);
+
+                showAlert(intent);
+            }
+        }
+    };
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.WIFI_CALLING_FOR_SUB;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        addPreferencesFromResource(R.xml.wifi_calling_settings);
+
+        // SubId should always be specified when creating this fragment. Either through
+        // fragment.setArguments() or through savedInstanceState.
+        if (getArguments() != null && getArguments().containsKey(FRAGMENT_BUNDLE_SUBID))
+        {
+            mSubId = getArguments().getInt(FRAGMENT_BUNDLE_SUBID);
+        } else if (savedInstanceState != null) {
+            mSubId = savedInstanceState.getInt(
+                    FRAGMENT_BUNDLE_SUBID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        }
+
+        mImsManager = ImsManager.getInstance(
+                getActivity(), SubscriptionManager.getPhoneId(mSubId));
+
+        mButtonWfcMode = (ListPreference) findPreference(BUTTON_WFC_MODE);
+        mButtonWfcMode.setOnPreferenceChangeListener(this);
+
+        mButtonWfcRoamingMode = (ListPreference) findPreference(BUTTON_WFC_ROAMING_MODE);
+        mButtonWfcRoamingMode.setOnPreferenceChangeListener(this);
+
+        mUpdateAddress = (Preference) findPreference(PREFERENCE_EMERGENCY_ADDRESS);
+        mUpdateAddress.setOnPreferenceClickListener(mUpdateAddressListener);
+
+        mIntentFilter = new IntentFilter();
+        mIntentFilter.addAction(ImsManager.ACTION_IMS_REGISTRATION_ERROR);
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putInt(FRAGMENT_BUNDLE_SUBID, mSubId);
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+
+        View view = inflater.inflate(
+                R.layout.wifi_calling_settings_preferences, container, false);
+
+        final ViewGroup prefs_container = view.findViewById(R.id.prefs_container);
+        Utils.prepareCustomPreferencesList(container, view, prefs_container, false);
+        View prefs = super.onCreateView(inflater, prefs_container, savedInstanceState);
+        prefs_container.addView(prefs);
+
+        return view;
+    }
+
+    private void updateBody() {
+        CarrierConfigManager configManager = (CarrierConfigManager)
+                getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        boolean isWifiOnlySupported = true;
+
+        if (configManager != null) {
+            PersistableBundle b = configManager.getConfigForSubId(mSubId);
+            if (b != null) {
+                mEditableWfcMode = b.getBoolean(
+                        CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
+                mEditableWfcRoamingMode = b.getBoolean(
+                        CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
+                isWifiOnlySupported = b.getBoolean(
+                        CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, true);
+            }
+        }
+
+        if (!isWifiOnlySupported) {
+            mButtonWfcMode.setEntries(R.array.wifi_calling_mode_choices_without_wifi_only);
+            mButtonWfcMode.setEntryValues(R.array.wifi_calling_mode_values_without_wifi_only);
+            mButtonWfcRoamingMode.setEntries(
+                    R.array.wifi_calling_mode_choices_v2_without_wifi_only);
+            mButtonWfcRoamingMode.setEntryValues(
+                    R.array.wifi_calling_mode_values_without_wifi_only);
+        }
+
+
+        // NOTE: Buttons will be enabled/disabled in mPhoneStateListener
+        boolean wfcEnabled = mImsManager.isWfcEnabledByUser()
+                && mImsManager.isNonTtyOrTtyOnVolteEnabled();
+        mSwitch.setChecked(wfcEnabled);
+        int wfcMode = mImsManager.getWfcMode(false);
+        int wfcRoamingMode = mImsManager.getWfcMode(true);
+        mButtonWfcMode.setValue(Integer.toString(wfcMode));
+        mButtonWfcRoamingMode.setValue(Integer.toString(wfcRoamingMode));
+        updateButtonWfcMode(wfcEnabled, wfcMode, wfcRoamingMode);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        final Context context = getActivity();
+
+        updateBody();
+
+        if (mImsManager.isWfcEnabledByPlatform()) {
+            TelephonyManager tm =
+                    (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+            tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+
+            mSwitchBar.addOnSwitchChangeListener(this);
+
+            mValidListener = true;
+        }
+
+        context.registerReceiver(mIntentReceiver, mIntentFilter);
+
+        Intent intent = getActivity().getIntent();
+        if (intent.getBooleanExtra(Phone.EXTRA_KEY_ALERT_SHOW, false)) {
+            showAlert(intent);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        final Context context = getActivity();
+
+        if (mValidListener) {
+            mValidListener = false;
+
+            TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+            tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+
+            mSwitchBar.removeOnSwitchChangeListener(this);
+        }
+
+        context.unregisterReceiver(mIntentReceiver);
+    }
+
+    /**
+     * Listens to the state change of the switch.
+     */
+    @Override
+    public void onSwitchChanged(Switch switchView, boolean isChecked) {
+        Log.d(TAG, "onSwitchChanged(" + isChecked + ")");
+
+        if (!isChecked) {
+            updateWfcMode(false);
+            return;
+        }
+
+        // Call address management activity before turning on WFC
+        Intent carrierAppIntent = getCarrierActivityIntent();
+        if (carrierAppIntent != null) {
+            carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_ACTIVATE);
+            startActivityForResult(carrierAppIntent, REQUEST_CHECK_WFC_EMERGENCY_ADDRESS);
+        } else {
+            updateWfcMode(true);
+        }
+    }
+
+    /*
+     * Get the Intent to launch carrier emergency address management activity.
+     * Return null when no activity found.
+     */
+    private Intent getCarrierActivityIntent() {
+        // Retrive component name from carrier config
+        CarrierConfigManager configManager =
+                getActivity().getSystemService(CarrierConfigManager.class);
+        if (configManager == null) return null;
+
+        PersistableBundle bundle = configManager.getConfigForSubId(mSubId);
+        if (bundle == null) return null;
+
+        String carrierApp = bundle.getString(
+                CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING);
+        if (TextUtils.isEmpty(carrierApp)) return null;
+
+        ComponentName componentName = ComponentName.unflattenFromString(carrierApp);
+        if (componentName == null) return null;
+
+        // Build and return intent
+        Intent intent = new Intent();
+        intent.setComponent(componentName);
+        return intent;
+    }
+
+    /*
+     * Turn on/off WFC mode with ImsManager and update UI accordingly
+     */
+    private void updateWfcMode(boolean wfcEnabled) {
+        Log.i(TAG, "updateWfcMode(" + wfcEnabled + ")");
+        mImsManager.setWfcSetting(wfcEnabled);
+
+        int wfcMode = mImsManager.getWfcMode(false);
+        int wfcRoamingMode = mImsManager.getWfcMode(true);
+        updateButtonWfcMode(wfcEnabled, wfcMode, wfcRoamingMode);
+        if (wfcEnabled) {
+            mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), wfcMode);
+        } else {
+            mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), -1);
+        }
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+
+        final Context context = getActivity();
+
+        if (requestCode == REQUEST_CHECK_WFC_EMERGENCY_ADDRESS) {
+            Log.d(TAG, "WFC emergency address activity result = " + resultCode);
+
+            if (resultCode == Activity.RESULT_OK) {
+                updateWfcMode(true);
+            }
+        }
+    }
+
+    private void updateButtonWfcMode(boolean wfcEnabled,
+            int wfcMode, int wfcRoamingMode) {
+        mButtonWfcMode.setSummary(getWfcModeSummary(wfcMode));
+        mButtonWfcMode.setEnabled(wfcEnabled && mEditableWfcMode);
+        // mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value.
+        mButtonWfcRoamingMode.setEnabled(wfcEnabled && mEditableWfcRoamingMode);
+
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        boolean updateAddressEnabled = (getCarrierActivityIntent() != null);
+        if (wfcEnabled) {
+            if (mEditableWfcMode) {
+                preferenceScreen.addPreference(mButtonWfcMode);
+            } else {
+                // Don't show WFC (home) preference if it's not editable.
+                preferenceScreen.removePreference(mButtonWfcMode);
+            }
+            if (mEditableWfcRoamingMode) {
+                preferenceScreen.addPreference(mButtonWfcRoamingMode);
+            } else {
+                // Don't show WFC roaming preference if it's not editable.
+                preferenceScreen.removePreference(mButtonWfcRoamingMode);
+            }
+            if (updateAddressEnabled) {
+                preferenceScreen.addPreference(mUpdateAddress);
+            } else {
+                preferenceScreen.removePreference(mUpdateAddress);
+            }
+        } else {
+            preferenceScreen.removePreference(mButtonWfcMode);
+            preferenceScreen.removePreference(mButtonWfcRoamingMode);
+            preferenceScreen.removePreference(mUpdateAddress);
+        }
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        if (preference == mButtonWfcMode) {
+            Log.d(TAG, "onPreferenceChange mButtonWfcMode " + newValue);
+            mButtonWfcMode.setValue((String) newValue);
+            int buttonMode = Integer.valueOf((String) newValue);
+            int currentWfcMode = mImsManager.getWfcMode(false);
+            if (buttonMode != currentWfcMode) {
+                mImsManager.setWfcMode(buttonMode, false);
+                mButtonWfcMode.setSummary(getWfcModeSummary(buttonMode));
+                mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), buttonMode);
+            }
+            if (!mEditableWfcRoamingMode) {
+                int currentWfcRoamingMode = mImsManager.getWfcMode(true);
+                if (buttonMode != currentWfcRoamingMode) {
+                    mImsManager.setWfcMode(buttonMode, true);
+                    // mButtonWfcRoamingMode.setSummary is not needed; summary is selected value
+                }
+            }
+        } else if (preference == mButtonWfcRoamingMode) {
+            mButtonWfcRoamingMode.setValue((String) newValue);
+            int buttonMode = Integer.valueOf((String) newValue);
+            int currentMode = mImsManager.getWfcMode(true);
+            if (buttonMode != currentMode) {
+                mImsManager.setWfcMode(buttonMode, true);
+                // mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value.
+                mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), buttonMode);
+            }
+        }
+        return true;
+    }
+
+    private int getWfcModeSummary(int wfcMode) {
+        int resId = com.android.internal.R.string.wifi_calling_off_summary;
+        if (mImsManager.isWfcEnabledByUser()) {
+            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:
+                    Log.e(TAG, "Unexpected WFC mode value: " + wfcMode);
+            }
+        }
+        return resId;
+    }
+}
diff --git a/tests/robotests/assets/grandfather_not_implementing_indexable b/tests/robotests/assets/grandfather_not_implementing_indexable
index d4a8d2d..a9fb589 100644
--- a/tests/robotests/assets/grandfather_not_implementing_indexable
+++ b/tests/robotests/assets/grandfather_not_implementing_indexable
@@ -79,6 +79,7 @@
 com.android.settings.SecuritySettings$SecuritySubSettings
 com.android.settings.PrivacySettings
 com.android.settings.WifiCallingSettings
+com.android.settings.WifiCallingSettingsForSub
 com.android.settings.password.SetupChooseLockGeneric$SetupChooseLockGenericFragment
 com.android.settings.SetupRedactionInterstitial$SetupRedactionInterstitialFragment
 com.android.settings.TrustAgentSettings
diff --git a/tests/unit/Android.mk b/tests/unit/Android.mk
index a91dcb1..ec0f0b6 100644
--- a/tests/unit/Android.mk
+++ b/tests/unit/Android.mk
@@ -5,7 +5,7 @@
 LOCAL_MODULE_TAGS := tests
 LOCAL_CERTIFICATE := platform
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common ims-common
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
diff --git a/tests/unit/src/com/android/settings/utils/MockedServiceManager.java b/tests/unit/src/com/android/settings/utils/MockedServiceManager.java
new file mode 100644
index 0000000..ea04974
--- /dev/null
+++ b/tests/unit/src/com/android/settings/utils/MockedServiceManager.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+// This class is for replacing existing system service with the mocked service.
+// Copied from CellBroadcastReceiver app.
+public final class MockedServiceManager {
+
+    private final String TAG = MockedServiceManager.class.getSimpleName();
+
+    private final HashMap<String, IBinder> mServiceManagerMockedServices = new HashMap<>();
+
+    private final HashMap<InstanceKey, Object> mOldInstances = new HashMap<>();
+
+    private final LinkedList<InstanceKey> mInstanceKeys = new LinkedList<>();
+
+    private static class InstanceKey {
+        final Class mClass;
+        final String mInstName;
+        final Object mObj;
+
+        InstanceKey(final Class c, final String instName, final Object obj) {
+            mClass = c;
+            mInstName = instName;
+            mObj = obj;
+        }
+
+        @Override
+        public int hashCode() {
+            return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == null || obj.getClass() != getClass()) {
+                return false;
+            }
+
+            InstanceKey other = (InstanceKey) obj;
+            return (other.mClass == mClass && other.mInstName.equals(mInstName)
+                    && other.mObj == mObj);
+        }
+    }
+
+    public MockedServiceManager() throws Exception {
+        replaceInstance(ServiceManager.class, "sCache", null, mServiceManagerMockedServices);
+    }
+
+    public void replaceService(String key, IBinder binder) {
+        mServiceManagerMockedServices.put(key, binder);
+    }
+
+    public void restoreAllServices() throws Exception {
+        restoreInstances();
+    }
+
+    public synchronized void replaceInstance(final Class c, final String instanceName,
+            final Object obj, final Object newValue)
+            throws Exception {
+        Field field = c.getDeclaredField(instanceName);
+        field.setAccessible(true);
+
+        InstanceKey key = new InstanceKey(c, instanceName, obj);
+        if (!mOldInstances.containsKey(key)) {
+            mOldInstances.put(key, field.get(obj));
+            mInstanceKeys.add(key);
+        }
+        field.set(obj, newValue);
+    }
+
+    public synchronized void restoreInstances() throws Exception {
+        Iterator<InstanceKey> it = mInstanceKeys.descendingIterator();
+
+        while (it.hasNext()) {
+            InstanceKey key = it.next();
+            Field field = key.mClass.getDeclaredField(key.mInstName);
+            field.setAccessible(true);
+            field.set(key.mObj, mOldInstances.get(key));
+        }
+
+        mInstanceKeys.clear();
+        mOldInstances.clear();
+    }
+}
diff --git a/tests/unit/src/com/android/settings/wifi/WifiCallingSettingUiTest.java b/tests/unit/src/com/android/settings/wifi/WifiCallingSettingUiTest.java
new file mode 100644
index 0000000..16617d0
--- /dev/null
+++ b/tests/unit/src/com/android/settings/wifi/WifiCallingSettingUiTest.java
@@ -0,0 +1,299 @@
+/**
+ * Copyright (C) 2017 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.wifi;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.isSelected;
+import static android.support.test.espresso.matcher.ViewMatchers.withResourceName;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.anything;
+import static org.junit.Assert.assertEquals;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.ViewInteraction;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.UiDevice;
+import android.telephony.SubscriptionInfo;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
+import com.android.internal.telephony.SubscriptionController;
+import com.android.settings.testutils.MockedServiceManager;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class WifiCallingSettingUiTest {
+    private static final String SUBSCRIPTION0_NAME = "SUB0";
+    private static final String SUBSCRIPTION1_NAME = "SUB1";
+    private static final String WFC_MODE_TITLE = "Calling preference";
+    private static final String WFC_MODE_WIFI_ONLY = "Wi-Fi only";
+    private static final String WFC_MODE_WIFI_PREFERRED = "Wi-Fi preferred";
+    private static final String WFC_MODE_CELLULAR_PREFERRED = "Mobile preferred";
+
+    private Instrumentation mInstrumentation;
+    private Context mContext;
+    private UiDevice mDevice;
+    @Mock
+    SubscriptionController mSubscriptionController;
+    MockedServiceManager mMockedServiceManager;
+    protected HashMap<Integer, ImsManager> mImsManagerInstances = new HashMap<>();
+    List<SubscriptionInfo> mSils = new ArrayList();
+    @Mock
+    SubscriptionInfo mSubscriptionInfo0;
+    @Mock
+    SubscriptionInfo mSubscriptionInfo1;
+    @Mock
+    ImsManager mImsManager0;
+    @Mock
+    ImsManager mImsManager1;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mContext = mInstrumentation.getTargetContext();
+        mDevice = UiDevice.getInstance(mInstrumentation);
+
+        mMockedServiceManager = new MockedServiceManager();
+        mMockedServiceManager.replaceService("isub", mSubscriptionController);
+
+        mMockedServiceManager.replaceInstance(
+                ImsManager.class, "sImsManagerInstances", null, mImsManagerInstances);
+        mMockedServiceManager.replaceInstance(
+                SubscriptionController.class, "sInstance", null, mSubscriptionController);
+        doReturn(mSubscriptionController)
+                .when(mSubscriptionController).queryLocalInterface(anyString());
+        mImsManagerInstances.put(0, mImsManager0);
+        mImsManagerInstances.put(1, mImsManager1);
+        doReturn(mSils).when(mSubscriptionController).getActiveSubscriptionInfoList(anyString());
+        doReturn(0).when(mSubscriptionController).getPhoneId(0);
+        doReturn(1).when(mSubscriptionController).getPhoneId(1);
+        doReturn(0).when(mSubscriptionInfo0).getSubscriptionId();
+        doReturn(1).when(mSubscriptionInfo1).getSubscriptionId();
+        doReturn(0).when(mSubscriptionInfo0).getSimSlotIndex();
+        doReturn(1).when(mSubscriptionInfo1).getSimSlotIndex();
+        doReturn(SUBSCRIPTION0_NAME).when(mSubscriptionInfo0).getDisplayName();
+        doReturn(SUBSCRIPTION1_NAME).when(mSubscriptionInfo1).getDisplayName();
+
+        doReturn(true).when(mImsManager0).isWfcEnabledByPlatform();
+        doReturn(true).when(mImsManager0).isNonTtyOrTtyOnVolteEnabled();
+        doReturn(true).when(mImsManager1).isWfcEnabledByPlatform();
+        doReturn(true).when(mImsManager1).isNonTtyOrTtyOnVolteEnabled();
+
+        mDevice.wakeUp();
+        mDevice.pressMenu();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mMockedServiceManager.restoreAllServices();
+    }
+
+    @Test
+    public void testSingleSimUi() throws InterruptedException {
+        configureSingleSim();
+        doReturn(true).when(mImsManager0).isWfcEnabledByUser();
+        doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
+                .when(mImsManager0).getWfcMode();
+        doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
+                .when(mImsManager0).getWfcMode(anyBoolean());
+
+        mInstrumentation.startActivitySync(createActivityIntent());
+
+        checkSingleSimUi();
+
+        try {
+            mDevice.setOrientationLeft();
+        } catch (Exception e) {
+            Assert.fail("Exception " + e);
+        }
+
+        // Re-check after rotation. Fragment should be recreated properly.
+        checkSingleSimUi();
+
+        try {
+            mDevice.setOrientationNatural();
+        } catch (Exception e) {
+            Assert.fail("Exception " + e);
+        }
+
+        // Re-check after rotation. Fragment should be resumed properly.
+        checkSingleSimUi();
+    }
+
+    private void checkSingleSimUi() {
+        assertEquals(false, checkExists(onView(withText(SUBSCRIPTION0_NAME))));
+        assertEquals(false, checkExists(onView(withText(SUBSCRIPTION1_NAME))));
+        assertEquals(true, checkExists(onView(withText(WFC_MODE_TITLE))));
+        assertEquals(true, checkExists(onView(withText(WFC_MODE_WIFI_PREFERRED))));
+        checkSwitchBarStatus(true, true);
+        checkEmptyViewStatus(false);
+    }
+
+    @Test
+    public void testNoValidSub() throws InterruptedException {
+        configureDualSim();
+        doReturn(false).when(mImsManager0).isWfcEnabledByPlatform();
+        doReturn(false).when(mImsManager0).isNonTtyOrTtyOnVolteEnabled();
+        doReturn(false).when(mImsManager1).isWfcEnabledByPlatform();
+        doReturn(false).when(mImsManager1).isNonTtyOrTtyOnVolteEnabled();
+        doReturn(false).when(mImsManager0).isWfcEnabledByUser();
+        doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
+                .when(mImsManager0).getWfcMode();
+        doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
+                .when(mImsManager0).getWfcMode(anyBoolean());
+
+        Activity activity = mInstrumentation.startActivitySync(createActivityIntent());
+
+        assertEquals(false, checkExists(onView(withText(SUBSCRIPTION0_NAME))));
+        assertEquals(false, checkExists(onView(withText(SUBSCRIPTION1_NAME))));
+        assertEquals(false, checkExists(onView(withText(WFC_MODE_TITLE))));
+
+        checkSwitchBarStatus(false, false);
+        checkEmptyViewStatus(false);
+    }
+
+    @Test
+    public void testWfcDisabled() throws InterruptedException {
+        configureSingleSim();
+        doReturn(false).when(mImsManager0).isWfcEnabledByUser();
+        doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
+                .when(mImsManager0).getWfcMode();
+        doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
+                .when(mImsManager0).getWfcMode(anyBoolean());
+
+        Activity activity = mInstrumentation.startActivitySync(createActivityIntent());
+
+        assertEquals(false, checkExists(onView(withText(SUBSCRIPTION0_NAME))));
+        assertEquals(false, checkExists(onView(withText(SUBSCRIPTION1_NAME))));
+        assertEquals(false, checkExists(onView(withText(WFC_MODE_TITLE))));
+
+        checkSwitchBarStatus(true, false);
+        checkEmptyViewStatus(true);
+    }
+
+    @Test
+    public void testDualSimUi() throws InterruptedException {
+        configureDualSim();
+        doReturn(true).when(mImsManager0).isWfcEnabledByUser();
+        doReturn(false).when(mImsManager1).isWfcEnabledByUser();
+        doReturn(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED)
+                .when(mImsManager0).getWfcMode();
+        doReturn(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED)
+                .when(mImsManager0).getWfcMode(anyBoolean());
+
+        mInstrumentation.startActivitySync(createActivityIntent());
+
+        assertEquals(true, checkExists(onView(withText(SUBSCRIPTION0_NAME))));
+        assertEquals(true, checkExists(onView(withText(SUBSCRIPTION1_NAME))));
+        assertEquals(true, checkExists(onView(withText(WFC_MODE_TITLE))));
+        assertEquals(true, checkExists(onView(withText(WFC_MODE_CELLULAR_PREFERRED))));
+
+        onView(withText(SUBSCRIPTION0_NAME)).check(matches(isSelected()));
+        checkSwitchBarStatus(true, true);
+        checkEmptyViewStatus(false);
+
+        // Switch to SUB1.
+        onView(withText(SUBSCRIPTION1_NAME)).perform(click());
+
+        checkSwitchBarStatus(true, false);
+        checkEmptyViewStatus(true);
+        onView(withText(SUBSCRIPTION1_NAME)).check(matches(isSelected()));
+    }
+
+    private boolean checkExists(ViewInteraction v) {
+        try {
+            v.check(matches(isCompletelyDisplayed()));
+            return true;
+        } catch (NoMatchingViewException e) {
+            return false;
+        }
+    }
+
+    private Intent createActivityIntent() {
+        Intent intent = new Intent(mContext,
+                com.android.settings.Settings.WifiCallingSettingsActivity.class);
+        intent.setPackage("com.android.settings");
+        intent.setAction("android.intent.action.MAIN");
+        return intent;
+    }
+
+    private void configureSingleSim() {
+        mSils.clear();
+        mSils.add(mSubscriptionInfo0);
+    }
+
+    private void configureDualSim() {
+        mSils.clear();
+        mSils.add(mSubscriptionInfo0);
+        mSils.add(mSubscriptionInfo1);
+    }
+
+    private void checkSwitchBarStatus(boolean shouldDisplay, boolean statusOn) {
+        if (shouldDisplay) {
+            try {
+                onView(allOf(withResourceName("switch_text"), isCompletelyDisplayed()))
+                        .check(matches(withText(containsString(statusOn ? "On" : "Off"))));
+            } catch (Exception e) {
+                Assert.fail("Exception " + e);
+            }
+        } else {
+            onView(allOf(withResourceName("switch_text"), isCompletelyDisplayed()))
+                    .check(doesNotExist());
+        }
+    }
+
+    private void checkEmptyViewStatus(boolean shouldDisplay) {
+        try {
+            if (!shouldDisplay) {
+                onView(allOf(withResourceName("empty"), isCompletelyDisplayed()))
+                        .check(doesNotExist());
+            } else {
+                onView(allOf(withResourceName("empty"), isCompletelyDisplayed()))
+                        .check(matches(anything()));
+            }
+        } catch (Exception e) {
+            Assert.fail("Exception " + e);
+        }
+    }
+}