VoWifi Emergency Call Notification

- Display a dialog when user clicks notification
- If user clicks Ok + Do not show again, remove notification and
  dialog
- If user clicks Ok, remove dialog
- If user clicks Cancel, disable WFC setting

Bug: 179122732
Test: Manually verified by simulating
Change-Id: I9e2a7ea4e80e669584cacfdb176a53fd15bfa446
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8828c3a..99e1b43 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -104,6 +104,7 @@
 
     <protected-broadcast android:name= "com.android.phone.settings.CARRIER_PROVISIONING" />
     <protected-broadcast android:name= "com.android.phone.settings.TRIGGER_CARRIER_PROVISIONING" />
+    <protected-broadcast android:name= "com.android.internal.telephony.ACTION_VOWIFI_ENABLED" />
 
     <!-- For Vendor Debugging in Telephony -->
     <protected-broadcast android:name="android.telephony.action.ANOMALY_REPORTED" />
@@ -575,6 +576,17 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="LimitedServiceActivity"
+            android:exported="true"
+            android:excludeFromRecents="true"
+            android:launchMode="singleTask"
+            android:taskAffinity=""
+            android:theme="@android:style/Theme.Translucent.NoTitleBar">
+            <intent-filter android:priority="1000">
+                <action android:name = "com.android.internal.telephony.ACTION_VOWIFI_ENABLED" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="MMIDialogActivity"
                 android:configChanges="orientation|screenSize|keyboardHidden"
                 android:excludeFromRecents="true"
diff --git a/res/layout/frag_limited_service_alert_dialog.xml b/res/layout/frag_limited_service_alert_dialog.xml
new file mode 100644
index 0000000..ad9d378
--- /dev/null
+++ b/res/layout/frag_limited_service_alert_dialog.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+/*
+ * Copyright (C) 2022 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.
+ */
+-->
+
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:scrollbars="none">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="@dimen/limited_service_top_padding"
+        android:paddingStart="@dimen/limited_service_margin_start_end"
+        android:paddingEnd="@dimen/limited_service_margin_start_end"
+        android:paddingBottom="@dimen/limited_service_bottom_padding"
+        android:orientation="vertical">
+
+      <TextView
+          android:id="@+id/message"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:layout_marginBottom="@dimen/limited_service_text_bottom_padding"
+          android:text="@string/limited_service_alert_dialog_description"
+          android:textColor="?android:attr/textColorPrimary"
+          android:textSize="16sp"/>
+
+      <CheckBox
+          android:id="@+id/do_not_show"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:buttonTint="?android:attr/textColorPrimary"
+          android:focusable="true"
+          android:clickable="true"
+          android:text="@string/do_not_show_again"
+          android:textColor="?android:attr/textColorPrimary"
+          android:textSize="14sp"/>
+    </LinearLayout>
+</ScrollView>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e1742d8..3eb1a12 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -225,4 +225,10 @@
     <dimen name="dialpad_button_height">43dp</dimen>
     <dimen name="dialpad_button_width">43dp</dimen>
     <!-- End of Shortcut view vertical dimens. -->
+
+    <!-- values for limited service -->
+    <dimen name="limited_service_top_padding">24dp</dimen>
+    <dimen name="limited_service_bottom_padding">4dp</dimen>
+    <dimen name="limited_service_margin_start_end">24dp</dimen>
+    <dimen name="limited_service_text_bottom_padding">10dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1684e89..d744834 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2196,4 +2196,16 @@
     <!-- Telephony notification channel name for a channel containing SIP accounts removed
      notificatios -->
     <string name="notification_channel_sip_account">Deprecated SIP accounts</string>
+
+    <!-- Instruction text to notify user that emergency calls may not be possible when voice is
+    enabled over wifi. [CHAR LIMIT=NONE] -->
+    <string name="limited_service_alert_dialog_description"><xliff:g id="spn" example="Operator">%s</xliff:g> doesn\'t support emergency calls over Wi-Fi.
+\n\nEmergency calls will be placed through a mobile network. If there\'s limited mobile coverage,
+ your emergency call may not go through.
+</string>
+    <!-- Option to hide the popup dialog if it is not necessary for the user. [CHAR LIMIT=40] -->
+    <string name="do_not_show_again">Don\'t show again</string>
+    <!-- Option to turn off wifi calling -->
+    <string name="turn_off_wfc">Turn off Wi-Fi calling</string>
+    <string name="unavailable_emergency_calls_notification_name">Emergency calls may be unavailable</string>
 </resources>
