1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi; 18 19 import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK; 20 import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_PICK_WIFI_NETWORK; 21 import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE; 22 import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_USER_DISMISSED_NOTIFICATION; 23 import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.AVAILABLE_NETWORK_NOTIFIER_TAG; 24 import static com.android.server.wifi.OpenNetworkNotifier.DEFAULT_REPEAT_DELAY_SEC; 25 26 import static org.junit.Assert.assertEquals; 27 import static org.junit.Assert.assertNull; 28 import static org.mockito.ArgumentMatchers.any; 29 import static org.mockito.ArgumentMatchers.eq; 30 import static org.mockito.Mockito.anyInt; 31 import static org.mockito.Mockito.never; 32 import static org.mockito.Mockito.times; 33 import static org.mockito.Mockito.verify; 34 import static org.mockito.Mockito.when; 35 36 import android.app.NotificationManager; 37 import android.content.BroadcastReceiver; 38 import android.content.Context; 39 import android.content.Intent; 40 import android.content.res.Resources; 41 import android.database.ContentObserver; 42 import android.net.Uri; 43 import android.net.wifi.ScanResult; 44 import android.net.wifi.WifiManager; 45 import android.os.Message; 46 import android.os.RemoteException; 47 import android.os.UserHandle; 48 import android.os.UserManager; 49 import android.os.test.TestLooper; 50 import android.provider.Settings; 51 import android.util.ArraySet; 52 53 import com.android.server.wifi.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount; 54 55 import org.junit.Before; 56 import org.junit.Test; 57 import org.mockito.ArgumentCaptor; 58 import org.mockito.Mock; 59 import org.mockito.MockitoAnnotations; 60 61 import java.util.ArrayList; 62 import java.util.List; 63 import java.util.Set; 64 65 /** 66 * Unit tests for {@link OpenNetworkNotifier}. 67 */ 68 public class OpenNetworkNotifierTest { 69 70 private static final String TEST_SSID_1 = "Test SSID 1"; 71 private static final String TEST_SSID_2 = "Test SSID 2"; 72 private static final int MIN_RSSI_LEVEL = -127; 73 private static final String OPEN_NET_NOTIFIER_TAG = OpenNetworkNotifier.TAG; 74 75 @Mock private Context mContext; 76 @Mock private Resources mResources; 77 @Mock private FrameworkFacade mFrameworkFacade; 78 @Mock private WifiMetrics mWifiMetrics; 79 @Mock private Clock mClock; 80 @Mock private WifiConfigStore mWifiConfigStore; 81 @Mock private WifiConfigManager mWifiConfigManager; 82 @Mock private NotificationManager mNotificationManager; 83 @Mock private WifiStateMachine mWifiStateMachine; 84 @Mock private ConnectToNetworkNotificationBuilder mNotificationBuilder; 85 @Mock private UserManager mUserManager; 86 private OpenNetworkNotifier mNotificationController; 87 private TestLooper mLooper; 88 private BroadcastReceiver mBroadcastReceiver; 89 private ContentObserver mContentObserver; 90 private ScanResult mDummyNetwork; 91 private List<ScanDetail> mOpenNetworks; 92 private Set<String> mBlacklistedSsids; 93 94 95 /** Initialize objects before each test run. */ 96 @Before 97 public void setUp() throws Exception { 98 MockitoAnnotations.initMocks(this); 99 when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)) 100 .thenReturn(mNotificationManager); 101 when(mFrameworkFacade.getIntegerSetting(mContext, 102 Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1)).thenReturn(1); 103 when(mFrameworkFacade.getIntegerSetting(mContext, 104 Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, DEFAULT_REPEAT_DELAY_SEC)) 105 .thenReturn(DEFAULT_REPEAT_DELAY_SEC); 106 when(mContext.getSystemService(Context.USER_SERVICE)) 107 .thenReturn(mUserManager); 108 when(mContext.getResources()).thenReturn(mResources); 109 mDummyNetwork = new ScanResult(); 110 mDummyNetwork.SSID = TEST_SSID_1; 111 mDummyNetwork.capabilities = "[ESS]"; 112 mDummyNetwork.level = MIN_RSSI_LEVEL; 113 mOpenNetworks = new ArrayList<>(); 114 mOpenNetworks.add(new ScanDetail(mDummyNetwork, null /* networkDetail */)); 115 mBlacklistedSsids = new ArraySet<>(); 116 117 mLooper = new TestLooper(); 118 mNotificationController = new OpenNetworkNotifier( 119 mContext, mLooper.getLooper(), mFrameworkFacade, mClock, mWifiMetrics, 120 mWifiConfigManager, mWifiConfigStore, mWifiStateMachine, mNotificationBuilder); 121 ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 122 ArgumentCaptor.forClass(BroadcastReceiver.class); 123 verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any()); 124 mBroadcastReceiver = broadcastReceiverCaptor.getValue(); 125 ArgumentCaptor<ContentObserver> observerCaptor = 126 ArgumentCaptor.forClass(ContentObserver.class); 127 verify(mFrameworkFacade).registerContentObserver(eq(mContext), any(Uri.class), eq(true), 128 observerCaptor.capture()); 129 mContentObserver = observerCaptor.getValue(); 130 mNotificationController.handleScreenStateChanged(true); 131 } 132 133 /** 134 * On {@link OpenNetworkNotifier} construction, WifiMetrics should track setting state. 135 */ 136 @Test 137 public void onCreate_setWifiNetworksAvailableNotificationSettingState() { 138 verify(mWifiMetrics).setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG, 139 true); 140 } 141 142 /** 143 * When feature setting is toggled, WifiMetrics should track the disabled setting state. 144 */ 145 @Test 146 public void onFeatureDisable_setWifiNetworksAvailableNotificationSettingDisabled() { 147 when(mFrameworkFacade.getIntegerSetting(mContext, 148 Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1)).thenReturn(0); 149 mContentObserver.onChange(false); 150 151 verify(mWifiMetrics).setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG, 152 false); 153 } 154 155 /** 156 * When scan results with open networks are handled, a notification is posted. 157 */ 158 @Test 159 public void handleScanResults_hasOpenNetworks_notificationDisplayed() { 160 mNotificationController.handleScanResults(mOpenNetworks); 161 162 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 163 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 164 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 165 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 166 verify(mNotificationManager).notify(anyInt(), any()); 167 } 168 169 /** 170 * When scan results with no open networks are handled, a notification is not posted. 171 */ 172 @Test 173 public void handleScanResults_emptyList_notificationNotDisplayed() { 174 mNotificationController.handleScanResults(new ArrayList<>()); 175 176 verify(mNotificationManager, never()).notify(anyInt(), any()); 177 } 178 179 /** 180 * When the feature is disabled, no notifications are posted. 181 */ 182 @Test 183 public void handleScanResults_featureDisabled_notificationNotDisplayed() { 184 when(mFrameworkFacade.getIntegerSetting(mContext, 185 Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1)).thenReturn(0); 186 mContentObserver.onChange(false); 187 mNotificationController.handleScanResults(new ArrayList<>()); 188 189 verify(mNotificationManager, never()).notify(anyInt(), any()); 190 } 191 192 /** 193 * When a notification is showing and scan results with no open networks are handled, the 194 * notification is cleared. 195 */ 196 @Test 197 public void handleScanResults_notificationShown_emptyList_notificationCleared() { 198 mNotificationController.handleScanResults(mOpenNetworks); 199 200 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 201 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 202 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 203 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 204 verify(mNotificationManager).notify(anyInt(), any()); 205 206 mNotificationController.handleScanResults(new ArrayList<>()); 207 208 verify(mNotificationManager).cancel(anyInt()); 209 } 210 211 /** 212 * When a notification is showing and no recommendation is made for the new scan results, the 213 * notification is cleared. 214 */ 215 @Test 216 public void handleScanResults_notificationShown_noRecommendation_notificationCleared() { 217 mNotificationController.handleScanResults(mOpenNetworks); 218 219 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 220 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 221 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 222 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 223 verify(mNotificationManager).notify(anyInt(), any()); 224 225 mOpenNetworks.clear(); 226 mNotificationController.handleScanResults(mOpenNetworks); 227 228 verify(mNotificationManager).cancel(anyInt()); 229 } 230 231 /** 232 * When a notification is showing, screen is off, and scan results with no open networks are 233 * handled, the notification is cleared. 234 */ 235 @Test 236 public void handleScanResults_notificationShown_screenOff_emptyList_notificationCleared() { 237 mNotificationController.handleScanResults(mOpenNetworks); 238 239 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 240 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 241 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 242 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 243 verify(mNotificationManager).notify(anyInt(), any()); 244 245 mNotificationController.handleScreenStateChanged(false); 246 mNotificationController.handleScanResults(new ArrayList<>()); 247 248 verify(mNotificationManager).cancel(anyInt()); 249 } 250 251 /** 252 * When {@link OpenNetworkNotifier#clearPendingNotification(boolean)} is called and a 253 * notification is shown, clear the notification. 254 */ 255 @Test 256 public void clearPendingNotification_clearsNotificationIfOneIsShowing() { 257 mNotificationController.handleScanResults(mOpenNetworks); 258 259 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 260 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 261 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 262 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 263 verify(mNotificationManager).notify(anyInt(), any()); 264 265 mNotificationController.clearPendingNotification(true); 266 267 verify(mNotificationManager).cancel(anyInt()); 268 } 269 270 /** 271 * When {@link OpenNetworkNotifier#clearPendingNotification(boolean)} is called and a 272 * notification was not previously shown, do not clear the notification. 273 */ 274 @Test 275 public void clearPendingNotification_doesNotClearNotificationIfNoneShowing() { 276 mNotificationController.clearPendingNotification(true); 277 278 verify(mNotificationManager, never()).cancel(anyInt()); 279 } 280 281 /** 282 * When screen is off and notification is not displayed, notification is not posted on handling 283 * new scan results with open networks. 284 */ 285 @Test 286 public void screenOff_notificationNotShowing_handleScanResults_notificationNotDisplayed() { 287 mNotificationController.handleScreenStateChanged(false); 288 mNotificationController.handleScanResults(mOpenNetworks); 289 290 verify(mNotificationManager, never()).notify(anyInt(), any()); 291 } 292 293 /** 294 * When screen is off and notification is displayed, the notification can be updated with a new 295 * recommendation. 296 */ 297 @Test 298 public void screenOff_notificationShowing_handleScanResults_recommendationCanBeUpdated() { 299 mNotificationController.handleScanResults(mOpenNetworks); 300 301 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 302 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 303 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 304 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 305 verify(mNotificationManager).notify(anyInt(), any()); 306 307 ScanResult newNetwork = new ScanResult(); 308 newNetwork.SSID = TEST_SSID_2; 309 mDummyNetwork.capabilities = "[ESS]"; 310 mDummyNetwork.level = MIN_RSSI_LEVEL + 1; 311 mOpenNetworks.add(new ScanDetail(newNetwork, null /* networkDetail */)); 312 313 mNotificationController.handleScreenStateChanged(false); 314 mNotificationController.handleScanResults(mOpenNetworks); 315 316 // Recommendation changed 317 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 318 OPEN_NET_NOTIFIER_TAG, newNetwork); 319 verify(mWifiMetrics).incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG); 320 verify(mNotificationManager, times(2)).notify(anyInt(), any()); 321 } 322 323 /** 324 * When a notification is posted and cleared without resetting delay, the next scan with open 325 * networks should not post another notification. 326 */ 327 @Test 328 public void postNotification_clearNotificationWithoutDelayReset_shouldNotPostNotification() { 329 mNotificationController.handleScanResults(mOpenNetworks); 330 331 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 332 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 333 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 334 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 335 verify(mNotificationManager).notify(anyInt(), any()); 336 337 mNotificationController.clearPendingNotification(false); 338 339 verify(mNotificationManager).cancel(anyInt()); 340 341 mNotificationController.handleScanResults(mOpenNetworks); 342 343 // no new notification posted 344 verify(mNotificationManager).notify(anyInt(), any()); 345 } 346 347 /** 348 * When a notification is posted and cleared without resetting delay, the next scan with open 349 * networks should post a notification. 350 */ 351 @Test 352 public void postNotification_clearNotificationWithDelayReset_shouldPostNotification() { 353 mNotificationController.handleScanResults(mOpenNetworks); 354 355 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 356 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 357 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 358 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 359 verify(mNotificationManager).notify(anyInt(), any()); 360 361 mNotificationController.clearPendingNotification(true); 362 363 mNotificationController.handleScanResults(mOpenNetworks); 364 365 verify(mNotificationBuilder, times(2)).createConnectToAvailableNetworkNotification( 366 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 367 verify(mWifiMetrics, times(2)).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 368 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 369 verify(mNotificationManager, times(2)).notify(anyInt(), any()); 370 } 371 372 private Intent createIntent(String action) { 373 return new Intent(action).putExtra(AVAILABLE_NETWORK_NOTIFIER_TAG, OPEN_NET_NOTIFIER_TAG); 374 } 375 376 /** 377 * When user dismissed notification and there is a recommended network, network ssid should be 378 * blacklisted. 379 */ 380 @Test 381 public void userDismissedNotification_shouldBlacklistNetwork() { 382 mNotificationController.handleScanResults(mOpenNetworks); 383 384 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 385 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 386 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 387 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 388 verify(mNotificationManager).notify(anyInt(), any()); 389 390 mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_USER_DISMISSED_NOTIFICATION)); 391 392 verify(mWifiConfigManager).saveToStore(false /* forceWrite */); 393 394 mNotificationController.clearPendingNotification(true); 395 List<ScanDetail> scanResults = mOpenNetworks; 396 mNotificationController.handleScanResults(scanResults); 397 398 Set<String> expectedBlacklist = new ArraySet<>(); 399 expectedBlacklist.add(mDummyNetwork.SSID); 400 verify(mWifiMetrics).setNetworkRecommenderBlacklistSize(OPEN_NET_NOTIFIER_TAG, 401 expectedBlacklist.size()); 402 } 403 404 /** 405 * When a notification is posted and cleared without resetting delay, after the delay has passed 406 * the next scan with open networks should post a notification. 407 */ 408 @Test 409 public void delaySet_delayPassed_shouldPostNotification() { 410 mNotificationController.handleScanResults(mOpenNetworks); 411 412 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 413 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 414 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 415 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 416 verify(mNotificationManager).notify(anyInt(), any()); 417 418 mNotificationController.clearPendingNotification(false); 419 420 // twice the delay time passed 421 when(mClock.getWallClockMillis()).thenReturn(DEFAULT_REPEAT_DELAY_SEC * 1000L * 2); 422 423 mNotificationController.handleScanResults(mOpenNetworks); 424 425 verify(mNotificationBuilder, times(2)).createConnectToAvailableNetworkNotification( 426 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 427 verify(mWifiMetrics, times(2)).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 428 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 429 verify(mNotificationManager, times(2)).notify(anyInt(), any()); 430 } 431 432 /** Verifies that {@link UserManager#DISALLOW_CONFIG_WIFI} disables the feature. */ 433 @Test 434 public void userHasDisallowConfigWifiRestriction_notificationNotDisplayed() { 435 when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT)) 436 .thenReturn(true); 437 438 mNotificationController.handleScanResults(mOpenNetworks); 439 440 verify(mNotificationManager, never()).notify(anyInt(), any()); 441 } 442 443 /** Verifies that {@link UserManager#DISALLOW_CONFIG_WIFI} clears the showing notification. */ 444 @Test 445 public void userHasDisallowConfigWifiRestriction_showingNotificationIsCleared() { 446 mNotificationController.handleScanResults(mOpenNetworks); 447 448 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 449 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 450 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 451 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 452 verify(mNotificationManager).notify(anyInt(), any()); 453 454 when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT)) 455 .thenReturn(true); 456 457 mNotificationController.handleScanResults(mOpenNetworks); 458 459 verify(mNotificationManager).cancel(anyInt()); 460 } 461 462 /** 463 * {@link ConnectToNetworkNotificationBuilder#ACTION_CONNECT_TO_NETWORK} does not connect to 464 * any network if the initial notification is not showing. 465 */ 466 @Test 467 public void actionConnectToNetwork_notificationNotShowing_doesNothing() { 468 mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK)); 469 470 verify(mWifiStateMachine, never()).sendMessage(any(Message.class)); 471 } 472 473 /** 474 * {@link ConnectToNetworkNotificationBuilder#ACTION_CONNECT_TO_NETWORK} connects to the 475 * currently recommended network if it exists. 476 */ 477 @Test 478 public void actionConnectToNetwork_currentRecommendationExists_connectsAndPostsNotification() { 479 mNotificationController.handleScanResults(mOpenNetworks); 480 481 // Initial Notification 482 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 483 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 484 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 485 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 486 verify(mNotificationManager).notify(anyInt(), any()); 487 488 mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK)); 489 490 verify(mWifiStateMachine).sendMessage(any(Message.class)); 491 // Connecting Notification 492 verify(mNotificationBuilder).createNetworkConnectingNotification(OPEN_NET_NOTIFIER_TAG, 493 mDummyNetwork); 494 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 495 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK); 496 verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, 497 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK, 498 ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK); 499 verify(mNotificationManager, times(2)).notify(anyInt(), any()); 500 } 501 502 /** 503 * {@link ConnectToNetworkNotificationBuilder#ACTION_PICK_WIFI_NETWORK} opens Wi-Fi settings 504 * if the recommendation notification is showing. 505 */ 506 @Test 507 public void actionPickWifiNetwork_currentRecommendationExists_opensWifiSettings() { 508 mNotificationController.handleScanResults(mOpenNetworks); 509 510 // Initial Notification 511 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 512 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 513 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 514 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 515 verify(mNotificationManager).notify(anyInt(), any()); 516 517 mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_PICK_WIFI_NETWORK)); 518 519 ArgumentCaptor<Intent> pickerIntentCaptor = ArgumentCaptor.forClass(Intent.class); 520 verify(mContext).startActivity(pickerIntentCaptor.capture()); 521 assertEquals(pickerIntentCaptor.getValue().getAction(), Settings.ACTION_WIFI_SETTINGS); 522 verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, 523 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK, 524 ConnectToNetworkNotificationAndActionCount.ACTION_PICK_WIFI_NETWORK); 525 } 526 527 /** 528 * {@link OpenNetworkNotifier#handleWifiConnected()} does not post connected notification if 529 * the connecting notification is not showing 530 */ 531 @Test 532 public void networkConnectionSuccess_wasNotInConnectingFlow_doesNothing() { 533 mNotificationController.handleWifiConnected(); 534 535 verify(mNotificationManager, never()).notify(anyInt(), any()); 536 verify(mWifiMetrics, never()).incrementConnectToNetworkNotification( 537 OPEN_NET_NOTIFIER_TAG, 538 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTED_TO_NETWORK); 539 } 540 541 /** 542 * {@link OpenNetworkNotifier#handleWifiConnected()} clears notification that is not connecting. 543 */ 544 @Test 545 public void networkConnectionSuccess_wasShowingNotification_clearsNotification() { 546 mNotificationController.handleScanResults(mOpenNetworks); 547 548 // Initial Notification 549 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 550 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 551 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 552 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 553 verify(mNotificationManager).notify(anyInt(), any()); 554 555 mNotificationController.handleWifiConnected(); 556 557 verify(mNotificationManager).cancel(anyInt()); 558 } 559 560 /** 561 * {@link OpenNetworkNotifier#handleWifiConnected()} posts the connected notification if 562 * the connecting notification is showing. 563 */ 564 @Test 565 public void networkConnectionSuccess_wasInConnectingFlow_postsConnectedNotification() { 566 mNotificationController.handleScanResults(mOpenNetworks); 567 568 // Initial Notification 569 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 570 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 571 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 572 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 573 verify(mNotificationManager).notify(anyInt(), any()); 574 575 mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK)); 576 577 // Connecting Notification 578 verify(mNotificationBuilder).createNetworkConnectingNotification(OPEN_NET_NOTIFIER_TAG, 579 mDummyNetwork); 580 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 581 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK); 582 verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, 583 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK, 584 ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK); 585 verify(mNotificationManager, times(2)).notify(anyInt(), any()); 586 587 mNotificationController.handleWifiConnected(); 588 589 // Connected Notification 590 verify(mNotificationBuilder).createNetworkConnectedNotification(OPEN_NET_NOTIFIER_TAG, 591 mDummyNetwork); 592 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 593 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTED_TO_NETWORK); 594 verify(mNotificationManager, times(3)).notify(anyInt(), any()); 595 } 596 597 /** 598 * {@link OpenNetworkNotifier#handleConnectionFailure()} posts the Failed to Connect 599 * notification if the connecting notification is showing. 600 */ 601 @Test 602 public void networkConnectionFailure_wasNotInConnectingFlow_doesNothing() { 603 mNotificationController.handleConnectionFailure(); 604 605 verify(mNotificationManager, never()).notify(anyInt(), any()); 606 verify(mWifiMetrics, never()).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 607 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT); 608 } 609 610 /** 611 * {@link OpenNetworkNotifier#handleConnectionFailure()} posts the Failed to Connect 612 * notification if the connecting notification is showing. 613 */ 614 @Test 615 public void networkConnectionFailure_wasInConnectingFlow_postsFailedToConnectNotification() { 616 mNotificationController.handleScanResults(mOpenNetworks); 617 618 // Initial Notification 619 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 620 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 621 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 622 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 623 verify(mNotificationManager).notify(anyInt(), any()); 624 625 mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK)); 626 627 // Connecting Notification 628 verify(mNotificationBuilder).createNetworkConnectingNotification(OPEN_NET_NOTIFIER_TAG, 629 mDummyNetwork); 630 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 631 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK); 632 verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, 633 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK, 634 ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK); 635 verify(mNotificationManager, times(2)).notify(anyInt(), any()); 636 637 mNotificationController.handleConnectionFailure(); 638 639 // Failed to Connect Notification 640 verify(mNotificationBuilder).createNetworkFailedNotification(OPEN_NET_NOTIFIER_TAG); 641 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 642 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT); 643 verify(mNotificationManager, times(3)).notify(anyInt(), any()); 644 } 645 646 /** 647 * When a {@link WifiManager#CONNECT_NETWORK_FAILED} is received from the connection callback 648 * of {@link WifiStateMachine#sendMessage(Message)}, a Failed to Connect notification should 649 * be posted. On tapping this notification, Wi-Fi Settings should be launched. 650 */ 651 @Test 652 public void connectionFailedCallback_postsFailedToConnectNotification() throws RemoteException { 653 mNotificationController.handleScanResults(mOpenNetworks); 654 655 // Initial Notification 656 verify(mNotificationBuilder).createConnectToAvailableNetworkNotification( 657 OPEN_NET_NOTIFIER_TAG, mDummyNetwork); 658 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 659 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 660 verify(mNotificationManager).notify(anyInt(), any()); 661 662 mBroadcastReceiver.onReceive(mContext, createIntent(ACTION_CONNECT_TO_NETWORK)); 663 664 ArgumentCaptor<Message> connectMessageCaptor = ArgumentCaptor.forClass(Message.class); 665 verify(mWifiStateMachine).sendMessage(connectMessageCaptor.capture()); 666 Message connectMessage = connectMessageCaptor.getValue(); 667 668 // Connecting Notification 669 verify(mNotificationBuilder).createNetworkConnectingNotification(OPEN_NET_NOTIFIER_TAG, 670 mDummyNetwork); 671 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 672 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK); 673 verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, 674 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK, 675 ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK); 676 verify(mNotificationManager, times(2)).notify(anyInt(), any()); 677 678 Message connectFailedMsg = Message.obtain(); 679 connectFailedMsg.what = WifiManager.CONNECT_NETWORK_FAILED; 680 connectMessage.replyTo.send(connectFailedMsg); 681 mLooper.dispatchAll(); 682 683 // Failed to Connect Notification 684 verify(mNotificationBuilder).createNetworkFailedNotification(OPEN_NET_NOTIFIER_TAG); 685 verify(mWifiMetrics).incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, 686 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT); 687 verify(mWifiMetrics).incrementNumNetworkConnectMessageFailedToSend(OPEN_NET_NOTIFIER_TAG); 688 verify(mNotificationManager, times(3)).notify(anyInt(), any()); 689 690 mBroadcastReceiver.onReceive(mContext, 691 createIntent(ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE)); 692 693 ArgumentCaptor<Intent> pickerIntentCaptor = ArgumentCaptor.forClass(Intent.class); 694 verify(mContext).startActivity(pickerIntentCaptor.capture()); 695 assertEquals(pickerIntentCaptor.getValue().getAction(), Settings.ACTION_WIFI_SETTINGS); 696 verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, 697 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT, 698 ConnectToNetworkNotificationAndActionCount 699 .ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE); 700 } 701 702 private List<ScanDetail> createOpenScanResults(String... ssids) { 703 List<ScanDetail> scanResults = new ArrayList<>(); 704 for (String ssid : ssids) { 705 ScanResult scanResult = new ScanResult(); 706 scanResult.SSID = ssid; 707 scanResult.capabilities = "[ESS]"; 708 scanResults.add(new ScanDetail(scanResult, null /* networkDetail */)); 709 } 710 return scanResults; 711 } 712 713 /** If list of open networks contain only one network, that network should be returned. */ 714 @Test 715 public void onlyNetworkIsRecommended() { 716 List<ScanDetail> scanResults = createOpenScanResults(TEST_SSID_1); 717 scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL; 718 719 ScanResult actual = mNotificationController.recommendNetwork( 720 scanResults, mBlacklistedSsids); 721 ScanResult expected = scanResults.get(0).getScanResult(); 722 assertEquals(expected, actual); 723 } 724 725 /** Verifies that the network with the highest rssi is recommended. */ 726 @Test 727 public void networkWithHighestRssiIsRecommended() { 728 List<ScanDetail> scanResults = createOpenScanResults(TEST_SSID_1, TEST_SSID_2); 729 scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL; 730 scanResults.get(1).getScanResult().level = MIN_RSSI_LEVEL + 1; 731 732 ScanResult actual = mNotificationController.recommendNetwork( 733 scanResults, mBlacklistedSsids); 734 ScanResult expected = scanResults.get(1).getScanResult(); 735 assertEquals(expected, actual); 736 } 737 738 /** 739 * If the best available open network is blacklisted, no network should be recommended. 740 */ 741 @Test 742 public void blacklistBestNetworkSsid_shouldNeverRecommendNetwork() { 743 List<ScanDetail> scanResults = createOpenScanResults(TEST_SSID_1, TEST_SSID_2); 744 scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL + 1; 745 scanResults.get(1).getScanResult().level = MIN_RSSI_LEVEL; 746 mBlacklistedSsids.add(TEST_SSID_1); 747 748 ScanResult actual = mNotificationController.recommendNetwork( 749 scanResults, mBlacklistedSsids); 750 assertNull(actual); 751 } 752 } 753