Alert user when they start data roaming

We already tell them when we stop their data because we have moved to a
data roaming network, but this allows us to optionally also notify them
that their network is now data roaming when they have data roaming on.

Bug: 133358875
Test: manual
Change-Id: I3adfc6307a16bf3e94fa3036cc46fe8c2f720ffe
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index 3b9f996..1012a9e 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -92,7 +92,7 @@
     static final int NETWORK_SELECTION_NOTIFICATION = 2;
     static final int VOICEMAIL_NOTIFICATION = 3;
     static final int CALL_FORWARD_NOTIFICATION = 4;
-    static final int DATA_DISCONNECTED_ROAMING_NOTIFICATION = 5;
+    static final int DATA_ROAMING_NOTIFICATION = 5;
     static final int SELECTED_OPERATOR_FAIL_NOTIFICATION = 6;
     static final int LIMITED_SIM_FUNCTION_NOTIFICATION = 7;
 
@@ -569,23 +569,39 @@
     }
 
     /**
-     * Shows the "data disconnected due to roaming" notification, which
+     * Shows either:
+     * 1) the "Data roaming is on" notification, which
+     * appears when you're roaming and you have the "data roaming" feature turned on for the
+     * given {@code subId}.
+     * or
+     * 2) the "data disconnected due to roaming" notification, which
      * appears when you lose data connectivity because you're roaming and
      * you have the "data roaming" feature turned off for the given {@code subId}.
+     * @param subId which subscription it's notifying about.
+     * @param roamingOn whether currently roaming is on or off. If true, we show notification
+     *                  1) above; else we show notification 2).
      */
-    /* package */ void showDataDisconnectedRoaming(int subId) {
-        if (DBG) log("showDataDisconnectedRoaming()...");
+    /* package */ void showDataRoamingNotification(int subId, boolean roamingOn) {
+        if (DBG) {
+            log("showDataRoamingNotification() roaming " + (roamingOn ? "on" : "off")
+                    + " on subId " + subId);
+        }
 
         // "Mobile network settings" screen / dialog
         Intent intent = new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS);
         intent.putExtra(Settings.EXTRA_SUB_ID, subId);
         PendingIntent contentIntent = PendingIntent.getActivity(mContext, subId, intent, 0);
 
-        final CharSequence contentText = mContext.getText(R.string.roaming_reenable_message);
+        CharSequence contentTitle = mContext.getText(roamingOn
+                ? R.string.roaming_on_notification_title
+                : R.string.roaming_notification_title);
+        CharSequence contentText = mContext.getText(roamingOn
+                ? R.string.roaming_enabled_message
+                : R.string.roaming_reenable_message);
 
         final Notification.Builder builder = new Notification.Builder(mContext)
                 .setSmallIcon(android.R.drawable.stat_sys_warning)
-                .setContentTitle(mContext.getText(R.string.roaming_notification_title))
+                .setContentTitle(contentTitle)
                 .setColor(mContext.getResources().getColor(R.color.dialer_theme_color))
                 .setContentText(contentText)
                 .setChannel(NotificationChannelController.CHANNEL_ID_MOBILE_DATA_STATUS)
@@ -593,15 +609,15 @@
         final Notification notif =
                 new Notification.BigTextStyle(builder).bigText(contentText).build();
         mNotificationManager.notifyAsUser(
-                null /* tag */, DATA_DISCONNECTED_ROAMING_NOTIFICATION, notif, UserHandle.ALL);
+                null /* tag */, DATA_ROAMING_NOTIFICATION, notif, UserHandle.ALL);
     }
 
     /**
-     * Turns off the "data disconnected due to roaming" notification.
+     * Turns off the "data disconnected due to roaming" or "Data roaming is on" notification.
      */
