Merge "Move SMS raw db deletion to phone process."
diff --git a/res/layout/vpn_dialog.xml b/res/layout/vpn_dialog.xml
index 71ce0ad..a626205 100644
--- a/res/layout/vpn_dialog.xml
+++ b/res/layout/vpn_dialog.xml
@@ -140,6 +140,46 @@
                     android:labelFor="@+id/routes"/>
             <EditText style="@style/vpn_value" android:id="@+id/routes"
                     android:hint="@string/vpn_not_used"/>
+
+            <TextView android:id="@+id/vpn_proxy_settings_title"
+                      style="@style/vpn_label"
+                      android:text="@string/proxy_settings_title"
+                      android:labelFor="@+id/vpn_proxy_settings" />
+
+            <Spinner android:id="@+id/vpn_proxy_settings"
+                     style="@style/vpn_value"
+                     android:prompt="@string/proxy_settings_title"
+                     android:entries="@array/vpn_proxy_settings" />
+
+            <LinearLayout
+                android:id="@+id/vpn_proxy_fields"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:visibility="gone" >
+
+                <TextView
+                    style="@style/vpn_label"
+                    android:text="@string/proxy_hostname_label"
+                    android:labelFor="@+id/vpn_proxy_host" />
+
+                <EditText
+                    android:id="@+id/vpn_proxy_host"
+                    style="@style/vpn_value"
+                    android:hint="@string/proxy_hostname_hint"
+                    android:inputType="textNoSuggestions" />
+
+                <TextView
+                    style="@style/vpn_label"
+                    android:text="@string/proxy_port_label"
+                    android:labelFor="@+id/vpn_proxy_port" />
+
+                <EditText
+                    android:id="@+id/vpn_proxy_port"
+                    style="@style/vpn_value"
+                    android:hint="@string/proxy_port_hint"
+                    android:inputType="number" />
+            </LinearLayout>
         </LinearLayout>
 
         <LinearLayout android:id="@+id/login"
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index be7a0ca..930e21e 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -939,6 +939,14 @@
         <item>IPSec VPN with certificates and hybrid authentication</item>
     </string-array>
 
+    <!-- VPN proxy settings. -->
+    <string-array name="vpn_proxy_settings">
+        <!-- No HTTP proxy is used for the current VPN [CHAR LIMIT=25] -->
+        <item>None</item>
+        <!-- Manual HTTP proxy settings are used for the current VPN [CHAR LIMIT=25] -->
+        <item>Manual</item>
+    </string-array>
+
     <!-- Match this with the constants in LegacyVpnInfo. --> <skip />
     <!-- Status for a VPN network. [CHAR LIMIT=100] -->
     <string-array name="vpn_states">
@@ -1157,4 +1165,17 @@
         <item>0</item>
     </string-array>
 
+    <!-- WiFi calling mode array -->
+    <string-array name="wifi_calling_mode_summaries" translatable="false">
+         <item>@string/wifi_calling_mode_wifi_preferred_summary</item>
+         <item>@string/wifi_calling_mode_cellular_preferred_summary</item>
+         <item>@string/wifi_calling_mode_wifi_only_summary</item>
+    </string-array>
+
+    <!-- WiFi calling mode array without wifi only mode -->
+    <string-array name="wifi_calling_mode_summaries_without_wifi_only" translatable="false">
+         <item>@string/wifi_calling_mode_wifi_preferred_summary</item>
+         <item>@string/wifi_calling_mode_cellular_preferred_summary</item>
+    </string-array>
+
 </resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 33573ac..181af40 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -149,6 +149,11 @@
         <attr name="aspectRatio" format="float" />
     </declare-styleable>
 
+    <declare-styleable name="ListWithEntrySummaryPreference">
+        <!-- Summaries of entry -->
+        <attr name="entrySummaries" format="reference" />
+    </declare-styleable>
+
     <!-- For UsageView -->
     <declare-styleable name="UsageView">
         <attr name="android:colorAccent" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 2c52c3a..ae12511 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -291,6 +291,15 @@
 
     <dimen name="password_requirement_textsize">14sp</dimen>
 
+    <!-- Visible vertical space we want to show below password edittext field when ime is shown.
+         The unit is sp as it is related to the text size of password requirement item. -->
+    <dimen name="visible_vertical_space_below_password">20sp</dimen>
+
+    <!-- Select dialog -->
+    <dimen name="select_dialog_padding_start">20dp</dimen>
+    <dimen name="select_dialog_item_margin_start">12dp</dimen>
+    <dimen name="select_dialog_summary_padding_bottom">8dp</dimen>
+
     <!-- Padding between the donut and the storage summary. -->
     <dimen name="storage_summary_padding_end">16dp</dimen>
     <!-- Text size of the big number in the donut. -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c55bcfc..4985ae62e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2302,7 +2302,7 @@
     <!-- Title of WFC preference item [CHAR LIMIT=30] -->
     <string name="wifi_calling_mode_title">Calling preference</string>
     <!-- Title of WFC preference selection dialog [CHAR LIMIT=30] -->
