Update IMSI protection notification flow

Bug: 161932419
Test: atest com.android.server.wifi

Merged-In: I8be7c1b9e66162fdd244946b47367290116a7747
Change-Id: I922a46fee984721ca2fef8c0e2c1307718b2b7e8
diff --git a/libs/WifiTrackerLib/res/values/strings.xml b/libs/WifiTrackerLib/res/values/strings.xml
index c238f66..7e81b58 100644
--- a/libs/WifiTrackerLib/res/values/strings.xml
+++ b/libs/WifiTrackerLib/res/values/strings.xml
@@ -170,7 +170,7 @@
     <string name="osu_sign_up_complete">Sign-up complete. Connecting\u2026</string>
 
     <!-- IMSI protection warning for non-protection network [CHAR LIMIT=NONE] -->
-    <string name="imsi_protection_warning">This network receives a unique ID that can be used to track device location. <annotation id="url">Learn more</annotation></string>
+    <string name="imsi_protection_warning">This network receives a SIM ID that can be used to track device location. <annotation id="url">Learn more</annotation></string>
 
     <!-- Help URL, IMSI protection [DO NOT TRANSLATE] -->
     <string name="help_url_imsi_protection" translatable="false"></string>
diff --git a/service/AndroidManifest_Resources.xml b/service/AndroidManifest_Resources.xml
index 6d637cb..04ba1d3 100644
--- a/service/AndroidManifest_Resources.xml
+++ b/service/AndroidManifest_Resources.xml
@@ -22,6 +22,7 @@
           coreApp="true"
           android:versionCode="1"
           android:versionName="R-initial">
+    <protected-broadcast android:name="com.android.server.wifi.action.CarrierNetwork.USER_CLICKED" />
     <application
         android:label="@string/wifiResourcesAppLabel"
         android:defaultToDeviceProtectedStorage="true"
diff --git a/service/java/com/android/server/wifi/WifiCarrierInfoManager.java b/service/java/com/android/server/wifi/WifiCarrierInfoManager.java
index d483047..047f913 100644
--- a/service/java/com/android/server/wifi/WifiCarrierInfoManager.java
+++ b/service/java/com/android/server/wifi/WifiCarrierInfoManager.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wifi;
 
+import static android.Manifest.permission.NETWORK_SETTINGS;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.app.AlertDialog;
@@ -96,6 +98,10 @@
     @VisibleForTesting
     public static final String NOTIFICATION_USER_DISMISSED_INTENT_ACTION =
             "com.android.server.wifi.action.CarrierNetwork.USER_DISMISSED";
+    /** Intent when user clicked on the notification. */
+    @VisibleForTesting
+    public static final String NOTIFICATION_USER_CLICKED_INTENT_ACTION =
+            "com.android.server.wifi.action.CarrierNetwork.USER_CLICKED";
     @VisibleForTesting
     public static final String EXTRA_CARRIER_NAME =
             "com.android.server.wifi.extra.CarrierNetwork.CARRIER_NAME";
@@ -223,14 +229,16 @@
 
                     switch (intent.getAction()) {
                         case NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION:
-                            Log.i(TAG, "User clicked to allow carrier");
-                            sendImsiPrivacyConfirmationDialog(carrierName, carrierId);
-                            // Collapse the notification bar
-                            mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+                            handleUserAllowCarrierExemptionAction(carrierName, carrierId);
                             break;
                         case NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION:
                             handleUserDisallowCarrierExemptionAction(carrierName, carrierId);
                             break;
+                        case NOTIFICATION_USER_CLICKED_INTENT_ACTION:
+                            sendImsiPrivacyConfirmationDialog(carrierName, carrierId);
+                            // Collapse the notification bar
+                            mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+                            break;
                         case NOTIFICATION_USER_DISMISSED_INTENT_ACTION:
                             handleUserDismissAction();
                             return; // no need to cancel a dismissed notification, return.
@@ -297,8 +305,9 @@
         mIntentFilter.addAction(NOTIFICATION_USER_DISMISSED_INTENT_ACTION);
         mIntentFilter.addAction(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION);
         mIntentFilter.addAction(NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION);
+        mIntentFilter.addAction(NOTIFICATION_USER_CLICKED_INTENT_ACTION);
 
-        mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, null, handler);
+        mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, NETWORK_SETTINGS, handler);
         configStore.registerStoreData(wifiInjector.makeImsiProtectionExemptionStoreData(
                 new ImsiProtectionExemptionDataSource()));
 
