Add Wi-Fi Calling preference screen

Change-Id: Ie89902b55c5c4184236636f5039b3246a9c0bda5
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ad84ff9..e49c6a2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2058,6 +2058,23 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="Settings$WifiCallingSettingsActivity"
+                  android:label="@string/wifi_calling_settings_title"
+                  android:taskAffinity="">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <action android:name="android.settings.WIFI_CALLING_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.VOICE_LAUNCH" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.WifiCallingSettings" />
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                       android:value="true" />
+            <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
+                       android:resource="@id/wireless_settings" />
+        </activity>
+
         <provider
             android:name=".search.SettingsSearchIndexablesProvider"
             android:authorities="com.android.settings"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6af190d..190cb80 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1884,6 +1884,35 @@
          Label on Wifi Configuration screen-->
     <string name="config_list_label" translatable="false">Configured networks</string>
 
+    <!-- Wireless networks, item title to go into the WFC settings -->
+    <string name="wifi_calling_settings_title">Wi-Fi calling</string>
+    <!-- WFC mode [CHAR LIMIT=30] -->
+    <string name="wifi_calling_mode_title">Wi-Fi calling mode</string>
+    <!-- WFC mode dialog [CHAR LIMIT=30] -->
+    <string name="wifi_calling_mode_dialog_title">Wi-Fi calling mode</string>
+    <string-array name="wifi_calling_mode_choices">
+        <item>Wi-Fi preferred</item>
+        <item>Cellular preferred</item>
+        <item>Wi-Fi only</item>
+    </string-array>
+    <string-array name="wifi_calling_mode_values">
+        <item>"2"</item>
+        <item>"1"</item>
+        <item>"0"</item>
+    </string-array>
+    <!-- WFC, summary for Disabled [CHAR LIMIT=100] -->
+    <string name="wifi_calling_off_summary">Off</string>
+    <!-- WFC, summary for Wi-Fi Preferred [CHAR LIMIT=100] -->
+    <string name="wfc_mode_wifi_preferred_summary">Wi-Fi preferred (Uses cell network only if Wi-Fi isn\'t available)</string>
+    <!-- WFC, summary for Cellular Preferred [CHAR LIMIT=100] -->
+    <string name="wfc_mode_cellular_preferred_summary">Cellular preferred (Uses Wi-Fi only if cell network isn\'t available)</string>
+    <!-- WFC, summary for Wi-Fi Only [CHAR LIMIT=100] -->
+    <string name="wfc_mode_wifi_only_summary">Wi-Fi only (Never uses cell network. Can\'t make or receive calls if Wi-Fi isn\'t available)</string>
+    <!-- WFC roam enable/disable [CHAR LIMIT=30] -->
+    <string name="wifi_calling_roam_title">WFC handoff while roaming</string>
+    <!-- WFC roam summary [CHAR LIMIT=80] -->
+    <string name="wifi_calling_roam_summary">Allow Wi-Fi voice calls handoff to cell network when roaming</string>
+
     <!-- Sound and alerts settings -->
     <skip/>
     <!-- Main Settings screen setting option name to go into the display settings screen -->
diff --git a/res/xml/wifi_calling_settings.xml b/res/xml/wifi_calling_settings.xml
new file mode 100644
index 0000000..37a2d28
--- /dev/null
+++ b/res/xml/wifi_calling_settings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  android:key="wifi_calling_settings"
+                  android:title="@string/wifi_calling_settings_title">
+
+    <ListPreference
+            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" />
+
+    <SwitchPreference
+            android:key="wifi_calling_roam"
+            android:title="@string/wifi_calling_roam_title"
+            android:persistent="false"/>
+
+</PreferenceScreen>
diff --git a/res/xml/wireless_settings.xml b/res/xml/wireless_settings.xml
index a5f722b..fc3ca16 100644
--- a/res/xml/wireless_settings.xml
+++ b/res/xml/wireless_settings.xml
@@ -63,6 +63,11 @@
             android:targetClass="com.android.phone.MobileNetworkSettings" />
     </PreferenceScreen>
 
+    <PreferenceScreen
+        android:key="wifi_calling_settings"
+        android:title="@string/wifi_calling_settings_title"
+        android:fragment="com.android.settings.WifiCallingSettings" />
+
     <Preference
         android:key="manage_mobile_plan"
         android:title="@string/manage_mobile_plan_title"
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 84bf615..ebb7491 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -101,5 +101,6 @@
 
     public static class TopLevelSettings extends SettingsActivity { /* empty */ }
     public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class WifiCallingSettingsActivity extends SettingsActivity { /* empty */ }
 }
 
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index dc5675c..cbffa86 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -112,6 +112,7 @@
 import com.android.settings.wifi.SavedAccessPointsWifiSettings;
 import com.android.settings.wifi.WifiSettings;
 import com.android.settings.wifi.p2p.WifiP2pSettings;
+import com.android.settings.WifiCallingSettings;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -302,7 +303,8 @@
             AppNotificationSettings.class.getName(),
             OtherSoundSettings.class.getName(),
             QuickLaunchSettings.class.getName(),
-            ApnSettings.class.getName()
+            ApnSettings.class.getName(),
+            WifiCallingSettings.class.getName()
     };
 
 
diff --git a/src/com/android/settings/WifiCallingSettings.java b/src/com/android/settings/WifiCallingSettings.java
new file mode 100644
index 0000000..6b64fdf
--- /dev/null
+++ b/src/com/android/settings/WifiCallingSettings.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2015 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.content.Context;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.SwitchPreference;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.widget.Switch;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
+import com.android.settings.search.Indexable;
+import com.android.settings.widget.SwitchBar;
+
+/**
+ * "Wi-Fi Calling settings" screen.  This preference screen lets you
+ * enable/disable Wi-Fi Calling, change mode, enable/disable
+ * handover while on roaming.
+ */
+public class WifiCallingSettings extends SettingsPreferenceFragment
+        implements SwitchBar.OnSwitchChangeListener,
+        Preference.OnPreferenceChangeListener, Indexable {
+
+    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_ROAM = "wifi_calling_roam";
+
+    //UI objects
+    private SwitchBar mSwitchBar;
+    private Switch mSwitch;
+    private ListPreference mButtonWfcMode;
+    private SwitchPreference mButtonWfcRoam;
+
+    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);
+
+            Preference pref = getPreferenceScreen().findPreference(BUTTON_WFC_MODE);
+            int wfcMode = ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
+            if (pref != null) {
+                pref.setEnabled(isWfcEnabled
+                        && (state == TelephonyManager.CALL_STATE_IDLE));
+                ListPreference prefWfcMode = (ListPreference) pref;
+                wfcMode = Integer.valueOf(prefWfcMode.getValue()).intValue();
+            }
+            pref = getPreferenceScreen().findPreference(BUTTON_WFC_ROAM);
+            if (pref != null) {
+                pref.setEnabled(isWfcEnabled
+                        && (wfcMode != ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY)
+                        && (state == TelephonyManager.CALL_STATE_IDLE));
+            }
+        }
+    };
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        final SettingsActivity activity = (SettingsActivity) getActivity();
+
+        mSwitchBar = activity.getSwitchBar();
+        mSwitch = mSwitchBar.getSwitch();
+        mSwitchBar.show();
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        mSwitchBar.hide();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        addPreferencesFromResource(R.xml.wifi_calling_settings);
+
+        mButtonWfcMode = (ListPreference) findPreference(BUTTON_WFC_MODE);
+        mButtonWfcMode.setOnPreferenceChangeListener(this);
+
+        mButtonWfcRoam = (SwitchPreference) findPreference(BUTTON_WFC_ROAM);
+        mButtonWfcRoam.setOnPreferenceChangeListener(this);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        final Context context = getActivity();
+
+        if (ImsManager.isWfcEnabledByPlatform(context)) {
+            TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+            tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+
+            mSwitchBar.addOnSwitchChangeListener(this);
+        }
+
+        // NOTE: Buttons will be enabled/disabled in mPhoneStateListener
+        boolean wfcEnabled = ImsManager.isWfcEnabledByUser(context)
+                && ImsManager.isNonTtyOrTtyOnVolteEnabled(context);
+        mSwitch.setChecked(wfcEnabled);
+
+        int wfcMode = ImsManager.getWfcMode(context);
+        mButtonWfcMode.setValue(Integer.toString(wfcMode));
+        mButtonWfcMode.setSummary(getWfcModeSummary(context, ImsManager.getWfcMode(context)));
+
+        mButtonWfcRoam.setChecked(wfcEnabled
+                && (wfcMode != ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY)
+                && ImsManager.isWfcRoamingEnabledByUser(context));
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        if (ImsManager.isWfcEnabledByPlatform(getActivity())) {
+            TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+            tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+
+            mSwitchBar.removeOnSwitchChangeListener(this);
+        }
+    }
+
+    /**
+     * Listens to the state change of the switch.
+     */
+    @Override
+    public void onSwitchChanged(Switch switchView, boolean isChecked) {
+        final Context context = getActivity();
+
+        ImsManager.setWfcSetting(context, isChecked);
+
+        mButtonWfcMode.setEnabled(isChecked);
+        boolean wfcHandoffEnabled = (ImsManager.getWfcMode(context)
+                != ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY);
+        mButtonWfcRoam.setEnabled(isChecked && wfcHandoffEnabled);
+        mButtonWfcRoam.setChecked(isChecked && wfcHandoffEnabled
+                && ImsManager.isWfcRoamingEnabledByUser(context));
+    }
+
+    @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 currentMode = ImsManager.getWfcMode(context);
+            if (buttonMode != currentMode) {
+                ImsManager.setWfcMode(context, buttonMode);
+                mButtonWfcMode.setSummary(getWfcModeSummary(context, buttonMode));
+            }
+            boolean wfcHandoffEnabled =
+                    (buttonMode != ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY);
+            mButtonWfcRoam.setEnabled(wfcHandoffEnabled);
+            mButtonWfcRoam.setChecked(wfcHandoffEnabled &&
+                    ImsManager.isWfcRoamingEnabledByUser(context));
+        } else if (preference == mButtonWfcRoam) {
+            SwitchPreference wfcRoamPref = (SwitchPreference) preference;
+            wfcRoamPref.setChecked(!wfcRoamPref.isChecked());
+            ImsManager.setWfcRoamingSetting(context, wfcRoamPref.isChecked());
+        }
+        return true;
+    }
+
+    static int getWfcModeSummary(Context context, int wfcMode) {
+        int resId = R.string.wifi_calling_off_summary;
+        if (ImsManager.isWfcEnabledByUser(context)) {
+            switch (wfcMode) {
+                case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
+                    resId = R.string.wfc_mode_wifi_only_summary;
+                    break;
+                case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED:
+                    resId = R.string.wfc_mode_cellular_preferred_summary;
+                    break;
+                case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED:
+                    resId = R.string.wfc_mode_wifi_preferred_summary;
+                    break;
+                default:
+                    Log.e(TAG, "Unexpected WFC mode value: " + wfcMode);
+            }
+        }
+        return resId;
+    }
+}
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index e9c39d9..9152870 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -47,6 +47,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
 import com.android.internal.telephony.SmsApplication;
 import com.android.internal.telephony.SmsApplication.SmsApplicationData;
 import com.android.internal.telephony.TelephonyIntents;