-    <string name="wifi_calling_mode_dialog_title">Wi-Fi calling mode</string>
+    <string name="wifi_calling_mode_dialog_title">Calling preference</string>
     <!-- Title of WFC roaming preference item [CHAR LIMIT=45] -->
     <string name="wifi_calling_roaming_mode_title">Roaming preference</string>
     <!-- Summary of WFC roaming preference item [CHAR LIMIT=NONE]-->
@@ -2310,9 +2310,9 @@
     <!-- WFC mode dialog [CHAR LIMIT=45] -->
     <string name="wifi_calling_roaming_mode_dialog_title">Roaming preference</string>
     <string-array name="wifi_calling_mode_choices">
-        <item>Wi-Fi preferred</item>
-        <item>Mobile preferred</item>
-        <item>Wi-Fi only</item>
+        <item>@*android:string/wfc_mode_wifi_preferred_summary</item>
+        <item>@*android:string/wfc_mode_cellular_preferred_summary</item>
+        <item>@*android:string/wfc_mode_wifi_only_summary</item>
     </string-array>
     <string-array name="wifi_calling_mode_choices_v2">
         <item>Wi-Fi</item>
@@ -2325,8 +2325,8 @@
         <item>"0"</item>
     </string-array>
     <string-array name="wifi_calling_mode_choices_without_wifi_only">
-        <item>Wi-Fi preferred</item>
-        <item>Mobile preferred</item>
+        <item>@*android:string/wfc_mode_wifi_preferred_summary</item>
+        <item>@*android:string/wfc_mode_cellular_preferred_summary</item>
     </string-array>
     <string-array name="wifi_calling_mode_choices_v2_without_wifi_only">
         <item>Wi-Fi</item>
@@ -2336,6 +2336,14 @@
         <item>"2"</item>
         <item>"1"</item>
     </string-array>
+
+    <!-- Summary of WFC preference item on the WFC preference selection dialog. [CHAR LIMIT=70]-->
+    <string name="wifi_calling_mode_wifi_preferred_summary">If Wi\u2011Fi is unavailable, use mobile network</string>
+    <!-- Summary of WFC preference item on the WFC preference selection dialog. [CHAR LIMIT=70]-->
+    <string name="wifi_calling_mode_cellular_preferred_summary">If mobile network is unavailable, use Wi\u2011Fi</string>
+    <!-- Summary of WFC preference item on the WFC preference selection dialog. [CHAR LIMIT=70]-->
+    <string name="wifi_calling_mode_wifi_only_summary">Call over Wi\u2011Fi. If Wi\u2011Fi is lost, call will end.</string>
+
     <!-- Wi-Fi Calling settings. Text displayed when Wi-Fi Calling is off -->
     <string name="wifi_calling_off_explanation">When Wi-Fi calling is on, your phone can route calls via Wi-Fi networks or your carrier\u2019s network, depending on your preference and which signal is stronger. Before turning on this feature, check with your carrier regarding fees and other details.<xliff:g id="additional_text" example="Learn More">%1$s</xliff:g></string>
     <!-- Wi-Fi Calling settings. Additional text displayed when Wi-Fi Calling is off. Default empty. [CHAR LIMIT=NONE] -->
diff --git a/res/xml/single_choice_list_item_2.xml b/res/xml/single_choice_list_item_2.xml
new file mode 100644
index 0000000..ca80f44
--- /dev/null
+++ b/res/xml/single_choice_list_item_2.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingStart="@dimen/select_dialog_padding_start"
+    android:paddingEnd="?android:attr/dialogPreferredPadding"
+    android:orientation="horizontal"
+    android:descendantFocusability="blocksDescendants">
+
+    <RadioButton
+        android:id="@+id/radio"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:clickable="false" />
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:layout_marginStart="@dimen/select_dialog_item_margin_start"
+        android:layout_gravity="center_vertical">
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textColor="?android:attr/textColorAlertDialogListItem"
+            android:ellipsize="marquee" />
+
+        <TextView
+            android:id="@+id/summary"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingBottom="@dimen/select_dialog_summary_padding_bottom"
+            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="10" />
+
+    </LinearLayout>
+</LinearLayout>
diff --git a/res/xml/wifi_calling_settings.xml b/res/xml/wifi_calling_settings.xml
index 0adb1e8..0276bdb 100644
--- a/res/xml/wifi_calling_settings.xml
+++ b/res/xml/wifi_calling_settings.xml
@@ -15,24 +15,27 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res-auto"
                   android:key="wifi_calling_settings"
                   android:title="@string/wifi_calling_settings_title">
 
-    <ListPreference
+    <com.android.settings.wifi.calling.ListWithEntrySummaryPreference
             android:key="wifi_calling_mode"
             android:title="@string/wifi_calling_mode_title"
             android:summary="@string/wifi_calling_mode_title"
             android:entries="@array/wifi_calling_mode_choices"
             android:entryValues="@array/wifi_calling_mode_values"