diff --git a/src/com/android/phone/LimitedServiceActivity.java b/src/com/android/phone/LimitedServiceActivity.java
new file mode 100644
index 0000000..fd6c176
--- /dev/null
+++ b/src/com/android/phone/LimitedServiceActivity.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2022 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.phone;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.PreferenceManager;
+import android.support.annotation.NonNull;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.TelephonyManager;
+import android.telephony.SubscriptionManager;
+import android.util.Log;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.TextView;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.FragmentActivity;
+import com.android.internal.telephony.CarrierServiceStateTracker;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.PhoneFactory;
+
+public class LimitedServiceActivity extends FragmentActivity {
+
+    private static final String LOG_TAG = "LimitedServiceActivity";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.d(LOG_TAG, "Started LimitedServiceActivity");
+        int phoneId = getIntent().getExtras().getInt(PhoneConstants.PHONE_KEY);
+        LimitedServiceAlertDialogFragment newFragment = LimitedServiceAlertDialogFragment.
+                newInstance(phoneId);
+        newFragment.show(getSupportFragmentManager(), null);
+    }
+
+    public static class LimitedServiceAlertDialogFragment extends DialogFragment {
+        private static final String TAG = "LimitedServiceAlertDialog";
+        private static final int EVENT_IMS_CAPABILITIES_CHANGED = 1;
+        private static final String KEY_PHONE_ID = "key_phone_id";
+        private Phone mPhone;
+        private int mPhoneId;
+        private TelephonyManager mTelephonyManager;
+        private Handler mHandler;
+
+        public static LimitedServiceAlertDialogFragment newInstance(int phoneId) {
+            LimitedServiceAlertDialogFragment frag = new LimitedServiceAlertDialogFragment();
+            Log.i(TAG, "LimitedServiceAlertDialog for phoneId:" + phoneId);
+            Bundle args = new Bundle();
+            args.putInt(KEY_PHONE_ID, phoneId);
+            frag.setArguments(args);
+            return frag;
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle bundle) {
+            mPhoneId = getArguments().getInt(KEY_PHONE_ID);
+            mPhone = PhoneFactory.getPhone(mPhoneId);
+            mTelephonyManager = getContext().getSystemService(TelephonyManager.class).
+                    createForSubscriptionId(mPhone.getSubId());
+            mHandler = new MsgHandler();
+            mPhone.getServiceStateTracker().registerForImsCapabilityChanged(mHandler,
+                    EVENT_IMS_CAPABILITIES_CHANGED, null);
+            if (!SubscriptionManager.isValidPhoneId(mPhoneId)) return null;
+            super.onCreateDialog(bundle);
+            View dialogView = View.inflate(getActivity(),
+                    R.layout.frag_limited_service_alert_dialog, null);
+            TextView textView = (TextView) dialogView.findViewById(R.id.message);
+            Resources res = getResources();
+            String description = String.format(res.getString(
+                            R.string.limited_service_alert_dialog_description),
+                    mPhone.getServiceStateTracker().getServiceProviderNameOrPlmn().trim());
+            textView.setText(description);
+            CheckBox alertCheckBox = dialogView.findViewById(R.id.do_not_show);
+            SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(
+                    mPhone.getContext());
+            Log.i(TAG, "onCreateDialog " + Phone.KEY_DO_NOT_SHOW_LIMITED_SERVICE_ALERT +
+                    mPhone.getSubId() + ":" + pref.getBoolean
+                    (Phone.KEY_DO_NOT_SHOW_LIMITED_SERVICE_ALERT + mPhone.getSubId(), false));
+
+            AlertDialog alertDialog =
+                    new AlertDialog.Builder(getActivity(),
+                            android.R.style.Theme_DeviceDefault_Dialog_Alert)
+                            .setTitle(R.string.unavailable_emergency_calls_notification_name)
+                            .setView(dialogView)
+                            .setNegativeButton(
+                                    R.string.turn_off_wfc,
+                                    (dialog, which) -> onNegativeButtonClicked())
+                            .setPositiveButton(
+                                    android.R.string.ok,
+                                    (dialog, which) -> onPositiveButtonClicked(pref,
+                                            alertCheckBox.isChecked()))
+                            .create();
+            this.setCancelable(false);
+            return alertDialog;
+        }
+
+        private void onNegativeButtonClicked() {
+            Log.d(TAG, "onNegativeButtonClicked");
+            SubscriptionManager subscriptionManager = (SubscriptionManager) getContext().
+                    getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+            int[] subIds = subscriptionManager.getSubscriptionIds(mPhoneId);
+            if (subIds != null && subIds.length > 0 && SubscriptionManager.
+                    isValidSubscriptionId(subIds[0])) {
+                ImsMmTelManager imsMmTelMgr = ImsMmTelManager.
+                        createForSubscriptionId(subIds[0]);
+                Log.i(TAG, "Disabling WFC setting");
+                imsMmTelMgr.setVoWiFiSettingEnabled(false);
+            }
+            cleanUp();
+        }
+
+        private void onPositiveButtonClicked(@NonNull SharedPreferences preferences,
+                boolean isChecked) {
+            SharedPreferences.Editor editor = preferences.edit();
+            editor.putBoolean(Phone.KEY_DO_NOT_SHOW_LIMITED_SERVICE_ALERT + PhoneFactory.
+                    getPhone(mPhoneId).getSubId(), isChecked);
+            editor.apply();
+            Log.i(TAG, "onPositiveButtonClicked isChecked:" + isChecked + " phoneId:" + mPhoneId
+                    + " do not show preference:" + preferences.getBoolean
+                    (Phone.KEY_DO_NOT_SHOW_LIMITED_SERVICE_ALERT + mPhone.getSubId(), false));
+            if (isChecked) {
+                NotificationManager sNotificationManager = (NotificationManager) getContext().
+                        getSystemService(NOTIFICATION_SERVICE);
+                sNotificationManager.cancel(CarrierServiceStateTracker.EMERGENCY_NOTIFICATION_TAG,
+                        mPhone.getSubId());
+            }
+            cleanUp();
+        }
+
+        private void cleanUp() {
+            mPhone.getServiceStateTracker().unregisterForImsCapabilityChanged(mHandler);
+            dismiss();
+            getActivity().finish();
+        }
+
+        private class MsgHandler extends Handler {
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case EVENT_IMS_CAPABILITIES_CHANGED:
+                        if (!mTelephonyManager.isWifiCallingAvailable()) {
+                            cleanUp();
+                        }
+                        break;
+                }
+            }
+        }
+    }
+}