@@ -54,6 +56,7 @@
 import com.android.settings.nfc.NfcEnabler;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
+import com.android.settings.WifiCallingSettings;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -76,6 +79,7 @@
     private static final String KEY_SMS_APPLICATION = "sms_application";
     private static final String KEY_TOGGLE_NSD = "toggle_nsd"; //network service discovery
     private static final String KEY_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
+    private static final String KEY_WFC_SETTINGS = "wifi_calling_settings";
 
     public static final String EXIT_ECM_RESULT = "exit_ecm_result";
     public static final int REQUEST_CODE_EXIT_ECM = 1;
@@ -95,6 +99,7 @@
     private static final String SAVED_MANAGE_MOBILE_PLAN_MSG = "mManageMobilePlanMessage";
 
     private AppListPreference mSmsApplicationPreference;
+    private PreferenceScreen mButtonWfc;
 
     /**
      * Invoked on each preference click in this hierarchy, overrides
@@ -282,6 +287,12 @@
             initSmsApplicationSetting();
         }
 
+        if (ImsManager.isWfcEnabledByPlatform(activity)) {
+            mButtonWfc = (PreferenceScreen) findPreference(KEY_WFC_SETTINGS);
+        } else {
+            removePreference(KEY_WFC_SETTINGS);
+        }
+
         // Remove NSD checkbox by default
         getPreferenceScreen().removePreference(nsd);
         //mNsdEnabler = new NsdEnabler(activity, nsd);
@@ -423,6 +434,12 @@
         if (mNsdEnabler != null) {
             mNsdEnabler.resume();
         }
+
+        final Context context = getActivity();
+        if (ImsManager.isWfcEnabledByPlatform(context)) {
+            mButtonWfc.setSummary(WifiCallingSettings.getWfcModeSummary(
+                    context, ImsManager.getWfcMode(context)));
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java
index 6abbc3d..0022338 100644
--- a/src/com/android/settings/search/Ranking.java
+++ b/src/com/android/settings/search/Ranking.java
@@ -47,6 +47,7 @@
 import com.android.settings.wifi.AdvancedWifiSettings;
 import com.android.settings.wifi.SavedAccessPointsWifiSettings;
 import com.android.settings.wifi.WifiSettings;
+import com.android.settings.WifiCallingSettings;
 
 import java.util.HashMap;
 
@@ -104,6 +105,7 @@
 
         // Other wireless settinfs
         sRankMap.put(WirelessSettings.class.getName(), RANK_WIRELESS);
+        sRankMap.put(WifiCallingSettings.class.getName(), RANK_WIRELESS);
 
         // Home
         sRankMap.put(HomeSettings.class.getName(), RANK_HOME);
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 502480d..d774469 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -49,6 +49,7 @@
 import com.android.settings.wifi.AdvancedWifiSettings;
 import com.android.settings.wifi.SavedAccessPointsWifiSettings;
 import com.android.settings.wifi.WifiSettings;
+import com.android.settings.WifiCallingSettings;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -270,6 +271,13 @@
                         NO_DATA_RES_ID,
                         DeviceInfoSettings.class.getName(),
                         R.drawable.ic_settings_about));
+
+        sResMap.put(WifiCallingSettings.class.getName(),
+                new SearchIndexableResource(
+                        Ranking.getRankForClassName(WifiCallingSettings.class.getName()),
+                        R.xml.wifi_calling_settings,
+                        WifiCallingSettings.class.getName(),
+                        R.drawable.ic_settings_wireless));
     }
 
     private SearchIndexableResources() {