-            android:dialogTitle="@string/wifi_calling_mode_dialog_title" />
+            android:dialogTitle="@string/wifi_calling_mode_dialog_title"
+            settings:entrySummaries="@array/wifi_calling_mode_summaries" />
 
-    <ListPreference
+    <com.android.settings.wifi.calling.ListWithEntrySummaryPreference
             android:key="wifi_calling_roaming_mode"
             android:title="@string/wifi_calling_roaming_mode_title"
             android:summary="@string/wifi_calling_roaming_mode_summary"
             android:entries="@array/wifi_calling_mode_choices_v2"
             android:entryValues="@array/wifi_calling_mode_values"
-            android:dialogTitle="@string/wifi_calling_roaming_mode_dialog_title" />
+            android:dialogTitle="@string/wifi_calling_roaming_mode_dialog_title"
+            settings:entrySummaries="@array/wifi_calling_mode_summaries" />
 
     <Preference
             android:key="emergency_address_key"
diff --git a/src/com/android/settings/development/FileEncryptionPreferenceController.java b/src/com/android/settings/development/FileEncryptionPreferenceController.java
index 731f487..a988fdd 100644
--- a/src/com/android/settings/development/FileEncryptionPreferenceController.java
+++ b/src/com/android/settings/development/FileEncryptionPreferenceController.java
@@ -63,7 +63,8 @@
 
     @Override
     public void updateState(Preference preference) {
-        if (!TextUtils.equals("file", CryptoProperties.type().orElse("none"))) {
+        if (CryptoProperties.type().orElse(CryptoProperties.type_values.NONE) !=
+            CryptoProperties.type_values.FILE) {
             return;
         }
 
diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java
index 4eecd28..0c6d061 100644
--- a/src/com/android/settings/vpn2/ConfigDialog.java
+++ b/src/com/android/settings/vpn2/ConfigDialog.java
@@ -19,6 +19,8 @@
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.net.Proxy;
+import android.net.ProxyInfo;
 import android.os.Bundle;
 import android.os.SystemProperties;
 import android.security.Credentials;
@@ -66,6 +68,9 @@
     private TextView mSearchDomains;
     private TextView mDnsServers;
     private TextView mRoutes;
+    private Spinner mProxySettings;
+    private TextView mProxyHost;
+    private TextView mProxyPort;
     private CheckBox mMppe;
     private TextView mL2tpSecret;
     private TextView mIpsecIdentifier;
@@ -104,6 +109,9 @@
         mSearchDomains = (TextView) mView.findViewById(R.id.search_domains);
         mDnsServers = (TextView) mView.findViewById(R.id.dns_servers);
         mRoutes = (TextView) mView.findViewById(R.id.routes);
+        mProxySettings = (Spinner) mView.findViewById(R.id.vpn_proxy_settings);
+        mProxyHost = (TextView) mView.findViewById(R.id.vpn_proxy_host);
+        mProxyPort = (TextView) mView.findViewById(R.id.vpn_proxy_port);
         mMppe = (CheckBox) mView.findViewById(R.id.mppe);
         mL2tpSecret = (TextView) mView.findViewById(R.id.l2tp_secret);
         mIpsecIdentifier = (TextView) mView.findViewById(R.id.ipsec_identifier);
@@ -127,6 +135,11 @@
         mSearchDomains.setText(mProfile.searchDomains);
         mDnsServers.setText(mProfile.dnsServers);
         mRoutes.setText(mProfile.routes);
+        if (mProfile.proxy != null) {
+            mProxyHost.setText(mProfile.proxy.getHost());
+            int port = mProfile.proxy.getPort();
+            mProxyPort.setText(port == 0 ? "" : Integer.toString(port));
+        }
         mMppe.setChecked(mProfile.mppe);
         mL2tpSecret.setText(mProfile.l2tpSecret);
         mIpsecIdentifier.setText(mProfile.ipsecIdentifier);
@@ -152,6 +165,9 @@
         mPassword.addTextChangedListener(this);
         mDnsServers.addTextChangedListener(this);
         mRoutes.addTextChangedListener(this);
+        mProxySettings.setOnItemSelectedListener(this);
+        mProxyHost.addTextChangedListener(this);
+        mProxyPort.addTextChangedListener(this);
         mIpsecSecret.addTextChangedListener(this);
         mIpsecUserCert.setOnItemSelectedListener(this);
         mShowOptions.setOnClickListener(this);
@@ -174,7 +190,8 @@
 
             // Switch to advanced view immediately if any advanced options are on
             if (!mProfile.searchDomains.isEmpty() || !mProfile.dnsServers.isEmpty() ||
-                    !mProfile.routes.isEmpty()) {
+                    !mProfile.routes.isEmpty() || (mProfile.proxy != null &&
+                    (!mProfile.proxy.getHost().isEmpty() || mProfile.proxy.getPort() != 0))) {
                 showAdvancedOptions();
             }
 
@@ -245,6 +262,8 @@
     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
         if (parent == mType) {
             changeType(position);
+        } else if (parent == mProxySettings) {
+            updateProxyFieldsVisibility(position);
         }
         updateUiControls();
     }
@@ -270,6 +289,7 @@
      * These include:
      * "Always-on VPN" checkbox
      * Reason for "Always-on VPN" being disabled, when necessary
+     * Proxy info if manually configured
      * "Save account information" checkbox
      * "Save" and "Connect" buttons
      */
@@ -297,6 +317,13 @@
             mAlwaysOnInvalidReason.setVisibility(View.VISIBLE);
         }
 