-    /* package */ void hideDataDisconnectedRoaming() {
-        if (DBG) log("hideDataDisconnectedRoaming()...");
-        mNotificationManager.cancel(DATA_DISCONNECTED_ROAMING_NOTIFICATION);
+    /* package */ void hideDataRoamingNotification() {
+        if (DBG) log("hideDataRoamingNotification()...");
+        mNotificationManager.cancel(DATA_ROAMING_NOTIFICATION);
     }
 
     /**
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 8d3027a..9953a43 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -16,6 +16,7 @@
 
 package com.android.phone;
 
+import android.annotation.IntDef;
 import android.app.Activity;
 import android.app.KeyguardManager;
 import android.app.ProgressDialog;
@@ -74,6 +75,8 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 
 /**
@@ -109,11 +112,12 @@
     private static final int EVENT_SIM_NETWORK_LOCKED = 3;
     private static final int EVENT_SIM_STATE_CHANGED = 8;
     private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10;
-    private static final int EVENT_DATA_ROAMING_OK = 11;
-    private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12;
-    private static final int EVENT_RESTART_SIP = 13;
-    private static final int EVENT_DATA_ROAMING_SETTINGS_CHANGED = 14;
-    private static final int EVENT_MOBILE_DATA_SETTINGS_CHANGED = 15;
+    private static final int EVENT_DATA_ROAMING_CONNECTED = 11;
+    private static final int EVENT_DATA_ROAMING_OK = 12;
+    private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 13;
+    private static final int EVENT_RESTART_SIP = 14;
+    private static final int EVENT_DATA_ROAMING_SETTINGS_CHANGED = 15;
+    private static final int EVENT_MOBILE_DATA_SETTINGS_CHANGED = 16;
 
     // The MMI codes are also used by the InCallScreen.
     public static final int MMI_INITIATE = 51;
@@ -160,7 +164,21 @@
     private Activity mPUKEntryActivity;
     private ProgressDialog mPUKEntryProgressDialog;
 
-    private boolean mNoDataDueToRoaming = false;
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"ROAMING_NOTIFICATION_"},
+            value = {
+                    ROAMING_NOTIFICATION_NO_NOTIFICATION,
+                    ROAMING_NOTIFICATION_CONNECTED,
+                    ROAMING_NOTIFICATION_DISCONNECTED})
+    public @interface RoamingNotification {}
+
+    private static final int ROAMING_NOTIFICATION_NO_NOTIFICATION = 0;
+    private static final int ROAMING_NOTIFICATION_CONNECTED       = 1;
+    private static final int ROAMING_NOTIFICATION_DISCONNECTED    = 2;
+
+    @RoamingNotification
+    private int mPrevRoamingNotification = ROAMING_NOTIFICATION_NO_NOTIFICATION;
 
     private WakeState mWakeState = WakeState.SLEEP;
 
@@ -209,11 +227,15 @@
                     break;
 
                 case EVENT_DATA_ROAMING_DISCONNECTED:
-                    notificationMgr.showDataDisconnectedRoaming(msg.arg1);
+                    notificationMgr.showDataRoamingNotification(msg.arg1, false);
+                    break;
+
+                case EVENT_DATA_ROAMING_CONNECTED:
+                    notificationMgr.showDataRoamingNotification(msg.arg1, true);
                     break;
 
                 case EVENT_DATA_ROAMING_OK:
-                    notificationMgr.hideDataDisconnectedRoaming();
+                    notificationMgr.hideDataRoamingNotification();
                     break;
 
                 case MMI_COMPLETE:
@@ -721,6 +743,16 @@
     }
 
     /**
+     * @return whether or not we should show a notification when connecting to data roaming if the
+     * user has data roaming enabled
+     */
+    private boolean shouldShowDataConnectedRoaming(int subId) {
+        PersistableBundle config = getCarrierConfigForSubId(subId);
+        return config.getBoolean(CarrierConfigManager
+                .KEY_SHOW_DATA_CONNECTED_ROAMING_NOTIFICATION_BOOL);
+    }
+
+    /**
      * When roaming, if mobile data cannot be established due to data roaming not enabled, we need
      * to notify the user so they can enable it through settings. Vise versa if the condition
      * changes, we need to dismiss the notification.
@@ -737,27 +769,48 @@
         boolean dataAllowed = phone.isDataAllowed(ApnSetting.TYPE_DEFAULT, reasons);
         mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons);
         if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons);
-        if (!mNoDataDueToRoaming
-                && !dataAllowed
-                && reasons.containsOnly(DataDisallowedReasonType.ROAMING_DISABLED)) {
+        if (!dataAllowed && reasons.containsOnly(DataDisallowedReasonType.ROAMING_DISABLED)) {
+            // No need to show it again if we never cancelled it explicitly.
+            if (mPrevRoamingNotification == ROAMING_NOTIFICATION_DISCONNECTED) return;
             // If the only reason of no data is data roaming disabled, then we notify the user
             // so the user can turn on data roaming.
-            mNoDataDueToRoaming = true;
+            mPrevRoamingNotification = ROAMING_NOTIFICATION_DISCONNECTED;
             Log.d(LOG_TAG, "Show roaming disconnected notification");
-            mDataRoamingNotifLog.log("Show");
+            mDataRoamingNotifLog.log("Show roaming off.");
             Message msg = mHandler.obtainMessage(EVENT_DATA_ROAMING_DISCONNECTED);
             msg.arg1 = mDefaultDataSubId;
             msg.sendToTarget();
-        } else if (mNoDataDueToRoaming && (dataAllowed
-                || !reasons.containsOnly(DataDisallowedReasonType.ROAMING_DISABLED))) {
-            // Otherwise dismiss the notification we showed earlier.
-            mNoDataDueToRoaming = false;
-            Log.d(LOG_TAG, "Dismiss roaming disconnected notification");
+        } else if (dataAllowed && dataIsNowRoaming(mDefaultDataSubId)
+                && shouldShowDataConnectedRoaming(mDefaultDataSubId)) {
+            // No need to show it again if we never cancelled it explicitly, or carrier config
+            // indicates this is not needed.
+            if (mPrevRoamingNotification == ROAMING_NOTIFICATION_CONNECTED) return;
+            mPrevRoamingNotification = ROAMING_NOTIFICATION_CONNECTED;
+            Log.d(LOG_TAG, "Show roaming connected notification");
+            mDataRoamingNotifLog.log("Show roaming on.");
+            Message msg = mHandler.obtainMessage(EVENT_DATA_ROAMING_CONNECTED);
+            msg.arg1 = mDefaultDataSubId;
+            msg.sendToTarget();
+        } else if (mPrevRoamingNotification != ROAMING_NOTIFICATION_NO_NOTIFICATION) {
+            // Otherwise we either 1) we are not roaming or 2) roaming is off but ROAMING_DISABLED
+            // is not the only data disable reason. In this case we dismiss the notification we
+            // showed earlier.
+            mPrevRoamingNotification = ROAMING_NOTIFICATION_NO_NOTIFICATION;
+            Log.d(LOG_TAG, "Dismiss roaming notification");
             mDataRoamingNotifLog.log("Hide. data allowed=" + dataAllowed + ", reasons=" + reasons);
             mHandler.sendEmptyMessage(EVENT_DATA_ROAMING_OK);
         }
     }
 
+    /**
+     *
+     * @param subId to check roaming on
+     * @return whether we have transitioned to dataRoaming
+     */
+    private boolean dataIsNowRoaming(int subId) {
+        return getPhone(subId).getServiceState().getDataRoaming();
+    }
+
     private void updateLimitedSimFunctionForDualSim() {
         if (DBG) Log.d(LOG_TAG, "updateLimitedSimFunctionForDualSim");
         // check conditions to display limited SIM function notification under dual SIM
@@ -828,7 +881,7 @@
         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
         pw.println("------- PhoneGlobals -------");
         pw.increaseIndent();
-        pw.println("mNoDataDueToRoaming=" + mNoDataDueToRoaming);
+        pw.println("mPrevRoamingNotification=" + mPrevRoamingNotification);
         pw.println("mDefaultDataSubId=" + mDefaultDataSubId);
         pw.println("mDataRoamingNotifLog:");
         pw.println("isSmsCapable=" + TelephonyManager.from(this).isSmsCapable());