@@ -1448,6 +1457,9 @@
                 .setStyle(new Notification.BigTextStyle()
                         .bigText(mResources.getString(
                                 R.string.wifi_suggestion_imsi_privacy_content)))
+                .setContentIntent(getPrivateBroadcast(NOTIFICATION_USER_CLICKED_INTENT_ACTION,
+                        Pair.create(EXTRA_CARRIER_NAME, carrierName),
+                        Pair.create(EXTRA_CARRIER_ID, carrierId)))
                 .setDeleteIntent(getPrivateBroadcast(NOTIFICATION_USER_DISMISSED_INTENT_ACTION,
                         Pair.create(EXTRA_CARRIER_NAME, carrierName),
                         Pair.create(EXTRA_CARRIER_ID, carrierId)))
diff --git a/service/res/values/strings.xml b/service/res/values/strings.xml
index 441ecca..ae3f197 100644
--- a/service/res/values/strings.xml
+++ b/service/res/values/strings.xml
@@ -49,11 +49,11 @@
     <string name="wifi_suggestion_action_disallow_app">No thanks</string>
 
     <!-- Notification title for a connection to a SIM-based carrier network without IMSI privacy protection. -->
-    <string name="wifi_suggestion_imsi_privacy_title"><xliff:g id="carrierName" example="xxxMobile">%s</xliff:g> wants to auto\u2011connect</string>
+    <string name="wifi_suggestion_imsi_privacy_title">Connect to <xliff:g id="carrierName" example="xxxMobile">%s</xliff:g> Wi\u2011Fi?</string>
     <!-- Notification content for a connection to a SIM-based carrier network without IMSI privacy protection.-->
-    <string name="wifi_suggestion_imsi_privacy_content">These networks receive a unique ID that can be used to track device location</string>
+    <string name="wifi_suggestion_imsi_privacy_content">These networks receive a SIM ID that can be used to track device location</string>
     <!-- Notification action for allowing carrier specified in the notification body.-->
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier">Connect anyway</string>
+    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier">Connect</string>
     <!-- Notification action for disallowing carrier specified in the notification body.-->
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier">Don\u0027t connect</string>
     <!-- Confirmation dialog title for a connection to a SIM-based carrier network without IMSI privacy protection. -->
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java
index 2c1c2ec..750e8d4 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java
@@ -19,6 +19,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION;
+import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_CLICKED_INTENT_ACTION;
 import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION;
 import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_DISMISSED_INTENT_ACTION;
 
@@ -166,6 +167,7 @@
         when(mNotificationBuilder.setTicker(any())).thenReturn(mNotificationBuilder);
         when(mNotificationBuilder.setContentTitle(any())).thenReturn(mNotificationBuilder);
         when(mNotificationBuilder.setStyle(any())).thenReturn(mNotificationBuilder);
+        when(mNotificationBuilder.setContentIntent(any())).thenReturn(mNotificationBuilder);
         when(mNotificationBuilder.setDeleteIntent(any())).thenReturn(mNotificationBuilder);
         when(mNotificationBuilder.setShowWhen(anyBoolean())).thenReturn(mNotificationBuilder);
         when(mNotificationBuilder.setLocalOnly(anyBoolean())).thenReturn(mNotificationBuilder);
@@ -1538,26 +1540,13 @@
         verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
         verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
                 WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, false);
-        validateUserApprovalDialog(CARRIER_NAME);
-
-        // Simulate user clicking on allow in the dialog.
-        ArgumentCaptor<DialogInterface.OnClickListener> clickListenerCaptor =
-                ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
-        verify(mAlertDialogBuilder, atLeastOnce()).setPositiveButton(
-                any(), clickListenerCaptor.capture());
-        assertNotNull(clickListenerCaptor.getValue());
-        clickListenerCaptor.getValue().onClick(mAlertDialog, 0);
-        mLooper.dispatchAll();
-        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-        verify(mContext).sendBroadcast(intentCaptor.capture());
-        assertEquals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intentCaptor.getValue().getAction());
         verify(mWifiConfigManager).saveToStore(true);
         assertTrue(mImsiDataSource.hasNewDataToSerialize());
         assertTrue(mWifiCarrierInfoManager
                 .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID));
         verify(mListener).onUserAllowed(DATA_CARRIER_ID);
         verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