+        // Show proxy fields if any proxy field is filled.
+        if (mProfile.proxy != null && (!mProfile.proxy.getHost().isEmpty() ||
+                mProfile.proxy.getPort() != 0)) {
+            mProxySettings.setSelection(VpnProfile.PROXY_MANUAL);
+            updateProxyFieldsVisibility(VpnProfile.PROXY_MANUAL);
+        }
+
         // Save account information
         if (mAlwaysOnVpn.isChecked()) {
             mSaveLogin.setChecked(true);
@@ -310,6 +337,11 @@
         getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(validate(mEditing));
     }
 
+    private void updateProxyFieldsVisibility(int position) {
+        final int visible = position == VpnProfile.PROXY_MANUAL ? View.VISIBLE : View.GONE;
+        mView.findViewById(R.id.vpn_proxy_fields).setVisibility(visible);
+    }
+
     private void showAdvancedOptions() {
         mView.findViewById(R.id.options).setVisibility(View.VISIBLE);
         mShowOptions.setVisibility(View.GONE);
@@ -360,6 +392,11 @@
                 !validateAddresses(mRoutes.getText().toString(), true)) {
             return false;
         }
+
+        if (!validateProxy()) {
+            return false;
+        }
+
         switch (mType.getSelectedItemPosition()) {
             case VpnProfile.TYPE_PPTP:
             case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
@@ -434,6 +471,10 @@
         return mEditing;
     }
 
+    boolean hasProxy() {
+        return mProxySettings.getSelectedItemPosition() == VpnProfile.PROXY_MANUAL;
+    }
+
     VpnProfile getProfile() {
         // First, save common fields.
         VpnProfile profile = new VpnProfile(mProfile.key);
@@ -445,7 +486,16 @@
         profile.searchDomains = mSearchDomains.getText().toString().trim();
         profile.dnsServers = mDnsServers.getText().toString().trim();
         profile.routes = mRoutes.getText().toString().trim();
-
+        if (hasProxy()) {
+            String proxyHost = mProxyHost.getText().toString().trim();
+            String proxyPort = mProxyPort.getText().toString().trim();
+            // 0 is a last resort default, but the interface validates that the proxy port is
+            // present and non-zero.
+            int port = proxyPort.isEmpty() ? 0 : Integer.parseInt(proxyPort);
+            profile.proxy = new ProxyInfo(proxyHost, port, null);
+        } else {
+            profile.proxy = null;
+        }
         // Then, save type-specific fields.
         switch (profile.type) {
             case VpnProfile.TYPE_PPTP:
@@ -482,4 +532,15 @@
         profile.saveLogin = mSaveLogin.isChecked() || (mEditing && hasLogin);
         return profile;
     }
+
+    private boolean validateProxy() {
+        if (!hasProxy()) {
+            return true;
+        }
+
+        final String host = mProxyHost.getText().toString().trim();
+        final String port = mProxyPort.getText().toString().trim();
+        return Proxy.validate(host, port, "") == Proxy.PROXY_VALID;
+    }
+
 }
