diff options
author | Roshan Pius <rpius@google.com> | 2019-01-09 15:22:27 -0800 |
---|---|---|
committer | Roshan Pius <rpius@google.com> | 2019-01-18 08:02:24 -0800 |
commit | 768dcd10ef7113a7a91e8a3352cd491aee11c925 (patch) | |
tree | 39b12869dcbe8618e753dbfe5127e4b2b1d141a3 /tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java | |
parent | f5b1eaecda28293d3273dc1ea1ec3578e173a332 (diff) | |
download | android_frameworks_opt_net_wifi-768dcd10ef7113a7a91e8a3352cd491aee11c925.tar.gz android_frameworks_opt_net_wifi-768dcd10ef7113a7a91e8a3352cd491aee11c925.tar.bz2 android_frameworks_opt_net_wifi-768dcd10ef7113a7a91e8a3352cd491aee11c925.zip |
WifiNetworkSuggestionsManager: Post notification for user approval
Whenever a network suggested by an app is available in scan results,
post a notification asking to approve the app (if not already approved).
If there are multiple such apps matching a suggestion & pending approval,
then we pick the first one to post the notification for. Once a notification is posted,
we don't post any further notification until the user interacts with the
active notification (i.e dismiss, allow, deny).
a) If the user dismisses the notification, we popup the notification for
the next time a suggestion from the app is available in scan results.
b) If the user clicks on allow, then we don't popup notifications for
any further connection from the app.
c) If user clicks on disallow, then we revoke CHANGE_WIFI_STATE app-ops,
which will trigger a full removal of the app & it's suggestions from the
database.
Bug: 120072329
Test: Manually verified the notification posting using ACTS tests.
Test: Manual verification of interacting with the notification.
Test: `act.py -c wifi_manager.config -tb dut-name -tc
WifiNetworkSuggestionTest`
Change-Id: I4a3ed6abca01aab84fcd3717fde56bca6187fae6
Diffstat (limited to 'tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java')
-rw-r--r-- | tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java index cdfb2dfc1..feb087d78 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java @@ -19,6 +19,13 @@ package com.android.server.wifi; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_IGNORED; import static android.app.AppOpsManager.OPSTR_CHANGE_WIFI_STATE; +import static android.app.AppOpsManager.OP_CHANGE_WIFI_STATE; +import static android.app.Notification.EXTRA_TEXT; +import static android.app.Notification.EXTRA_TITLE; + +import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION; +import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION; +import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISMISSED_INTENT_ACTION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -29,8 +36,15 @@ import static org.junit.Assert.fail; import static org.mockito.Mockito.*; import android.app.AppOpsManager; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; import android.net.MacAddress; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; @@ -40,6 +54,8 @@ import android.os.UserHandle; import android.os.test.TestLooper; import android.test.suitebuilder.annotation.SmallTest; +import com.android.internal.R; +import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion; import com.android.server.wifi.WifiNetworkSuggestionsManager.PerAppInfo; import com.android.server.wifi.util.WifiPermissionsUtil; @@ -67,14 +83,20 @@ import java.util.stream.Collectors; public class WifiNetworkSuggestionsManagerTest { private static final String TEST_PACKAGE_1 = "com.test12345"; private static final String TEST_PACKAGE_2 = "com.test54321"; + private static final String TEST_APP_NAME_1 = "test12345"; + private static final String TEST_APP_NAME_2 = "test54321"; private static final String TEST_BSSID = "00:11:22:33:44:55"; private static final int TEST_UID_1 = 5667; private static final int TEST_UID_2 = 4537; private @Mock Context mContext; + private @Mock Resources mResources; private @Mock AppOpsManager mAppOpsManager; + private @Mock NotificationManager mNotificationManger; + private @Mock PackageManager mPackageManager; private @Mock WifiPermissionsUtil mWifiPermissionsUtil; private @Mock WifiInjector mWifiInjector; + private @Mock FrameworkFacade mFrameworkFacade; private @Mock WifiConfigStore mWifiConfigStore; private @Mock WifiConfigManager mWifiConfigManager; private @Mock NetworkSuggestionStoreData mNetworkSuggestionStoreData; @@ -82,6 +104,8 @@ public class WifiNetworkSuggestionsManagerTest { private TestLooper mLooper; private ArgumentCaptor<AppOpsManager.OnOpChangedListener> mAppOpChangedListenerCaptor = ArgumentCaptor.forClass(AppOpsManager.OnOpChangedListener.class); + private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); private InOrder mInorder; @@ -100,13 +124,45 @@ public class WifiNetworkSuggestionsManagerTest { when(mWifiInjector.makeNetworkSuggestionStoreData(any())) .thenReturn(mNetworkSuggestionStoreData); + when(mWifiInjector.getFrameworkFacade()).thenReturn(mFrameworkFacade); when(mWifiInjector.getClientModeImpl()).thenReturn(mClientModeImpl); + when(mFrameworkFacade.getBroadcast(any(), anyInt(), any(), anyInt())) + .thenReturn(mock(PendingIntent.class)); + when(mContext.getResources()).thenReturn(mResources); when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager); + when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)) + .thenReturn(mNotificationManger); + when(mContext.getPackageManager()).thenReturn(mPackageManager); + + // setup resource strings for notification. + when(mResources.getString(eq(R.string.wifi_suggestion_title), anyString())) + .thenAnswer(s -> "blah" + s.getArguments()[1]); + when(mResources.getString(eq(R.string.wifi_suggestion_content), anyString())) + .thenAnswer(s -> "blah" + s.getArguments()[1]); + when(mResources.getText(eq(R.string.wifi_suggestion_action_allow_app))) + .thenReturn("blah"); + when(mResources.getText(eq(R.string.wifi_suggestion_action_disallow_app))) + .thenReturn("blah"); + + // Our app Info. Needed for notification builder. + ApplicationInfo ourAppInfo = new ApplicationInfo(); + when(mContext.getApplicationInfo()).thenReturn(ourAppInfo); + // test app info + ApplicationInfo appInfO1 = new ApplicationInfo(); + when(mPackageManager.getApplicationInfo(TEST_PACKAGE_1, 0)).thenReturn(appInfO1); + when(mPackageManager.getApplicationLabel(appInfO1)).thenReturn(TEST_APP_NAME_1); + ApplicationInfo appInfO2 = new ApplicationInfo(); + when(mPackageManager.getApplicationInfo(TEST_PACKAGE_2, 0)).thenReturn(appInfO2); + when(mPackageManager.getApplicationLabel(appInfO2)).thenReturn(TEST_APP_NAME_2); mWifiNetworkSuggestionsManager = new WifiNetworkSuggestionsManager(mContext, new Handler(mLooper.getLooper()), mWifiInjector, mWifiPermissionsUtil, mWifiConfigManager, mWifiConfigStore); + verify(mContext).getResources(); verify(mContext).getSystemService(Context.APP_OPS_SERVICE); + verify(mContext).getSystemService(Context.NOTIFICATION_SERVICE); + verify(mContext).getPackageManager(); + verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any()); ArgumentCaptor<NetworkSuggestionStoreData.DataSource> dataSourceArgumentCaptor = ArgumentCaptor.forClass(NetworkSuggestionStoreData.DataSource.class); @@ -1452,6 +1508,155 @@ public class WifiNetworkSuggestionsManagerTest { } /** + * Verify handling of user dismissal of the user approval notification. + */ + @Test + public void testUserApprovalNotificationDismissal() { + WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( + WifiConfigurationTestUtil.createOpenNetwork(), true, false, TEST_UID_1); + List<WifiNetworkSuggestion> networkSuggestionList = + new ArrayList<WifiNetworkSuggestion>() {{ + add(networkSuggestion); + }}; + assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, + mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1)); + + // Simulate finding the network in scan results. + mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( + createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); + + validateUserApprovalNotification(TEST_APP_NAME_1); + + // Simulate user dismissal notification. + sendBroadcastForUserAction( + NOTIFICATION_USER_DISMISSED_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1); + + reset(mNotificationManger); + // We should resend the notification next time the network is found in scan results. + mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( + createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); + + validateUserApprovalNotification(TEST_APP_NAME_1); + verifyNoMoreInteractions(mNotificationManger); + } + + /** + * Verify handling of user clicking allow on the user approval notification. + */ + @Test + public void testUserApprovalNotificationClickOnAllow() { + WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( + WifiConfigurationTestUtil.createOpenNetwork(), true, false, TEST_UID_1); + List<WifiNetworkSuggestion> networkSuggestionList = + new ArrayList<WifiNetworkSuggestion>() {{ + add(networkSuggestion); + }}; + assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, + mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1)); + + // Simulate finding the network in scan results. + mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( + createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); + + validateUserApprovalNotification(TEST_APP_NAME_1); + + // Simulate user clicking on allow in the notification. + sendBroadcastForUserAction( + NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1); + // Cancel the notification. + verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); + + reset(mNotificationManger); + // We should not resend the notification next time the network is found in scan results. + mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( + createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); + verifyNoMoreInteractions(mNotificationManger); + } + + /** + * Verify handling of user clicking disallow on the user approval notification. + */ + @Test + public void testUserApprovalNotificationClickOnDisallow() { + WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( + WifiConfigurationTestUtil.createOpenNetwork(), true, false, TEST_UID_1); + List<WifiNetworkSuggestion> networkSuggestionList = + new ArrayList<WifiNetworkSuggestion>() {{ + add(networkSuggestion); + }}; + assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, + mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1)); + verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), + eq(TEST_PACKAGE_1), mAppOpChangedListenerCaptor.capture()); + + // Simulate finding the network in scan results. + mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( + createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); + + validateUserApprovalNotification(TEST_APP_NAME_1); + + // Simulate user clicking on disallow in the notification. + sendBroadcastForUserAction( + NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION, TEST_PACKAGE_1, TEST_UID_1); + // Ensure we turn off CHANGE_WIFI_STATE app-ops. + verify(mAppOpsManager).setMode( + OP_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1, MODE_IGNORED); + // Cancel the notification. + verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE); + + reset(mNotificationManger); + + // Now trigger the app-ops callback to ensure we remove all of their suggestions. + AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue(); + assertNotNull(listener); + when(mAppOpsManager.unsafeCheckOpNoThrow( + OPSTR_CHANGE_WIFI_STATE, TEST_UID_1, TEST_PACKAGE_1)) + .thenReturn(MODE_IGNORED); + listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE_1); + mLooper.dispatchAll(); + assertTrue(mWifiNetworkSuggestionsManager.getAllNetworkSuggestions().isEmpty()); + + // Assuming the user re-enabled the app again & added the same suggestions back. + assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, + mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1)); + + // We should resend the notification when the network is again found in scan results. + mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( + createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); + + validateUserApprovalNotification(TEST_APP_NAME_1); + verifyNoMoreInteractions(mNotificationManger); + } + + /** + * Verify that we don't send a new notification when a pending notification is active. + */ + @Test + public void testUserApprovalNotificationWhilePreviousNotificationActive() { + WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( + WifiConfigurationTestUtil.createOpenNetwork(), true, false, TEST_UID_1); + List<WifiNetworkSuggestion> networkSuggestionList = + new ArrayList<WifiNetworkSuggestion>() {{ + add(networkSuggestion); + }}; + assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, + mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_PACKAGE_1)); + + // Simulate finding the network in scan results. + mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( + createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); + + validateUserApprovalNotification(TEST_APP_NAME_1); + + reset(mNotificationManger); + // We should not resend the notification next time the network is found in scan results. + mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( + createScanDetailForNetwork(networkSuggestion.wifiConfiguration)); + + verifyNoMoreInteractions(mNotificationManger); + } + + /** * Creates a scan detail corresponding to the provided network values. */ private ScanDetail createScanDetailForNetwork(WifiConfiguration configuration) { @@ -1477,4 +1682,38 @@ public class WifiNetworkSuggestionsManagerTest { assertEquals(expectedPackageName, packageName); assertEquals(expectedNetworkSuggestion, networkSuggestion); } + + private boolean checkUserApprovalNotificationParams( + Notification notification, String expectedAppName) { + if (!notification.tickerText.toString().contains(expectedAppName)) return false; + if (!notification.extras.getString(EXTRA_TITLE).contains(expectedAppName)) return false; + if (!notification.extras.getString(EXTRA_TEXT).contains(expectedAppName)) return false; + return true; + } + + private void validateUserApprovalNotification(String... anyOfExpectedAppNames) { + ArgumentCaptor<Notification> notificationArgumentCaptor = + ArgumentCaptor.forClass(Notification.class); + verify(mNotificationManger).notify(eq(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE), + notificationArgumentCaptor.capture()); + Notification notification = notificationArgumentCaptor.getValue(); + assertNotNull(notification); + + boolean foundMatch = false; + for (int i = 0; i < anyOfExpectedAppNames.length; i++) { + foundMatch = checkUserApprovalNotificationParams( + notification, anyOfExpectedAppNames[i]); + if (foundMatch) break; + } + assertTrue(foundMatch); + } + + private void sendBroadcastForUserAction(String action, String packageName, int uid) { + Intent intent = new Intent() + .setAction(action) + .putExtra(WifiNetworkSuggestionsManager.EXTRA_PACKAGE_NAME, packageName) + .putExtra(WifiNetworkSuggestionsManager.EXTRA_UID, uid); + assertNotNull(mBroadcastReceiverCaptor.getValue()); + mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); + } } |