-                WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, true);
+                WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, false);
     }
 
     @Test
@@ -1607,7 +1596,7 @@
         validateImsiProtectionNotification(CARRIER_NAME);
         //Simulate user dismissal the notification
         sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_DISMISSED_INTENT_ACTION,
-                CARRIER_NAME, DATA_SUBID);
+                CARRIER_NAME, DATA_CARRIER_ID);
         verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
                 WifiCarrierInfoManager.ACTION_USER_DISMISS, false);
         reset(mNotificationManger);
@@ -1618,7 +1607,7 @@
 
         // As there is notification is active, should not send notification again.
         sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_DISMISSED_INTENT_ACTION,
-                CARRIER_NAME, DATA_SUBID);
+                CARRIER_NAME, DATA_CARRIER_ID);
         verifyNoMoreInteractions(mNotificationManger);
         verify(mWifiConfigManager, never()).saveToStore(true);
         assertFalse(mImsiDataSource.hasNewDataToSerialize());
@@ -1642,12 +1631,10 @@
 
         mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
         validateImsiProtectionNotification(CARRIER_NAME);
-        // Simulate user clicking on allow in the notification.
-        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION,
-                CARRIER_NAME, DATA_SUBID);
+        // Simulate user clicking on the notification.
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_CLICKED_INTENT_ACTION,
+                CARRIER_NAME, DATA_CARRIER_ID);
         verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
-        verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
-                WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, false);
         validateUserApprovalDialog(CARRIER_NAME);
 
         // Simulate user clicking on disallow in the dialog.
@@ -1685,11 +1672,10 @@
 
         mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
         validateImsiProtectionNotification(CARRIER_NAME);
-        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION,
-                CARRIER_NAME, DATA_SUBID);
+        // Simulate user clicking on the notification.
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_CLICKED_INTENT_ACTION,
+                CARRIER_NAME, DATA_CARRIER_ID);
         verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
-        verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
-                WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, false);
         validateUserApprovalDialog(CARRIER_NAME);
 
         // Simulate user clicking on dismissal in the dialog.
@@ -1718,6 +1704,45 @@
     }
 
     @Test
+    public void testSendImsiProtectionExemptionDialogWithUserAllowed() {
+        // Setup carrier without IMSI privacy protection
+        when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID))
+                .thenReturn(generateTestCarrierConfig(false));
+        ArgumentCaptor<BroadcastReceiver> receiver =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
+
+        receiver.getValue().onReceive(mContext,
+                new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+        assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
+        validateImsiProtectionNotification(CARRIER_NAME);
+        // Simulate user clicking on the notification.
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_CLICKED_INTENT_ACTION,
+                CARRIER_NAME, DATA_CARRIER_ID);
+        verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
+        validateUserApprovalDialog(CARRIER_NAME);
+
+        // Simulate user clicking on allow in the dialog.
+        ArgumentCaptor<DialogInterface.OnClickListener> clickListenerCaptor =
+                ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
+        verify(mAlertDialogBuilder, atLeastOnce()).setPositiveButton(
+                any(), clickListenerCaptor.capture());
+        assertNotNull(clickListenerCaptor.getValue());
+        clickListenerCaptor.getValue().onClick(mAlertDialog, 0);
+        mLooper.dispatchAll();
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).sendBroadcast(intentCaptor.capture());
+        assertEquals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intentCaptor.getValue().getAction());
+        verify(mWifiConfigManager).saveToStore(true);
+        assertTrue(mImsiDataSource.hasNewDataToSerialize());
+        verify(mListener).onUserAllowed(DATA_CARRIER_ID);
+        verify(mWifiMetrics).addUserApprovalCarrierUiReaction(
+                WifiCarrierInfoManager.ACTION_USER_ALLOWED_CARRIER, true);
+    }
+
+    @Test
     public void testUserDataStoreIsNotLoadedNotificationWillNotBeSent() {
         // reset data source to unloaded state.
         mImsiDataSource.reset();