diff --git a/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreference.java b/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreference.java
new file mode 100644
index 0000000..c24ff2b
--- /dev/null
+++ b/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreference.java
@@ -0,0 +1,204 @@
+/*
+ * 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.wifi.calling;
+
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListAdapter;
+import android.widget.RadioButton;
+import android.widget.TextView;
+
+import com.android.settings.CustomListPreference;
+import com.android.settings.R;
+
+/**
+ * ListPreference contain the entry summary.
+ */
+public class ListWithEntrySummaryPreference extends CustomListPreference {
+    private static final String LOG_TAG = "ListWithEntrySummaryPreference";
+    private final Context mContext;
+    private CharSequence[] mSummaries;
+
+    /**
+     * ListWithEntrySummaryPreference constructor.
+     *
+     * @param context The context of view.
+     * @param attrs The attributes of the XML tag that is inflating the linear layout.
+     */
+    public ListWithEntrySummaryPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+
+        TypedArray array = context.obtainStyledAttributes(attrs,
+                R.styleable.ListWithEntrySummaryPreference, 0, 0);
+        mSummaries = array.getTextArray(R.styleable.ListWithEntrySummaryPreference_entrySummaries);
+        array.recycle();
+    }
+
+    /**
+     * Sets the summaries of mode items to be shown in the mode select dialog.
+     *
+     * @param summariesResId The summaries of mode items.
+     */
+    public void setEntrySummaries(int summariesResId) {
+        mSummaries = getContext().getResources().getTextArray(summariesResId);
+    }
+
+    /**
+     * Sets the summaries of mode items to be shown in the mode select dialog.
+     *
+     * @param summaries The summaries of mode items.
+     */
+    public void setEntrySummaries(CharSequence[] summaries) {
+        mSummaries = summaries;
+    }
+
+    private CharSequence getEntrySummary(int index) {
+        if (mSummaries == null) {
+            Log.w(LOG_TAG, "getEntrySummary : mSummaries is null");
+            return "";
+        }
+        return mSummaries[index];
+    }
+
+    @Override
+    protected void onPrepareDialogBuilder(Builder builder,
+            DialogInterface.OnClickListener listener) {
+        ListAdapter la = (ListAdapter) new SelectorAdapter(mContext,
+                R.xml.single_choice_list_item_2, this);
+        builder.setSingleChoiceItems(la, findIndexOfValue(getValue()), listener);
+        super.onPrepareDialogBuilder(builder, listener);
+    }
+
+    private static class SelectorAdapter extends ArrayAdapter<CharSequence> {
+        private final Context mContext;
+        private ListWithEntrySummaryPreference mSelector;
+
+        /**
+         * SelectorAdapter constructor.
+         *
+         * @param context The current context.
+         * @param rowResourceId The resource id of the XML tag that is inflating the linear layout.
+         * @param listPreference The instance of ListWithEntrySummaryPreference.
+         */
+        public SelectorAdapter(Context context, int rowResourceId,
+                ListWithEntrySummaryPreference listPreference) {
+            super(context, rowResourceId, listPreference.getEntryValues());
+            mContext = context;
+            mSelector = listPreference;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            LayoutInflater inflater = LayoutInflater.from(mContext);
+            View row = inflater.inflate(R.xml.single_choice_list_item_2, parent, false);
+
+            TextView title = (TextView) row.findViewById(R.id.title);
+            title.setText(mSelector.getEntries()[position]);
+
+            TextView summary = (TextView) row.findViewById(R.id.summary);
+            summary.setText(mSelector.getEntrySummary(position));
+
+            RadioButton rb = (RadioButton) row.findViewById(R.id.radio);
+            if (position == mSelector.findIndexOfValue(mSelector.getValue())) {
+                rb.setChecked(true);
+            }
+
+            return row;
+        }
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+
+        final SavedState myState = new SavedState(superState);
+        myState.mEntries = getEntries();
+        myState.mEntryValues = getEntryValues();
+        myState.mSummaries = mSummaries;
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+        setEntries(myState.mEntries);
+        setEntryValues(myState.mEntryValues);
+        mSummaries = myState.mSummaries;
+    }
+
+    /**
+     *  We save entries, entryValues and summaries into bundle.
+     *  At onCreate of fragment, dialog will be restored if it was open. In this case,
+     *  we need to restore entries, entryValues and summaries. Without those information,
+     *  crash when entering multi window during wfc modes dialog shown.
+     */
+    private static class SavedState extends BaseSavedState {
+        private CharSequence[] mEntries;
+        private CharSequence[] mEntryValues;
+        private CharSequence[] mSummaries;
+
+        public SavedState(Parcel source) {
+            super(source);
+            mEntries = source.readCharSequenceArray();
+            mEntryValues = source.readCharSequenceArray();
+            mSummaries = source.readCharSequenceArray();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeCharSequenceArray(mEntries);
+            dest.writeCharSequenceArray(mEntryValues);
+            dest.writeCharSequenceArray(mSummaries);
+        }
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            @Override
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            @Override
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+}
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
index 33e8d85..b3b639f 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
@@ -81,14 +81,15 @@
     //UI objects
     private SwitchBar mSwitchBar;
     private Switch mSwitch;
-    private ListPreference mButtonWfcMode;
-    private ListPreference mButtonWfcRoamingMode;
+    private ListWithEntrySummaryPreference mButtonWfcMode;
+    private ListWithEntrySummaryPreference mButtonWfcRoamingMode;
     private Preference mUpdateAddress;
     private TextView mEmptyView;
 
     private boolean mValidListener = false;
     private boolean mEditableWfcMode = true;
     private boolean mEditableWfcRoamingMode = true;
+    private boolean mUseWfcHomeModeForRoaming = false;
 
     private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     private ImsManager mImsManager;
@@ -259,10 +260,11 @@
 
         mImsManager = getImsManager();
 
