Home | History | Annotate | Download | only in wifi
      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