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
17package com.android.server.wifi;
18
19import static com.android.server.wifi.OpenNetworkNotifier.DEFAULT_REPEAT_DELAY_SEC;
20
21import static org.junit.Assert.assertEquals;
22import static org.mockito.ArgumentMatchers.any;
23import static org.mockito.ArgumentMatchers.eq;
24import static org.mockito.Mockito.anyInt;
25import static org.mockito.Mockito.never;
26import static org.mockito.Mockito.times;
27import static org.mockito.Mockito.verify;
28import static org.mockito.Mockito.when;
29
30import android.app.NotificationManager;
31import android.content.BroadcastReceiver;
32import android.content.Context;
33import android.content.Intent;
34import android.content.res.Resources;
35import android.database.ContentObserver;
36import android.net.Uri;
37import android.net.wifi.ScanResult;
38import android.net.wifi.WifiManager;
39import android.os.Message;
40import android.os.RemoteException;
41import android.os.UserHandle;
42import android.os.UserManager;
43import android.os.test.TestLooper;
44import android.provider.Settings;
45import android.util.ArraySet;
46
47import com.android.server.wifi.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount;
48
49import org.junit.Before;
50import org.junit.Test;
51import org.mockito.ArgumentCaptor;
52import org.mockito.Mock;
53import org.mockito.MockitoAnnotations;
54
55import java.util.ArrayList;
56import java.util.List;
57import java.util.Set;
58
59/**
60 * Unit tests for {@link OpenNetworkNotifier}.
61 */
62public class OpenNetworkNotifierTest {
63
64    private static final String TEST_SSID_1 = "Test SSID 1";
65    private static final String TEST_SSID_2 = "Test SSID 2";
66    private static final int MIN_RSSI_LEVEL = -127;
67
68    @Mock private Context mContext;
69    @Mock private Resources mResources;
70    @Mock private FrameworkFacade mFrameworkFacade;
71    @Mock private WifiMetrics mWifiMetrics;
72    @Mock private Clock mClock;
73    @Mock private WifiConfigStore mWifiConfigStore;
74    @Mock private WifiConfigManager mWifiConfigManager;
75    @Mock private NotificationManager mNotificationManager;
76    @Mock private WifiStateMachine mWifiStateMachine;
77    @Mock private OpenNetworkRecommender mOpenNetworkRecommender;
78    @Mock private ConnectToNetworkNotificationBuilder mNotificationBuilder;
79    @Mock private UserManager mUserManager;
80    private OpenNetworkNotifier mNotificationController;
81    private TestLooper mLooper;
82    private BroadcastReceiver mBroadcastReceiver;
83    private ContentObserver mContentObserver;
84    private ScanResult mDummyNetwork;
85    private List<ScanDetail> mOpenNetworks;
86    private Set<String> mBlacklistedSsids;
87
88
89    /** Initialize objects before each test run. */
90    @Before
91    public void setUp() throws Exception {
92        MockitoAnnotations.initMocks(this);
93        when(mContext.getSystemService(Context.NOTIFICATION_SERVICE))
94                .thenReturn(mNotificationManager);
95        when(mFrameworkFacade.getIntegerSetting(mContext,
96                Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1)).thenReturn(1);
97        when(mFrameworkFacade.getIntegerSetting(mContext,
98                Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, DEFAULT_REPEAT_DELAY_SEC))
99                .thenReturn(DEFAULT_REPEAT_DELAY_SEC);
100        when(mContext.getSystemService(Context.USER_SERVICE))
101                .thenReturn(mUserManager);
102        when(mContext.getResources()).thenReturn(mResources);
103        mDummyNetwork = new ScanResult();
104        mDummyNetwork.SSID = TEST_SSID_1;
105        mDummyNetwork.capabilities = "[ESS]";
106        mDummyNetwork.level = MIN_RSSI_LEVEL;
107        when(mOpenNetworkRecommender.recommendNetwork(any(), any())).thenReturn(mDummyNetwork);
108        mOpenNetworks = new ArrayList<>();
109        mOpenNetworks.add(new ScanDetail(mDummyNetwork, null /* networkDetail */));
110        mBlacklistedSsids = new ArraySet<>();
111
112        mLooper = new TestLooper();
113        mNotificationController = new OpenNetworkNotifier(
114                mContext, mLooper.getLooper(), mFrameworkFacade, mClock, mWifiMetrics,
115                mWifiConfigManager, mWifiConfigStore, mWifiStateMachine, mOpenNetworkRecommender,
116                mNotificationBuilder);
117        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
118                ArgumentCaptor.forClass(BroadcastReceiver.class);
119        verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
120        mBroadcastReceiver = broadcastReceiverCaptor.getValue();
121        ArgumentCaptor<ContentObserver> observerCaptor =
122                ArgumentCaptor.forClass(ContentObserver.class);
123        verify(mFrameworkFacade).registerContentObserver(eq(mContext), any(Uri.class), eq(true),
124                observerCaptor.capture());
125        mContentObserver = observerCaptor.getValue();
126        mNotificationController.handleScreenStateChanged(true);
127    }
128
129    /**
130     * On {@link OpenNetworkNotifier} construction, WifiMetrics should track setting state.
131     */
132    @Test
133    public void onCreate_setWifiNetworksAvailableNotificationSettingState() {
134        verify(mWifiMetrics).setIsWifiNetworksAvailableNotificationEnabled(true);
135    }
136
137    /**
138     * When feature setting is toggled, WifiMetrics should track the disabled setting state.
139     */
140    @Test
141    public void onFeatureDisable_setWifiNetworksAvailableNotificationSettingDisabled() {
142        when(mFrameworkFacade.getIntegerSetting(mContext,
143                Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1)).thenReturn(0);
144        mContentObserver.onChange(false);
145
146        verify(mWifiMetrics).setIsWifiNetworksAvailableNotificationEnabled(false);
147    }
148
149    /**
150     * When scan results with open networks are handled, a notification is posted.
151     */
152    @Test
153    public void handleScanResults_hasOpenNetworks_notificationDisplayed() {
154        mNotificationController.handleScanResults(mOpenNetworks);
155
156        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
157        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
158        verify(mWifiMetrics).incrementConnectToNetworkNotification(
159                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
160        verify(mNotificationManager).notify(anyInt(), any());
161    }
162
163    /**
164     * When scan results with no open networks are handled, a notification is not posted.
165     */
166    @Test
167    public void handleScanResults_emptyList_notificationNotDisplayed() {
168        mNotificationController.handleScanResults(new ArrayList<>());
169
170        verify(mOpenNetworkRecommender, never()).recommendNetwork(any(), any());
171        verify(mNotificationManager, never()).notify(anyInt(), any());
172    }
173
174    /**
175     * When the feature is disabled, no notifications are posted.
176     */
177    @Test
178    public void handleScanResults_featureDisabled_notificationNotDisplayed() {
179        when(mFrameworkFacade.getIntegerSetting(mContext,
180                Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1)).thenReturn(0);
181        mContentObserver.onChange(false);
182        mNotificationController.handleScanResults(new ArrayList<>());
183
184        verify(mOpenNetworkRecommender, never()).recommendNetwork(any(), any());
185        verify(mNotificationManager, never()).notify(anyInt(), any());
186    }
187
188    /**
189     * When a notification is showing and scan results with no open networks are handled, the
190     * notification is cleared.
191     */
192    @Test
193    public void handleScanResults_notificationShown_emptyList_notificationCleared() {
194        mNotificationController.handleScanResults(mOpenNetworks);
195
196        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
197        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
198        verify(mWifiMetrics).incrementConnectToNetworkNotification(
199                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
200        verify(mNotificationManager).notify(anyInt(), any());
201
202        mNotificationController.handleScanResults(new ArrayList<>());
203
204        verify(mNotificationManager).cancel(anyInt());
205    }
206
207    /**
208     * When a notification is showing and no recommendation is made for the new scan results, the
209     * notification is cleared.
210     */
211    @Test
212    public void handleScanResults_notificationShown_noRecommendation_notificationCleared() {
213        mNotificationController.handleScanResults(mOpenNetworks);
214
215        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
216        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
217        verify(mWifiMetrics).incrementConnectToNetworkNotification(
218                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
219        verify(mNotificationManager).notify(anyInt(), any());
220
221        when(mOpenNetworkRecommender.recommendNetwork(any(), any())).thenReturn(null);
222        mNotificationController.handleScanResults(mOpenNetworks);
223
224        verify(mNotificationManager).cancel(anyInt());
225    }
226
227    /**
228     * When a notification is showing, screen is off, and scan results with no open networks are
229     * handled, the notification is cleared.
230     */
231    @Test
232    public void handleScanResults_notificationShown_screenOff_emptyList_notificationCleared() {
233        mNotificationController.handleScanResults(mOpenNetworks);
234
235        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
236        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
237        verify(mWifiMetrics).incrementConnectToNetworkNotification(
238                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
239        verify(mNotificationManager).notify(anyInt(), any());
240
241        mNotificationController.handleScreenStateChanged(false);
242        mNotificationController.handleScanResults(new ArrayList<>());
243
244        verify(mNotificationManager).cancel(anyInt());
245    }
246
247    /**
248     * When {@link OpenNetworkNotifier#clearPendingNotification(boolean)} is called and a
249     * notification is shown, clear the notification.
250     */
251    @Test
252    public void clearPendingNotification_clearsNotificationIfOneIsShowing() {
253        mNotificationController.handleScanResults(mOpenNetworks);
254
255        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
256        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
257        verify(mWifiMetrics).incrementConnectToNetworkNotification(
258                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
259        verify(mNotificationManager).notify(anyInt(), any());
260
261        mNotificationController.clearPendingNotification(true);
262
263        verify(mNotificationManager).cancel(anyInt());
264    }
265
266    /**
267     * When {@link OpenNetworkNotifier#clearPendingNotification(boolean)} is called and a
268     * notification was not previously shown, do not clear the notification.
269     */
270    @Test
271    public void clearPendingNotification_doesNotClearNotificationIfNoneShowing() {
272        mNotificationController.clearPendingNotification(true);
273
274        verify(mNotificationManager, never()).cancel(anyInt());
275    }
276
277    /**
278     * When screen is off and notification is not displayed, notification is not posted on handling
279     * new scan results with open networks.
280     */
281    @Test
282    public void screenOff_notificationNotShowing_handleScanResults_notificationNotDisplayed() {
283        mNotificationController.handleScreenStateChanged(false);
284        mNotificationController.handleScanResults(mOpenNetworks);
285
286        verify(mOpenNetworkRecommender, never()).recommendNetwork(any(), any());
287        verify(mNotificationManager, never()).notify(anyInt(), any());
288    }
289
290    /**
291     * When screen is off and notification is displayed, the notification can be updated with a new
292     * recommendation.
293     */
294    @Test
295    public void screenOff_notificationShowing_handleScanResults_recommendationCanBeUpdated() {
296        mNotificationController.handleScanResults(mOpenNetworks);
297
298        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
299        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
300        verify(mWifiMetrics).incrementConnectToNetworkNotification(
301                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
302        verify(mNotificationManager).notify(anyInt(), any());
303
304        ScanResult newNetwork = new ScanResult();
305        newNetwork.SSID = TEST_SSID_2;
306        mDummyNetwork.capabilities = "[ESS]";
307        mDummyNetwork.level = MIN_RSSI_LEVEL;
308        mOpenNetworks.add(new ScanDetail(newNetwork, null /* networkDetail */));
309        when(mOpenNetworkRecommender.recommendNetwork(any(), any())).thenReturn(newNetwork);
310
311        mNotificationController.handleScreenStateChanged(false);
312        mNotificationController.handleScanResults(mOpenNetworks);
313
314        // Recommendation changed
315        verify(mOpenNetworkRecommender, times(2)).recommendNetwork(
316                mOpenNetworks, mBlacklistedSsids);
317        verify(mNotificationBuilder).createConnectToNetworkNotification(newNetwork);
318        verify(mWifiMetrics).incrementNumOpenNetworkRecommendationUpdates();
319        verify(mNotificationManager, times(2)).notify(anyInt(), any());
320    }
321
322    /**
323     * When a notification is posted and cleared without resetting delay, the next scan with open
324     * networks should not post another notification.
325     */
326    @Test
327    public void postNotification_clearNotificationWithoutDelayReset_shouldNotPostNotification() {
328        mNotificationController.handleScanResults(mOpenNetworks);
329
330        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
331        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
332        verify(mWifiMetrics).incrementConnectToNetworkNotification(
333                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
334        verify(mNotificationManager).notify(anyInt(), any());
335
336        mNotificationController.clearPendingNotification(false);
337
338        verify(mNotificationManager).cancel(anyInt());
339
340        mNotificationController.handleScanResults(mOpenNetworks);
341
342        // no new notification posted
343        verify(mNotificationManager).notify(anyInt(), any());
344    }
345
346    /**
347     * When a notification is posted and cleared without resetting delay, the next scan with open
348     * networks should post a notification.
349     */
350    @Test
351    public void postNotification_clearNotificationWithDelayReset_shouldPostNotification() {
352        mNotificationController.handleScanResults(mOpenNetworks);
353
354        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
355        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
356        verify(mWifiMetrics).incrementConnectToNetworkNotification(
357                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
358        verify(mNotificationManager).notify(anyInt(), any());
359
360        mNotificationController.clearPendingNotification(true);
361
362        mNotificationController.handleScanResults(mOpenNetworks);
363
364        verify(mOpenNetworkRecommender, times(2)).recommendNetwork(
365                mOpenNetworks, mBlacklistedSsids);
366        verify(mNotificationBuilder, times(2)).createConnectToNetworkNotification(mDummyNetwork);
367        verify(mWifiMetrics, times(2)).incrementConnectToNetworkNotification(
368                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
369        verify(mNotificationManager, times(2)).notify(anyInt(), any());
370    }
371
372    /**
373     * When user dismissed notification and there is a recommended network, network ssid should be
374     * blacklisted.
375     */
376    @Test
377    public void userDismissedNotification_shouldBlacklistNetwork() {
378        mNotificationController.handleScanResults(mOpenNetworks);
379
380        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
381        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
382        verify(mWifiMetrics).incrementConnectToNetworkNotification(
383                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
384        verify(mNotificationManager).notify(anyInt(), any());
385
386        mBroadcastReceiver.onReceive(
387                mContext,
388                new Intent(ConnectToNetworkNotificationBuilder.ACTION_USER_DISMISSED_NOTIFICATION));
389
390        verify(mWifiConfigManager).saveToStore(false /* forceWrite */);
391
392        mNotificationController.clearPendingNotification(true);
393        List<ScanDetail> scanResults = mOpenNetworks;
394        mNotificationController.handleScanResults(scanResults);
395
396        Set<String> expectedBlacklist = new ArraySet<>();
397        expectedBlacklist.add(mDummyNetwork.SSID);
398        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, expectedBlacklist);
399        verify(mWifiMetrics).setOpenNetworkRecommenderBlacklistSize(expectedBlacklist.size());
400    }
401
402    /**
403     * When a notification is posted and cleared without resetting delay, after the delay has passed
404     * the next scan with open networks should post a notification.
405     */
406    @Test
407    public void delaySet_delayPassed_shouldPostNotification() {
408        mNotificationController.handleScanResults(mOpenNetworks);
409
410        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
411        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
412        verify(mWifiMetrics).incrementConnectToNetworkNotification(
413                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
414        verify(mNotificationManager).notify(anyInt(), any());
415
416        mNotificationController.clearPendingNotification(false);
417
418        // twice the delay time passed
419        when(mClock.getWallClockMillis()).thenReturn(DEFAULT_REPEAT_DELAY_SEC * 1000L * 2);
420
421        mNotificationController.handleScanResults(mOpenNetworks);
422
423        verify(mOpenNetworkRecommender, times(2)).recommendNetwork(
424                mOpenNetworks, mBlacklistedSsids);
425        verify(mNotificationBuilder, times(2)).createConnectToNetworkNotification(mDummyNetwork);
426        verify(mWifiMetrics, times(2)).incrementConnectToNetworkNotification(
427                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
428        verify(mNotificationManager, times(2)).notify(anyInt(), any());
429    }
430
431    /** Verifies that {@link UserManager#DISALLOW_CONFIG_WIFI} disables the feature. */
432    @Test
433    public void userHasDisallowConfigWifiRestriction_notificationNotDisplayed() {
434        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT))
435                .thenReturn(true);
436
437        mNotificationController.handleScanResults(mOpenNetworks);
438
439        verify(mOpenNetworkRecommender, never()).recommendNetwork(any(), any());
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(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
449        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
450        verify(mWifiMetrics).incrementConnectToNetworkNotification(
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,
469                new Intent(ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK));
470
471        verify(mWifiStateMachine, never()).sendMessage(any(Message.class));
472    }
473
474    /**
475     * {@link ConnectToNetworkNotificationBuilder#ACTION_CONNECT_TO_NETWORK} connects to the
476     * currently recommended network if it exists.
477     */
478    @Test
479    public void actionConnectToNetwork_currentRecommendationExists_connectsAndPostsNotification() {
480        mNotificationController.handleScanResults(mOpenNetworks);
481
482        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
483        // Initial Notification
484        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
485        verify(mWifiMetrics).incrementConnectToNetworkNotification(
486                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
487        verify(mNotificationManager).notify(anyInt(), any());
488
489        mBroadcastReceiver.onReceive(mContext,
490                new Intent(ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK));
491
492        verify(mWifiStateMachine).sendMessage(any(Message.class));
493        // Connecting Notification
494        verify(mNotificationBuilder).createNetworkConnectingNotification(mDummyNetwork);
495        verify(mWifiMetrics).incrementConnectToNetworkNotification(
496                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK);
497        verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(
498                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK,
499                ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK);
500        verify(mNotificationManager, times(2)).notify(anyInt(), any());
501    }
502
503    /**
504     * {@link ConnectToNetworkNotificationBuilder#ACTION_PICK_WIFI_NETWORK} opens Wi-Fi settings
505     * if the recommendation notification is showing.
506     */
507    @Test
508    public void actionPickWifiNetwork_currentRecommendationExists_opensWifiSettings() {
509        mNotificationController.handleScanResults(mOpenNetworks);
510
511        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
512        // Initial Notification
513        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
514        verify(mWifiMetrics).incrementConnectToNetworkNotification(
515                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
516        verify(mNotificationManager).notify(anyInt(), any());
517
518        mBroadcastReceiver.onReceive(mContext,
519                new Intent(ConnectToNetworkNotificationBuilder.ACTION_PICK_WIFI_NETWORK));
520
521        ArgumentCaptor<Intent> pickerIntentCaptor = ArgumentCaptor.forClass(Intent.class);
522        verify(mContext).startActivity(pickerIntentCaptor.capture());
523        assertEquals(pickerIntentCaptor.getValue().getAction(), Settings.ACTION_WIFI_SETTINGS);
524        verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(
525                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK,
526                ConnectToNetworkNotificationAndActionCount.ACTION_PICK_WIFI_NETWORK);
527    }
528
529    /**
530     * {@link OpenNetworkNotifier#handleWifiConnected()} does not post connected notification if
531     * the connecting notification is not showing
532     */
533    @Test
534    public void networkConnectionSuccess_wasNotInConnectingFlow_doesNothing() {
535        mNotificationController.handleWifiConnected();
536
537        verify(mNotificationManager, never()).notify(anyInt(), any());
538        verify(mWifiMetrics, never()).incrementConnectToNetworkNotification(
539                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTED_TO_NETWORK);
540    }
541
542    /**
543     * {@link OpenNetworkNotifier#handleWifiConnected()} clears notification that is not connecting.
544     */
545    @Test
546    public void networkConnectionSuccess_wasShowingNotification_clearsNotification() {
547        mNotificationController.handleScanResults(mOpenNetworks);
548
549        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
550        // Initial Notification
551        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
552        verify(mWifiMetrics).incrementConnectToNetworkNotification(
553                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
554        verify(mNotificationManager).notify(anyInt(), any());
555
556        mNotificationController.handleWifiConnected();
557
558        verify(mNotificationManager).cancel(anyInt());
559    }
560
561    /**
562     * {@link OpenNetworkNotifier#handleWifiConnected()} posts the connected notification if
563     * the connecting notification is showing.
564     */
565    @Test
566    public void networkConnectionSuccess_wasInConnectingFlow_postsConnectedNotification() {
567        mNotificationController.handleScanResults(mOpenNetworks);
568
569        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
570        // Initial Notification
571        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
572        verify(mWifiMetrics).incrementConnectToNetworkNotification(
573                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
574        verify(mNotificationManager).notify(anyInt(), any());
575
576        mBroadcastReceiver.onReceive(mContext,
577                new Intent(ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK));
578
579        // Connecting Notification
580        verify(mNotificationBuilder).createNetworkConnectingNotification(mDummyNetwork);
581        verify(mWifiMetrics).incrementConnectToNetworkNotification(
582                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK);
583        verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(
584                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK,
585                ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK);
586        verify(mNotificationManager, times(2)).notify(anyInt(), any());
587
588        mNotificationController.handleWifiConnected();
589
590        // Connected Notification
591        verify(mNotificationBuilder).createNetworkConnectedNotification(mDummyNetwork);
592        verify(mWifiMetrics).incrementConnectToNetworkNotification(
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(
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        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
619        // Initial Notification
620        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
621        verify(mWifiMetrics).incrementConnectToNetworkNotification(
622                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
623        verify(mNotificationManager).notify(anyInt(), any());
624
625        mBroadcastReceiver.onReceive(mContext,
626                new Intent(ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK));
627
628        // Connecting Notification
629        verify(mNotificationBuilder).createNetworkConnectingNotification(mDummyNetwork);
630        verify(mWifiMetrics).incrementConnectToNetworkNotification(
631                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK);
632        verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(
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();
641        verify(mWifiMetrics).incrementConnectToNetworkNotification(
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        verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
656        // Initial Notification
657        verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
658        verify(mWifiMetrics).incrementConnectToNetworkNotification(
659                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK);
660        verify(mNotificationManager).notify(anyInt(), any());
661
662        mBroadcastReceiver.onReceive(mContext,
663                new Intent(ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK));
664
665        ArgumentCaptor<Message> connectMessageCaptor = ArgumentCaptor.forClass(Message.class);
666        verify(mWifiStateMachine).sendMessage(connectMessageCaptor.capture());
667        Message connectMessage = connectMessageCaptor.getValue();
668
669        // Connecting Notification
670        verify(mNotificationBuilder).createNetworkConnectingNotification(mDummyNetwork);
671        verify(mWifiMetrics).incrementConnectToNetworkNotification(
672                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK);
673        verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(
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();
685        verify(mWifiMetrics).incrementConnectToNetworkNotification(
686                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT);
687        verify(mWifiMetrics).incrementNumOpenNetworkConnectMessageFailedToSend();
688        verify(mNotificationManager, times(3)).notify(anyInt(), any());
689
690        mBroadcastReceiver.onReceive(mContext,
691                new Intent(ConnectToNetworkNotificationBuilder
692                        .ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE));
693
694        ArgumentCaptor<Intent> pickerIntentCaptor = ArgumentCaptor.forClass(Intent.class);
695        verify(mContext).startActivity(pickerIntentCaptor.capture());
696        assertEquals(pickerIntentCaptor.getValue().getAction(), Settings.ACTION_WIFI_SETTINGS);
697        verify(mWifiMetrics).incrementConnectToNetworkNotificationAction(
698                ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT,
699                ConnectToNetworkNotificationAndActionCount
700                        .ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE);
701    }
702}
703