-        mButtonWfcMode = (ListPreference) findPreference(BUTTON_WFC_MODE);
+        mButtonWfcMode = (ListWithEntrySummaryPreference) findPreference(BUTTON_WFC_MODE);
         mButtonWfcMode.setOnPreferenceChangeListener(this);
 
-        mButtonWfcRoamingMode = (ListPreference) findPreference(BUTTON_WFC_ROAMING_MODE);
+        mButtonWfcRoamingMode = (ListWithEntrySummaryPreference) findPreference(
+                BUTTON_WFC_ROAMING_MODE);
         mButtonWfcRoamingMode.setOnPreferenceChangeListener(this);
 
         mUpdateAddress = (Preference) findPreference(PREFERENCE_EMERGENCY_ADDRESS);
@@ -312,6 +314,9 @@
                         CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
                 mEditableWfcRoamingMode = b.getBoolean(
                         CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
+                mUseWfcHomeModeForRoaming = b.getBoolean(
+                        CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL,
+                        false);
                 isWifiOnlySupported = b.getBoolean(
                         CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, true);
             }
@@ -320,10 +325,14 @@
         if (!isWifiOnlySupported) {
             mButtonWfcMode.setEntries(R.array.wifi_calling_mode_choices_without_wifi_only);
             mButtonWfcMode.setEntryValues(R.array.wifi_calling_mode_values_without_wifi_only);
+            mButtonWfcMode.setEntrySummaries(R.array.wifi_calling_mode_summaries_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);
+            mButtonWfcRoamingMode.setEntrySummaries(
+                    R.array.wifi_calling_mode_summaries_without_wifi_only);
         }
 
 
@@ -496,7 +505,7 @@
                 // Don't show WFC (home) preference if it's not editable.
                 preferenceScreen.removePreference(mButtonWfcMode);
             }
-            if (mEditableWfcRoamingMode) {
+            if (mEditableWfcRoamingMode && !mUseWfcHomeModeForRoaming) {
                 preferenceScreen.addPreference(mButtonWfcRoamingMode);
             } else {
                 // Don't show WFC roaming preference if it's not editable.
@@ -525,10 +534,8 @@
                 mImsManager.setWfcMode(buttonMode, false);
                 mButtonWfcMode.setSummary(getWfcModeSummary(buttonMode));
                 mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), buttonMode);
-            }
-            if (!mEditableWfcRoamingMode) {
-                int currentWfcRoamingMode = mImsManager.getWfcMode(true);
-                if (buttonMode != currentWfcRoamingMode) {
+
+                if (mUseWfcHomeModeForRoaming) {
                     mImsManager.setWfcMode(buttonMode, true);
                     // mButtonWfcRoamingMode.setSummary is not needed; summary is selected value
                 }
diff --git a/tests/robotests/src/com/android/settings/development/FileEncryptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/FileEncryptionPreferenceControllerTest.java
index afd465a..fb5eaab 100644
--- a/tests/robotests/src/com/android/settings/development/FileEncryptionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/FileEncryptionPreferenceControllerTest.java
@@ -91,7 +91,7 @@
         ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager);
         when(mStorageManager.isConvertibleToFBE()).thenReturn(true);
         mController.displayPreference(mPreferenceScreen);
-        CryptoProperties.type("foobar");
+        CryptoProperties.type(CryptoProperties.type_values.NONE);
 
         mController.updateState(mPreference);
 
@@ -105,7 +105,7 @@
         ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager);
         when(mStorageManager.isConvertibleToFBE()).thenReturn(true);
         mController.displayPreference(mPreferenceScreen);
