AccessPointTest.java revision a78256947d190a84169a31340c086cfacfcf0697
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 */
16package com.android.settingslib.wifi;
17
18import static com.google.common.truth.Truth.assertThat;
19import static com.google.common.truth.Truth.assertWithMessage;
20
21import static org.mockito.Mockito.any;
22import static org.mockito.Mockito.anyInt;
23import static org.mockito.Mockito.mock;
24import static org.mockito.Mockito.verify;
25import static org.mockito.Mockito.when;
26
27import android.content.Context;
28import android.net.ConnectivityManager;
29import android.net.NetworkInfo;
30import android.net.NetworkKey;
31import android.net.RssiCurve;
32import android.net.ScoredNetwork;
33import android.net.WifiKey;
34import android.net.wifi.ScanResult;
35import android.net.wifi.WifiConfiguration;
36import android.net.wifi.WifiEnterpriseConfig;
37import android.net.wifi.WifiInfo;
38import android.net.wifi.WifiNetworkScoreCache;
39import android.net.wifi.WifiSsid;
40import android.net.wifi.hotspot2.PasspointConfiguration;
41import android.net.wifi.hotspot2.pps.HomeSp;
42import android.os.Bundle;
43import android.os.SystemClock;
44import android.support.test.InstrumentationRegistry;
45import android.support.test.filters.SmallTest;
46import android.support.test.runner.AndroidJUnit4;
47import android.text.SpannableString;
48import android.text.style.TtsSpan;
49
50import com.android.settingslib.R;
51import com.android.settingslib.wifi.AccessPoint.Speed;
52
53import org.junit.Before;
54import org.junit.Test;
55import org.junit.runner.RunWith;
56import org.mockito.Mock;
57import org.mockito.MockitoAnnotations;
58
59import java.util.ArrayList;
60import java.util.Arrays;
61import java.util.Collections;
62
63@SmallTest
64@RunWith(AndroidJUnit4.class)
65public class AccessPointTest {
66
67    private static final String TEST_SSID = "\"test_ssid\"";
68    private static final int NUM_SCAN_RESULTS = 5;
69
70    private static final ArrayList<ScanResult> SCAN_RESULTS = buildScanResultCache();
71
72    private static final RssiCurve FAST_BADGE_CURVE =
73            new RssiCurve(-150, 10, new byte[]{Speed.FAST});
74    public static final String TEST_BSSID = "00:00:00:00:00:00";
75
76    private Context mContext;
77    @Mock private RssiCurve mockBadgeCurve;
78    @Mock private WifiNetworkScoreCache mockWifiNetworkScoreCache;
79
80    private static ScanResult createScanResult(String ssid, String bssid, int rssi) {
81        ScanResult scanResult = new ScanResult();
82        scanResult.SSID = ssid;
83        scanResult.level = rssi;
84        scanResult.BSSID = bssid;
85        scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
86        scanResult.capabilities = "";
87        return scanResult;
88    }
89
90    @Before
91    public void setUp() {
92        MockitoAnnotations.initMocks(this);
93        mContext = InstrumentationRegistry.getTargetContext();
94        WifiTracker.sVerboseLogging = false;
95    }
96
97    @Test
98    public void testSsidIsTelephoneSpan() {
99        final Bundle bundle = new Bundle();
100        bundle.putString("key_ssid", TEST_SSID);
101        final AccessPoint ap = new AccessPoint(InstrumentationRegistry.getTargetContext(), bundle);
102        final CharSequence ssid = ap.getSsid();
103
104        assertThat(ssid instanceof SpannableString).isTrue();
105
106        TtsSpan[] spans = ((SpannableString) ssid).getSpans(0, TEST_SSID.length(), TtsSpan.class);
107
108        assertThat(spans.length).isEqualTo(1);
109        assertThat(spans[0].getType()).isEqualTo(TtsSpan.TYPE_TELEPHONE);
110    }
111
112    @Test
113    public void testCopyAccessPoint_dataShouldMatch() {
114        WifiConfiguration configuration = createWifiConfiguration();
115        configuration.meteredHint = true;
116
117        NetworkInfo networkInfo =
118                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE");
119        AccessPoint originalAccessPoint = new AccessPoint(mContext, configuration);
120        WifiInfo wifiInfo = new WifiInfo();
121        wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID));
122        wifiInfo.setBSSID(configuration.BSSID);
123        originalAccessPoint.update(configuration, wifiInfo, networkInfo);
124        AccessPoint copy = new AccessPoint(mContext, originalAccessPoint);
125
126        assertThat(originalAccessPoint.getSsid().toString()).isEqualTo(copy.getSsid().toString());
127        assertThat(originalAccessPoint.getBssid()).isEqualTo(copy.getBssid());
128        assertThat(originalAccessPoint.getConfig()).isEqualTo(copy.getConfig());
129        assertThat(originalAccessPoint.getSecurity()).isEqualTo(copy.getSecurity());
130        assertThat(originalAccessPoint.isMetered()).isEqualTo(copy.isMetered());
131        assertThat(originalAccessPoint.compareTo(copy) == 0).isTrue();
132    }
133
134    @Test
135    public void testThatCopyAccessPoint_scanCacheShouldMatch() {
136        AccessPoint original = createAccessPointWithScanResultCache();
137        assertThat(original.getRssi()).isEqualTo(4);
138        AccessPoint copy = new AccessPoint(mContext, createWifiConfiguration());
139        assertThat(copy.getRssi()).isEqualTo(AccessPoint.UNREACHABLE_RSSI);
140        copy.copyFrom(original);
141        assertThat(original.getRssi()).isEqualTo(copy.getRssi());
142    }
143
144    @Test
145    public void testCompareTo_GivesActiveBeforeInactive() {
146        AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build();
147        AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build();
148
149        assertSortingWorks(activeAp, inactiveAp);
150    }
151
152    @Test
153    public void testCompareTo_GivesReachableBeforeUnreachable() {
154        AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build();
155        AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build();
156
157        assertSortingWorks(nearAp, farAp);
158    }
159
160    @Test
161    public void testCompareTo_GivesSavedBeforeUnsaved() {
162        AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build();
163        AccessPoint notSavedAp = new TestAccessPointBuilder(mContext).setSaved(false).build();
164
165        assertSortingWorks(savedAp, notSavedAp);
166    }
167
168    @Test
169    public void testCompareTo_GivesHighSpeedBeforeLowSpeed() {
170        AccessPoint fastAp = new TestAccessPointBuilder(mContext).setSpeed(Speed.FAST).build();
171        AccessPoint slowAp = new TestAccessPointBuilder(mContext).setSpeed(Speed.SLOW).build();
172
173        assertSortingWorks(fastAp, slowAp);
174    }
175
176    @Test
177    public void testCompareTo_GivesHighLevelBeforeLowLevel() {
178        final int highLevel = AccessPoint.SIGNAL_LEVELS - 1;
179        final int lowLevel = 1;
180        assertThat(highLevel).isGreaterThan(lowLevel);
181
182        AccessPoint strongAp = new TestAccessPointBuilder(mContext).setLevel(highLevel).build();
183        AccessPoint weakAp = new TestAccessPointBuilder(mContext).setLevel(lowLevel).build();
184
185        assertSortingWorks(strongAp, weakAp);
186    }
187
188    @Test
189    public void testCompareTo_GivesSsidAlphabetically() {
190
191        final String firstName = "AAAAAA";
192        final String secondName = "zzzzzz";
193
194        AccessPoint firstAp = new TestAccessPointBuilder(mContext).setSsid(firstName).build();
195        AccessPoint secondAp = new TestAccessPointBuilder(mContext).setSsid(secondName).build();
196
197        assertThat(firstAp.getSsidStr().compareToIgnoreCase(secondAp.getSsidStr()) < 0).isTrue();
198        assertSortingWorks(firstAp, secondAp);
199    }
200
201    @Test
202    public void testCompareTo_GivesSsidCasePrecendenceAfterAlphabetical() {
203
204        final String firstName = "aaAaaa";
205        final String secondName = "aaaaaa";
206        final String thirdName = "BBBBBB";
207
208        AccessPoint firstAp = new TestAccessPointBuilder(mContext).setSsid(firstName).build();
209        AccessPoint secondAp = new TestAccessPointBuilder(mContext).setSsid(secondName).build();
210        AccessPoint thirdAp = new TestAccessPointBuilder(mContext).setSsid(thirdName).build();
211
212        assertSortingWorks(firstAp, secondAp);
213        assertSortingWorks(secondAp, thirdAp);
214    }
215
216    @Test
217    public void testCompareTo_AllSortingRulesCombined() {
218
219        AccessPoint active = new TestAccessPointBuilder(mContext).setActive(true).build();
220        AccessPoint reachableAndMinLevel = new TestAccessPointBuilder(mContext)
221                .setReachable(true).build();
222        AccessPoint saved = new TestAccessPointBuilder(mContext).setSaved(true).build();
223        AccessPoint highLevelAndReachable = new TestAccessPointBuilder(mContext)
224                .setLevel(AccessPoint.SIGNAL_LEVELS - 1).build();
225        AccessPoint firstName = new TestAccessPointBuilder(mContext).setSsid("a").build();
226        AccessPoint lastname = new TestAccessPointBuilder(mContext).setSsid("z").build();
227
228        ArrayList<AccessPoint> points = new ArrayList<AccessPoint>();
229        points.add(lastname);
230        points.add(firstName);
231        points.add(highLevelAndReachable);
232        points.add(saved);
233        points.add(reachableAndMinLevel);
234        points.add(active);
235
236        Collections.sort(points);
237        assertThat(points.indexOf(active)).isLessThan(points.indexOf(reachableAndMinLevel));
238        assertThat(points.indexOf(reachableAndMinLevel)).isLessThan(points.indexOf(saved));
239        // note: the saved AP will not appear before highLevelAndReachable,
240        // because all APs with a signal level are reachable,
241        // and isReachable() takes higher sorting precedence than isSaved().
242        assertThat(points.indexOf(saved)).isLessThan(points.indexOf(firstName));
243        assertThat(points.indexOf(highLevelAndReachable)).isLessThan(points.indexOf(firstName));
244        assertThat(points.indexOf(firstName)).isLessThan(points.indexOf(lastname));
245    }
246
247    @Test
248    public void testRssiIsSetFromScanResults() {
249        AccessPoint ap = createAccessPointWithScanResultCache();
250        int originalRssi = ap.getRssi();
251        assertThat(originalRssi).isNotEqualTo(AccessPoint.UNREACHABLE_RSSI);
252    }
253
254    @Test
255    public void testGetRssiShouldReturnSetRssiValue() {
256        AccessPoint ap = createAccessPointWithScanResultCache();
257        int originalRssi = ap.getRssi();
258        int newRssi = originalRssi - 10;
259        ap.setRssi(newRssi);
260        assertThat(ap.getRssi()).isEqualTo(newRssi);
261    }
262
263    @Test
264    public void testUpdateWithScanResultShouldAverageRssi() {
265        String ssid = "ssid";
266        int originalRssi = -65;
267        int newRssi = -80;
268        int expectedRssi = (originalRssi + newRssi) / 2;
269        AccessPoint ap =
270                new TestAccessPointBuilder(mContext).setSsid(ssid).setRssi(originalRssi).build();
271
272        ScanResult scanResult = new ScanResult();
273        scanResult.SSID = ssid;
274        scanResult.level = newRssi;
275        scanResult.BSSID = "bssid";
276        scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
277        scanResult.capabilities = "";
278        assertThat(ap.update(scanResult, true /* evict old scan results */)).isTrue();
279
280        assertThat(ap.getRssi()).isEqualTo(expectedRssi);
281    }
282
283    @Test
284    public void testCreateFromPasspointConfig() {
285        PasspointConfiguration config = new PasspointConfiguration();
286        HomeSp homeSp = new HomeSp();
287        homeSp.setFqdn("test.com");
288        homeSp.setFriendlyName("Test Provider");
289        config.setHomeSp(homeSp);
290        AccessPoint ap = new AccessPoint(mContext, config);
291        assertThat(ap.isPasspointConfig()).isTrue();
292    }
293
294    @Test
295    public void testIsMetered_returnTrueWhenWifiConfigurationIsMetered() {
296        WifiConfiguration configuration = createWifiConfiguration();
297        configuration.meteredHint = true;
298
299        NetworkInfo networkInfo =
300                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE");
301        AccessPoint accessPoint = new AccessPoint(mContext, configuration);
302        WifiInfo wifiInfo = new WifiInfo();
303        wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID));
304        wifiInfo.setBSSID(configuration.BSSID);
305        wifiInfo.setNetworkId(configuration.networkId);
306        accessPoint.update(configuration, wifiInfo, networkInfo);
307
308        assertThat(accessPoint.isMetered()).isTrue();
309    }
310
311    @Test
312    public void testIsMetered_returnTrueWhenWifiInfoIsMetered() {
313        WifiConfiguration configuration = createWifiConfiguration();
314
315        NetworkInfo networkInfo =
316                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE");
317        AccessPoint accessPoint = new AccessPoint(mContext, configuration);
318        WifiInfo wifiInfo = new WifiInfo();
319        wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID));
320        wifiInfo.setBSSID(configuration.BSSID);
321        wifiInfo.setNetworkId(configuration.networkId);
322        wifiInfo.setMeteredHint(true);
323        accessPoint.update(configuration, wifiInfo, networkInfo);
324
325        assertThat(accessPoint.isMetered()).isTrue();
326    }
327
328    @Test
329    public void testIsMetered_returnTrueWhenScoredNetworkIsMetered() {
330        AccessPoint ap = createAccessPointWithScanResultCache();
331
332        when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
333                .thenReturn(
334                        new ScoredNetwork(
335                                null /* NetworkKey */,
336                                null /* rssiCurve */,
337                                true /* metered */));
338        ap.update(mockWifiNetworkScoreCache, false /* scoringUiEnabled */);
339
340        assertThat(ap.isMetered()).isTrue();
341    }
342
343    @Test
344    public void testIsMetered_returnFalseByDefault() {
345        WifiConfiguration configuration = createWifiConfiguration();
346
347        NetworkInfo networkInfo =
348                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE");
349        AccessPoint accessPoint = new AccessPoint(mContext, configuration);
350        WifiInfo wifiInfo = new WifiInfo();
351        wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID));
352        wifiInfo.setBSSID(configuration.BSSID);
353        wifiInfo.setNetworkId(configuration.networkId);
354        accessPoint.update(configuration, wifiInfo, networkInfo);
355
356        assertThat(accessPoint.isMetered()).isFalse();
357    }
358
359    @Test
360    public void testSpeedLabel_returnsVeryFast() {
361        AccessPoint ap = createAccessPointWithScanResultCache();
362
363        when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
364                .thenReturn(buildScoredNetworkWithMockBadgeCurve());
365        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.VERY_FAST);
366
367        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
368
369        assertThat(ap.getSpeed()).isEqualTo(AccessPoint.Speed.VERY_FAST);
370        assertThat(ap.getSpeedLabel())
371                .isEqualTo(mContext.getString(R.string.speed_label_very_fast));
372    }
373
374    @Test
375    public void testSpeedLabel_returnsFast() {
376        AccessPoint ap = createAccessPointWithScanResultCache();
377
378        when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
379                .thenReturn(buildScoredNetworkWithMockBadgeCurve());
380        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.FAST);
381
382        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
383
384        assertThat(ap.getSpeed()).isEqualTo(AccessPoint.Speed.FAST);
385        assertThat(ap.getSpeedLabel())
386                .isEqualTo(mContext.getString(R.string.speed_label_fast));
387    }
388
389    @Test
390    public void testSpeedLabel_returnsOkay() {
391        AccessPoint ap = createAccessPointWithScanResultCache();
392
393        when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
394                .thenReturn(buildScoredNetworkWithMockBadgeCurve());
395        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.MODERATE);
396
397        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
398
399        assertThat(ap.getSpeed()).isEqualTo(AccessPoint.Speed.MODERATE);
400        assertThat(ap.getSpeedLabel())
401                .isEqualTo(mContext.getString(R.string.speed_label_okay));
402    }
403
404    @Test
405    public void testSpeedLabel_returnsSlow() {
406        AccessPoint ap = createAccessPointWithScanResultCache();
407
408        when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
409                .thenReturn(buildScoredNetworkWithMockBadgeCurve());
410        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.SLOW);
411
412        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
413
414        assertThat(ap.getSpeed()).isEqualTo(AccessPoint.Speed.SLOW);
415        assertThat(ap.getSpeedLabel())
416                .isEqualTo(mContext.getString(R.string.speed_label_slow));
417    }
418
419    @Test
420    public void testSummaryString_showsSpeedLabel() {
421        AccessPoint ap = createAccessPointWithScanResultCache();
422
423        when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
424                .thenReturn(buildScoredNetworkWithMockBadgeCurve());
425        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.VERY_FAST);
426
427        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
428
429        assertThat(ap.getSummary()).isEqualTo(mContext.getString(R.string.speed_label_very_fast));
430    }
431
432    @Test
433    public void testVerboseSummaryString_showsScanResultSpeedLabel() {
434        WifiTracker.sVerboseLogging = true;
435
436        Bundle bundle = new Bundle();
437        ArrayList<ScanResult> scanResults = buildScanResultCache();
438        bundle.putParcelableArrayList(AccessPoint.KEY_SCANRESULTCACHE, scanResults);
439        AccessPoint ap = new AccessPoint(mContext, bundle);
440
441        when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
442                .thenReturn(buildScoredNetworkWithMockBadgeCurve());
443        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.VERY_FAST);
444
445        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
446        String summary = ap.verboseScanResultSummary(scanResults.get(0), null);
447
448        assertThat(summary.contains(mContext.getString(R.string.speed_label_very_fast))).isTrue();
449    }
450
451    @Test
452    public void testSummaryString_concatenatesSpeedLabel() {
453        AccessPoint ap = createAccessPointWithScanResultCache();
454        ap.update(new WifiConfiguration());
455
456        when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
457                .thenReturn(buildScoredNetworkWithMockBadgeCurve());
458        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.VERY_FAST);
459
460        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
461
462        String expectedString = mContext.getString(R.string.speed_label_very_fast) + " / "
463                + mContext.getString(R.string.wifi_remembered);
464        assertThat(ap.getSummary()).isEqualTo(expectedString);
465    }
466
467    @Test
468    public void testSummaryString_showsWrongPasswordLabel() {
469        WifiConfiguration configuration = createWifiConfiguration();
470        configuration.getNetworkSelectionStatus().setNetworkSelectionStatus(
471                WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED);
472        configuration.getNetworkSelectionStatus().setNetworkSelectionDisableReason(
473                WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD);
474        AccessPoint ap = new AccessPoint(mContext, configuration);
475
476        assertThat(ap.getSummary()).isEqualTo(mContext.getString(
477                R.string.wifi_check_password_try_again));
478    }
479
480    @Test
481    public void testSummaryString_showsAvaiableViaCarrier() {
482        String carrierName = "Test Carrier";
483        ScanResult result = new ScanResult();
484        result.BSSID = "00:11:22:33:44:55";
485        result.capabilities = "EAP";
486        result.isCarrierAp = true;
487        result.carrierApEapType = WifiEnterpriseConfig.Eap.SIM;
488        result.carrierName = carrierName;
489
490        AccessPoint ap = new AccessPoint(mContext, result);
491        assertThat(ap.getSummary()).isEqualTo(String.format(mContext.getString(
492                R.string.available_via_carrier), carrierName));
493        assertThat(ap.isCarrierAp()).isEqualTo(true);
494        assertThat(ap.getCarrierApEapType()).isEqualTo(WifiEnterpriseConfig.Eap.SIM);
495        assertThat(ap.getCarrierName()).isEqualTo(carrierName);
496    }
497
498    @Test
499    public void testSummaryString_showsConnectedViaCarrier() {
500        int networkId = 123;
501        int rssi = -55;
502        String carrierName = "Test Carrier";
503        WifiConfiguration config = new WifiConfiguration();
504        config.networkId = networkId;
505        WifiInfo wifiInfo = new WifiInfo();
506        wifiInfo.setNetworkId(networkId);
507        wifiInfo.setRssi(rssi);
508
509        NetworkInfo networkInfo =
510                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
511        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
512
513        AccessPoint ap = new TestAccessPointBuilder(mContext)
514                .setNetworkInfo(networkInfo)
515                .setNetworkId(networkId)
516                .setRssi(rssi)
517                .setWifiInfo(wifiInfo)
518                .setIsCarrierAp(true)
519                .setCarrierName(carrierName)
520                .build();
521        assertThat(ap.getSummary()).isEqualTo(String.format(mContext.getString(
522                R.string.connected_via_carrier), carrierName));
523    }
524
525    @Test
526    public void testUpdateScanResultWithCarrierInfo() {
527        String ssid = "ssid";
528        AccessPoint ap = new TestAccessPointBuilder(mContext).setSsid(ssid).build();
529        assertThat(ap.isCarrierAp()).isEqualTo(false);
530        assertThat(ap.getCarrierApEapType()).isEqualTo(WifiEnterpriseConfig.Eap.NONE);
531        assertThat(ap.getCarrierName()).isEqualTo(null);
532
533        int carrierApEapType = WifiEnterpriseConfig.Eap.SIM;
534        String carrierName = "Test Carrier";
535        ScanResult scanResult = new ScanResult();
536        scanResult.SSID = ssid;
537        scanResult.BSSID = "00:11:22:33:44:55";
538        scanResult.capabilities = "";
539        scanResult.isCarrierAp = true;
540        scanResult.carrierApEapType = carrierApEapType;
541        scanResult.carrierName = carrierName;
542        assertThat(ap.update(scanResult, true /* evictOldScanresults */)).isTrue();
543
544        assertThat(ap.isCarrierAp()).isEqualTo(true);
545        assertThat(ap.getCarrierApEapType()).isEqualTo(carrierApEapType);
546        assertThat(ap.getCarrierName()).isEqualTo(carrierName);
547    }
548
549    private ScoredNetwork buildScoredNetworkWithMockBadgeCurve() {
550        return buildScoredNetworkWithGivenBadgeCurve(mockBadgeCurve);
551
552    }
553
554    private ScoredNetwork buildScoredNetworkWithGivenBadgeCurve(RssiCurve badgeCurve) {
555        Bundle attr1 = new Bundle();
556        attr1.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, badgeCurve);
557        return new ScoredNetwork(
558                new NetworkKey(new WifiKey(TEST_SSID, TEST_BSSID)),
559                badgeCurve,
560                false /* meteredHint */,
561                attr1);
562
563    }
564
565    private AccessPoint createAccessPointWithScanResultCache() {
566        Bundle bundle = new Bundle();
567        bundle.putParcelableArrayList(AccessPoint.KEY_SCANRESULTCACHE, SCAN_RESULTS);
568        return new AccessPoint(mContext, bundle);
569    }
570
571    private static ArrayList<ScanResult> buildScanResultCache() {
572        ArrayList<ScanResult> scanResults = new ArrayList<>();
573        for (int i = 0; i < 5; i++) {
574            ScanResult scanResult = createScanResult(TEST_SSID, "bssid-" + i, i);
575            scanResults.add(scanResult);
576        }
577        return scanResults;
578    }
579
580    private WifiConfiguration createWifiConfiguration() {
581        WifiConfiguration configuration = new WifiConfiguration();
582        configuration.BSSID = "bssid";
583        configuration.SSID = "ssid";
584        configuration.networkId = 123;
585        return configuration;
586    }
587
588    private AccessPoint createApWithFastTimestampedScoredNetworkCache(
589            long elapsedTimeMillis) {
590        TimestampedScoredNetwork recentScore = new TimestampedScoredNetwork(
591                buildScoredNetworkWithGivenBadgeCurve(FAST_BADGE_CURVE),
592                elapsedTimeMillis);
593        return new TestAccessPointBuilder(mContext)
594                .setSsid(TEST_SSID)
595                .setScoredNetworkCache(
596                        new ArrayList<>(Arrays.asList(recentScore)))
597                .build();
598    }
599
600    /**
601    * Assert that the first AccessPoint appears before the second AccessPoint
602    * once sorting has been completed.
603    */
604    private void assertSortingWorks(AccessPoint first, AccessPoint second) {
605
606        ArrayList<AccessPoint> points = new ArrayList<AccessPoint>();
607
608        // add in reverse order so we can tell that sorting actually changed something
609        points.add(second);
610        points.add(first);
611        Collections.sort(points);
612        assertWithMessage(
613                String.format("After sorting: second AccessPoint should have higher array index "
614                    + "than the first, but found indicies second '%s' and first '%s'.",
615                    points.indexOf(second), points.indexOf(first)))
616            .that(points.indexOf(second)).isGreaterThan(points.indexOf(first));
617    }
618
619    @Test
620    public void testBuilder_setActive() {
621        AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build();
622        assertThat(activeAp.isActive()).isTrue();
623
624        AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build();
625        assertThat(inactiveAp.isActive()).isFalse();
626    }
627
628    @Test
629    public void testBuilder_setReachable() {
630        AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build();
631        assertThat(nearAp.isReachable()).isTrue();
632
633        AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build();
634        assertThat(farAp.isReachable()).isFalse();
635    }
636
637    @Test
638    public void testBuilder_setSaved() {
639        AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build();
640        assertThat(savedAp.isSaved()).isTrue();
641
642        AccessPoint newAp = new TestAccessPointBuilder(mContext).setSaved(false).build();
643        assertThat(newAp.isSaved()).isFalse();
644    }
645
646    @Test
647    public void testBuilder_setLevel() {
648        AccessPoint testAp;
649
650        for (int i = 0; i < AccessPoint.SIGNAL_LEVELS; i++) {
651            testAp = new TestAccessPointBuilder(mContext).setLevel(i).build();
652            assertThat(testAp.getLevel()).isEqualTo(i);
653        }
654
655        // numbers larger than the max level should be set to max
656        testAp = new TestAccessPointBuilder(mContext).setLevel(AccessPoint.SIGNAL_LEVELS).build();
657        assertThat(testAp.getLevel()).isEqualTo(AccessPoint.SIGNAL_LEVELS - 1);
658
659        // numbers less than 0 should give level 0
660        testAp = new TestAccessPointBuilder(mContext).setLevel(-100).build();
661        assertThat(testAp.getLevel()).isEqualTo(0);
662    }
663
664    @Test
665    public void testBuilder_settingReachableAfterLevelDoesNotAffectLevel() {
666        int level = 1;
667        assertThat(level).isLessThan(AccessPoint.SIGNAL_LEVELS - 1);
668
669        AccessPoint testAp =
670                new TestAccessPointBuilder(mContext).setLevel(level).setReachable(true).build();
671        assertThat(testAp.getLevel()).isEqualTo(level);
672    }
673
674    @Test
675    public void testBuilder_setSsid() {
676        String name = "AmazingSsid!";
677        AccessPoint namedAp = new TestAccessPointBuilder(mContext).setSsid(name).build();
678        assertThat(namedAp.getSsidStr()).isEqualTo(name);
679    }
680
681    @Test
682    public void testBuilder_passpointConfig() {
683        String fqdn = "Test.com";
684        String providerFriendlyName = "Test Provider";
685        AccessPoint ap = new TestAccessPointBuilder(mContext).setFqdn(fqdn)
686                .setProviderFriendlyName(providerFriendlyName).build();
687        assertThat(ap.isPasspointConfig()).isTrue();
688        assertThat(ap.getPasspointFqdn()).isEqualTo(fqdn);
689        assertThat(ap.getConfigName()).isEqualTo(providerFriendlyName);
690    }
691
692    @Test
693    public void testUpdateNetworkInfo_returnsTrue() {
694        int networkId = 123;
695        int rssi = -55;
696        WifiConfiguration config = new WifiConfiguration();
697        config.networkId = networkId;
698        WifiInfo wifiInfo = new WifiInfo();
699        wifiInfo.setNetworkId(networkId);
700        wifiInfo.setRssi(rssi);
701
702        NetworkInfo networkInfo =
703                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
704        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
705
706        AccessPoint ap = new TestAccessPointBuilder(mContext)
707                .setNetworkInfo(networkInfo)
708                .setNetworkId(networkId)
709                .setRssi(rssi)
710                .setWifiInfo(wifiInfo)
711                .build();
712
713        NetworkInfo newInfo = new NetworkInfo(networkInfo);
714        newInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
715        assertThat(ap.update(config, wifiInfo, newInfo)).isTrue();
716    }
717
718    @Test
719    public void testUpdateNetworkInfoWithSameInfo_returnsFalse() {
720        int networkId = 123;
721        int rssi = -55;
722        WifiConfiguration config = new WifiConfiguration();
723        config.networkId = networkId;
724        WifiInfo wifiInfo = new WifiInfo();
725        wifiInfo.setNetworkId(networkId);
726        wifiInfo.setRssi(rssi);
727
728        NetworkInfo networkInfo =
729                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
730        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
731
732        AccessPoint ap = new TestAccessPointBuilder(mContext)
733                .setNetworkInfo(networkInfo)
734                .setNetworkId(networkId)
735                .setRssi(rssi)
736                .setWifiInfo(wifiInfo)
737                .build();
738
739        NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values
740        assertThat(ap.update(config, wifiInfo, newInfo)).isFalse();
741    }
742
743    @Test
744    public void testUpdateWithDifferentRssi_returnsTrue() {
745        int networkId = 123;
746        int rssi = -55;
747        WifiConfiguration config = new WifiConfiguration();
748        config.networkId = networkId;
749        WifiInfo wifiInfo = new WifiInfo();
750        wifiInfo.setNetworkId(networkId);
751        wifiInfo.setRssi(rssi);
752
753        NetworkInfo networkInfo =
754                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
755        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
756
757        AccessPoint ap = new TestAccessPointBuilder(mContext)
758                .setNetworkInfo(networkInfo)
759                .setNetworkId(networkId)
760                .setRssi(rssi)
761                .setWifiInfo(wifiInfo)
762                .build();
763
764        NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values
765        wifiInfo.setRssi(rssi + 1);
766        assertThat(ap.update(config, wifiInfo, newInfo)).isTrue();
767    }
768
769    @Test
770    public void testUpdateWithInvalidRssi_returnsFalse() {
771        int networkId = 123;
772        int rssi = -55;
773        WifiConfiguration config = new WifiConfiguration();
774        config.networkId = networkId;
775        WifiInfo wifiInfo = new WifiInfo();
776        wifiInfo.setNetworkId(networkId);
777        wifiInfo.setRssi(rssi);
778
779        NetworkInfo networkInfo =
780                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
781        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
782
783        AccessPoint ap = new TestAccessPointBuilder(mContext)
784                .setNetworkInfo(networkInfo)
785                .setNetworkId(networkId)
786                .setRssi(rssi)
787                .setWifiInfo(wifiInfo)
788                .build();
789
790        NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values
791        wifiInfo.setRssi(WifiInfo.INVALID_RSSI);
792        assertThat(ap.update(config, wifiInfo, newInfo)).isFalse();
793    }
794    @Test
795    public void testUpdateWithConfigChangeOnly_returnsFalseButInvokesListener() {
796        int networkId = 123;
797        int rssi = -55;
798        WifiConfiguration config = new WifiConfiguration();
799        config.networkId = networkId;
800        config.numNoInternetAccessReports = 1;
801
802        WifiInfo wifiInfo = new WifiInfo();
803        wifiInfo.setNetworkId(networkId);
804        wifiInfo.setRssi(rssi);
805
806        NetworkInfo networkInfo =
807                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
808        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
809
810        AccessPoint ap = new TestAccessPointBuilder(mContext)
811                .setNetworkInfo(networkInfo)
812                .setNetworkId(networkId)
813                .setRssi(rssi)
814                .setWifiInfo(wifiInfo)
815                .build();
816
817        AccessPoint.AccessPointListener mockListener = mock(AccessPoint.AccessPointListener.class);
818        ap.setListener(mockListener);
819        WifiConfiguration newConfig = new WifiConfiguration(config);
820        config.validatedInternetAccess = true;
821
822        assertThat(ap.update(newConfig, wifiInfo, networkInfo)).isFalse();
823        verify(mockListener).onAccessPointChanged(ap);
824    }
825
826    @Test
827    public void testUpdateWithNullWifiConfiguration_doesNotThrowNPE() {
828        int networkId = 123;
829        int rssi = -55;
830        WifiConfiguration config = new WifiConfiguration();
831        config.networkId = networkId;
832        WifiInfo wifiInfo = new WifiInfo();
833        wifiInfo.setNetworkId(networkId);
834        wifiInfo.setRssi(rssi);
835
836        NetworkInfo networkInfo =
837                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
838        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
839
840        AccessPoint ap = new TestAccessPointBuilder(mContext)
841                .setNetworkInfo(networkInfo)
842                .setNetworkId(networkId)
843                .setRssi(rssi)
844                .setWifiInfo(wifiInfo)
845                .build();
846
847        ap.update(null, wifiInfo, networkInfo);
848    }
849
850    @Test
851    public void testSpeedLabelAveragesAllBssidScores() {
852        AccessPoint ap = createAccessPointWithScanResultCache();
853
854        int speed1 = Speed.MODERATE;
855        RssiCurve badgeCurve1 = mock(RssiCurve.class);
856        when(badgeCurve1.lookupScore(anyInt())).thenReturn((byte) speed1);
857        when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(0)))
858                .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve1));
859        int speed2 = Speed.VERY_FAST;
860        RssiCurve badgeCurve2 = mock(RssiCurve.class);
861        when(badgeCurve2.lookupScore(anyInt())).thenReturn((byte) speed2);
862        when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(1)))
863                .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve2));
864
865        int expectedSpeed = (speed1 + speed2) / 2;
866
867        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
868
869        assertThat(ap.getSpeed()).isEqualTo(expectedSpeed);
870    }
871
872    @Test
873    public void testSpeedLabelAverageIgnoresNoSpeedScores() {
874        AccessPoint ap = createAccessPointWithScanResultCache();
875
876        int speed1 = Speed.VERY_FAST;
877        RssiCurve badgeCurve1 = mock(RssiCurve.class);
878        when(badgeCurve1.lookupScore(anyInt())).thenReturn((byte) speed1);
879        when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(0)))
880                .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve1));
881        int speed2 = Speed.NONE;
882        RssiCurve badgeCurve2 = mock(RssiCurve.class);
883        when(badgeCurve2.lookupScore(anyInt())).thenReturn((byte) speed2);
884        when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(1)))
885                .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve2));
886
887        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
888
889        assertThat(ap.getSpeed()).isEqualTo(speed1);
890    }
891
892    @Test
893    public void testSpeedLabelFallbackScoreIgnoresNullCurves() {
894        int rssi = -55;
895        String bssid = "00:00:00:00:00:00";
896        int networkId = 123;
897
898        WifiInfo info = new WifiInfo();
899        info.setRssi(rssi);
900        info.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID));
901        info.setBSSID(bssid);
902        info.setNetworkId(networkId);
903
904        ArrayList<ScanResult> scanResults = new ArrayList<>();
905        ScanResult scanResultUnconnected = createScanResult(TEST_SSID, "11:11:11:11:11:11", rssi);
906        scanResults.add(scanResultUnconnected);
907
908        ScanResult scanResultConnected = createScanResult(TEST_SSID, bssid, rssi);
909        scanResults.add(scanResultConnected);
910
911        AccessPoint ap =
912                new TestAccessPointBuilder(mContext)
913                        .setActive(true)
914                        .setNetworkId(networkId)
915                        .setSsid(TEST_SSID)
916                        .setScanResultCache(scanResults)
917                        .setWifiInfo(info)
918                        .build();
919
920        int fallbackSpeed = Speed.SLOW;
921        when(mockWifiNetworkScoreCache.getScoredNetwork(scanResultUnconnected))
922                .thenReturn(buildScoredNetworkWithMockBadgeCurve());
923        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) fallbackSpeed);
924
925        when(mockWifiNetworkScoreCache.getScoredNetwork(scanResultConnected))
926                .thenReturn(null);
927
928        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
929
930        assertThat(ap.getSpeed()).isEqualTo(fallbackSpeed);
931    }
932
933    @Test
934    public void testScoredNetworkCacheBundling() {
935        long timeMillis = SystemClock.elapsedRealtime();
936        AccessPoint ap = createApWithFastTimestampedScoredNetworkCache(timeMillis);
937        Bundle bundle = new Bundle();
938        ap.saveWifiState(bundle);
939
940        ArrayList<TimestampedScoredNetwork> list =
941                bundle.getParcelableArrayList(AccessPoint.KEY_SCOREDNETWORKCACHE);
942        assertThat(list).hasSize(1);
943        assertThat(list.get(0).getUpdatedTimestampMillis()).isEqualTo(timeMillis);
944
945        RssiCurve curve = list.get(0).getScore().attributes.getParcelable(
946                ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE);
947        assertThat(curve).isEqualTo(FAST_BADGE_CURVE);
948    }
949
950    @Test
951    public void testRecentNetworkScoresAreUsedForSpeedLabelGeneration() {
952        AccessPoint ap =
953                createApWithFastTimestampedScoredNetworkCache(SystemClock.elapsedRealtime());
954
955        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
956
957        assertThat(ap.getSpeed()).isEqualTo(Speed.FAST);
958    }
959
960    @Test
961    public void testNetworkScoresAreUsedForSpeedLabelGenerationWhenWithinAgeRange() {
962        long withinRangeTimeMillis =
963                SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS - 10000);
964        AccessPoint ap =
965                createApWithFastTimestampedScoredNetworkCache(withinRangeTimeMillis);
966
967        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
968
969        assertThat(ap.getSpeed()).isEqualTo(Speed.FAST);
970    }
971
972    @Test
973    public void testOldNetworkScoresAreNotUsedForSpeedLabelGeneration() {
974        long tooOldTimeMillis =
975                SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS + 1);
976        AccessPoint ap =
977                createApWithFastTimestampedScoredNetworkCache(tooOldTimeMillis);
978
979        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
980
981        assertThat(ap.getSpeed()).isEqualTo(Speed.NONE);
982    }
983
984    @Test
985    public void testUpdateScoresRefreshesScoredNetworkCacheTimestamps () {
986        long tooOldTimeMillis =
987                SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS + 1);
988
989        ScoredNetwork scoredNetwork = buildScoredNetworkWithGivenBadgeCurve(FAST_BADGE_CURVE);
990        TimestampedScoredNetwork recentScore = new TimestampedScoredNetwork(
991                scoredNetwork,
992                tooOldTimeMillis);
993        AccessPoint ap = new TestAccessPointBuilder(mContext)
994                .setSsid(TEST_SSID)
995                .setBssid(TEST_BSSID)
996                .setActive(true)
997                .setScoredNetworkCache(
998                        new ArrayList(Arrays.asList(recentScore)))
999                .setScanResultCache(SCAN_RESULTS)
1000                .build();
1001
1002        when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
1003                .thenReturn(scoredNetwork);
1004
1005        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
1006
1007        // Fast should still be returned since cache was updated with recent time
1008        assertThat(ap.getSpeed()).isEqualTo(Speed.FAST);
1009    }
1010
1011    @Test
1012    public void testUpdateScoresRefreshesScoredNetworkCacheWithNewSpeed () {
1013        long tooOldTimeMillis =
1014                SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS + 1);
1015
1016        ScoredNetwork scoredNetwork = buildScoredNetworkWithGivenBadgeCurve(FAST_BADGE_CURVE);
1017        TimestampedScoredNetwork recentScore = new TimestampedScoredNetwork(
1018                scoredNetwork,
1019                tooOldTimeMillis);
1020        AccessPoint ap = new TestAccessPointBuilder(mContext)
1021                .setSsid(TEST_SSID)
1022                .setBssid(TEST_BSSID)
1023                .setActive(true)
1024                .setScoredNetworkCache(
1025                        new ArrayList(Arrays.asList(recentScore)))
1026                .setScanResultCache(SCAN_RESULTS)
1027                .build();
1028
1029        int newSpeed = Speed.MODERATE;
1030        when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
1031                .thenReturn(buildScoredNetworkWithMockBadgeCurve());
1032        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) newSpeed);
1033
1034        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
1035
1036        // Fast should still be returned since cache was updated with recent time
1037        assertThat(ap.getSpeed()).isEqualTo(newSpeed);
1038    }
1039}
1040