-        CryptoProperties.type("file");
+        CryptoProperties.type(CryptoProperties.type_values.FILE);
 
         mController.updateState(mPreference);
 
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java
new file mode 100644
index 0000000..0cef231
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.wifi.calling;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.os.Parcelable;
+import android.widget.ListAdapter;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.io.IOException;
+
+@RunWith(RobolectricTestRunner.class)
+public class ListWithEntrySummaryPreferenceTest {
+
+    private Context mContext;
+    private ListWithEntrySummaryPreference mPreference;
+
+    private CharSequence[] mDefaultEntries =
+            {"default_entry1", "default_entry2", "default_entry3"};
+    private CharSequence[] mDefaultEntryValues = {"0", "1", "2"};
+    private CharSequence[] mDefaultEntrySummaries =
+            {"default_summary1", "default_summary2", "default_summary3"};
+
+    private CharSequence[] mCustomEntries = {"custom_entry1", "custom_entry2"};
+    private CharSequence[] mCustomEntryValues = {"0", "1"};
+    private CharSequence[] mCustomEntrySummaries = {"custom_summary1", "custom_summary2"};
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mPreference = new ListWithEntrySummaryPreference(mContext, null);
+        mPreference.setEntries(mDefaultEntries);
+        mPreference.setEntryValues(mDefaultEntryValues);
+        mPreference.setEntrySummaries(mDefaultEntrySummaries);
+    }
+
+    @Test
+    public void initialize_defaultEntries_shouldDisplayDefalutEntries() {
+        AlertDialog dialog = showDialog(mPreference);
+        ListAdapter adapter = dialog.getListView().getAdapter();
+
+        int len = mDefaultEntries.length;
+        assertThat(adapter.getCount()).isEqualTo(len);
+        for (int i = 0; i < len; i++) {
+            TextView title = adapter.getView(i, null, null).findViewById(R.id.title);
+            TextView summary = adapter.getView(i, null, null).findViewById(R.id.summary);
+            assertThat(title.getText()).isEqualTo(mDefaultEntries[i]);
+            assertThat(summary.getText()).isEqualTo(mDefaultEntrySummaries[i]);
+        }
+    }
+
+    @Test
+    public void setEntries_customEntries_shouldUpdateEntries() {
+        mPreference.setEntries(mCustomEntries);
+        mPreference.setEntryValues(mCustomEntryValues);
+        mPreference.setEntrySummaries(mCustomEntrySummaries);
+
+        AlertDialog dialog = showDialog(mPreference);
+        ListAdapter adapter = dialog.getListView().getAdapter();
+
+        int len = mCustomEntries.length;
+        assertThat(adapter.getCount()).isEqualTo(len);
+        for (int i = 0; i < len; i++) {
+            TextView title = adapter.getView(i, null, null).findViewById(R.id.title);
+            TextView summary = adapter.getView(i, null, null).findViewById(R.id.summary);
+            assertThat(title.getText()).isEqualTo(mCustomEntries[i]);
+            assertThat(summary.getText()).isEqualTo(mCustomEntrySummaries[i]);
+        }
+    }
+
+    @Test
+    public void onSaveAndRestoreInstanceState_resumePreference_shouldNotChangeEntries() {
+        setEntries_customEntries_shouldUpdateEntries();
+
+        final Parcelable parcelable = mPreference.onSaveInstanceState();
+        ListWithEntrySummaryPreference preference
+                = new ListWithEntrySummaryPreference(mContext, null);
+        preference.setEntries(mDefaultEntries);
+        preference.setEntryValues(mDefaultEntryValues);
+        preference.setEntrySummaries(mDefaultEntrySummaries);
+        preference.onRestoreInstanceState(parcelable);
+
+        AlertDialog dialog = showDialog(preference);
+        ListAdapter adapter = dialog.getListView().getAdapter();
+
+        int len = mCustomEntries.length;
+        assertThat(adapter.getCount()).isEqualTo(len);
+        for (int i = 0; i < len; i++) {
+            TextView title = adapter.getView(i, null, null).findViewById(R.id.title);
+            TextView summary = adapter.getView(i, null, null).findViewById(R.id.summary);
+            assertThat(title.getText()).isEqualTo(mCustomEntries[i]);
+            assertThat(summary.getText()).isEqualTo(mCustomEntrySummaries[i]);
+        }
+    }
+
+    private AlertDialog showDialog(ListWithEntrySummaryPreference preference) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+        preference.onPrepareDialogBuilder(builder, null);
+        return builder.show();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
index a5e80c6..2f2fa62 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
@@ -19,18 +19,23 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 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;
 
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
 import android.telephony.ims.ProvisioningManager;
 import android.view.View;
 import android.widget.TextView;
@@ -54,17 +59,23 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
-@RunWith(SettingsRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
 @Config(shadows = SettingsShadowResources.SettingsShadowTheme.class)
 public class WifiCallingSettingsForSubTest {
+    private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
+    private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
+
     private TestFragment mFragment;
     private Context mContext;
     private TextView mEmptyView;
+    private final PersistableBundle mBundle = new PersistableBundle();
 
+    @Mock private static CarrierConfigManager sCarrierConfigManager;
     @Mock private ImsManager mImsManager;
     @Mock private PreferenceScreen mPreferenceScreen;
     @Mock private SettingsActivity mActivity;
@@ -72,6 +83,8 @@
     @Mock private ToggleSwitch mToggleSwitch;
     @Mock private View mView;
     @Mock private ImsConfig mImsConfig;
+    @Mock private ListPreference mButtonWfcMode;
+    @Mock private ListPreference mButtonWfcRoamingMode;
 
     @Before
     public void setUp() throws NoSuchFieldException, ImsException {
@@ -90,6 +103,8 @@
         when(mFragment.getArguments()).thenReturn(bundle);
         doNothing().when(mFragment).addPreferencesFromResource(anyInt());
         doReturn(mock(ListPreference.class)).when(mFragment).findPreference(any());
+        doReturn(mButtonWfcMode).when(mFragment).findPreference(BUTTON_WFC_MODE);
+        doReturn(mButtonWfcRoamingMode).when(mFragment).findPreference(BUTTON_WFC_ROAMING_MODE);
         doNothing().when(mFragment).finish();
         doReturn(mView).when(mFragment).getView();
 
@@ -102,12 +117,26 @@
         doReturn(mImsManager).when(mFragment).getImsManager();
         doReturn(mImsConfig).when(mImsManager).getConfigInterface();
         doReturn(true).when(mImsManager).isWfcProvisionedOnDevice();
+        doReturn(true).when(mImsManager).isWfcEnabledByUser();
+        doReturn(true).when(mImsManager).isNonTtyOrTtyOnVolteEnabled();
+        doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
+                .when(mImsManager).getWfcMode(anyBoolean());
+
+        doReturn(mBundle).when(sCarrierConfigManager).getConfigForSubId(anyInt());
+        setDefaultCarrierConfigValues();
 
         mFragment.onAttach(mContext);
         mFragment.onCreate(null);
         mFragment.onActivityCreated(null);
     }
 
+    private void setDefaultCarrierConfigValues() {
+        mBundle.putBoolean(
+                CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, false);
+        mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, true);
+        mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, true);
+    }
+
     @Test
     public void getHelpResource_shouldReturn0() {
         assertThat(mFragment.getHelpResource()).isEqualTo(0);
@@ -143,10 +172,106 @@
         verify(mImsConfig).removeConfigCallback(any());
     }
 
+    @Test
+    public void onResume_useWfcHomeModeConfigFalseAndEditable_shouldShowWfcRoaming() {
+        // Call onResume to update the WFC roaming preference.
+        mFragment.onResume();
+
+        // Check that WFC roaming preference is shown.
+        verify(mPreferenceScreen, times(1)).addPreference(mButtonWfcRoamingMode);
+        verify(mPreferenceScreen, never()).removePreference(mButtonWfcRoamingMode);
+    }
+
+    @Test
+    public void onResume_useWfcHomeModeConfigTrueAndEditable_shouldHideWfcRoaming() {
+        mBundle.putBoolean(
+                CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, true);
+        mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, true);
+
+        // Call onResume to update the WFC roaming preference.
+        mFragment.onResume();
+
+        // Check that WFC roaming preference is hidden.
+        verify(mPreferenceScreen, never()).addPreference(mButtonWfcRoamingMode);
+        verify(mPreferenceScreen, times(1)).removePreference(mButtonWfcRoamingMode);
+    }
+
+    @Test
+    public void onResume_useWfcHomeModeConfigFalseAndNotEditable_shouldHideWfcRoaming() {
+        mBundle.putBoolean(
+                CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, false);
+        mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
+
+        // Call onResume to update the WFC roaming preference.
+        mFragment.onResume();
+
+        // Check that WFC roaming preference is hidden.
+        verify(mPreferenceScreen, never()).addPreference(mButtonWfcRoamingMode);
+        verify(mPreferenceScreen, times(1)).removePreference(mButtonWfcRoamingMode);
+    }
+
+    @Test
+    public void onResume_useWfcHomeModeConfigTrueAndNotEditable_shouldHideWfcRoaming() {
+        mBundle.putBoolean(
+                CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, true);
+        mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
+
+        // Call onResume to update the WFC roaming preference.
+        mFragment.onResume();
+
+        // Check that WFC roaming preference is hidden.
+        verify(mPreferenceScreen, never()).addPreference(mButtonWfcRoamingMode);
+        verify(mPreferenceScreen, times(1)).removePreference(mButtonWfcRoamingMode);
+    }
+
+    @Test
+    public void onPreferenceChange_useWfcHomeModeConfigFalse_shouldNotSetWfcRoaming() {
+        // Call onResume to update carrier config values.
+        mFragment.onResume();
+
+        // Set the WFC home mode.
+        mFragment.onPreferenceChange(mButtonWfcMode,
+                String.valueOf(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED));
+
+        // Check that only WFC home mode is set.
+        verify(mImsManager, times(1)).setWfcMode(
+                eq(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED),
+                eq(false));
+        verify(mImsManager, never()).setWfcMode(
+                eq(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED),
+                eq(true));
+    }
+
+    @Test
+    public void onPreferenceChange_useWfcHomeModeConfigTrue_shouldSetWfcRoaming() {
+        mBundle.putBoolean(
+                CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, true);
+
+        // Call onResume to update carrier config values.
+        mFragment.onResume();
+
+        // Set the WFC home mode.
+        mFragment.onPreferenceChange(mButtonWfcMode,
+                String.valueOf(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED));
+
+        // Check that both WFC home mode and roaming mode are set.
+        verify(mImsManager, times(1)).setWfcMode(
+                eq(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED),
+                eq(false));
+        verify(mImsManager, times(1)).setWfcMode(
+                eq(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED),
+                eq(true));
+    }
+
     protected static class TestFragment extends WifiCallingSettingsForSub {
         @Override
         protected Object getSystemService(final String name) {
-            return null;
+            switch (name) {
+                case Context.CARRIER_CONFIG_SERVICE:
+                    return sCarrierConfigManager;
+                default:
+                    return null;
+            }
         }
     }
 }