NetworkScoreServiceTest.java revision f1acc1e8114d629278ae98657e32abecfb7b9991
1/*
2 * Copyright (C) 2012 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;
18
19import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
20import static android.net.NetworkRecommendationProvider.EXTRA_SEQUENCE;
21import static android.net.NetworkScoreManager.CACHE_FILTER_NONE;
22
23import static junit.framework.Assert.assertEquals;
24import static junit.framework.Assert.assertFalse;
25import static junit.framework.Assert.assertNotNull;
26import static junit.framework.Assert.assertNull;
27import static junit.framework.Assert.assertSame;
28import static junit.framework.Assert.assertTrue;
29import static junit.framework.Assert.fail;
30
31import static org.mockito.Matchers.any;
32import static org.mockito.Matchers.anyInt;
33import static org.mockito.Matchers.anyListOf;
34import static org.mockito.Matchers.anyString;
35import static org.mockito.Matchers.eq;
36import static org.mockito.Matchers.isA;
37import static org.mockito.Mockito.atLeastOnce;
38import static org.mockito.Mockito.doAnswer;
39import static org.mockito.Mockito.doThrow;
40import static org.mockito.Mockito.mock;
41import static org.mockito.Mockito.times;
42import static org.mockito.Mockito.verify;
43import static org.mockito.Mockito.verifyNoMoreInteractions;
44import static org.mockito.Mockito.verifyZeroInteractions;
45import static org.mockito.Mockito.when;
46
47import android.Manifest.permission;
48import android.content.ComponentName;
49import android.content.ContentResolver;
50import android.content.Context;
51import android.content.Intent;
52import android.content.ServiceConnection;
53import android.content.pm.PackageManager;
54import android.content.res.Resources;
55import android.net.INetworkRecommendationProvider;
56import android.net.INetworkScoreCache;
57import android.net.NetworkKey;
58import android.net.NetworkScoreManager;
59import android.net.NetworkScorerAppData;
60import android.net.RecommendationRequest;
61import android.net.RecommendationResult;
62import android.net.ScoredNetwork;
63import android.net.Uri;
64import android.net.WifiKey;
65import android.net.wifi.ScanResult;
66import android.net.wifi.WifiConfiguration;
67import android.net.wifi.WifiInfo;
68import android.net.wifi.WifiSsid;
69import android.os.Binder;
70import android.os.Bundle;
71import android.os.Handler;
72import android.os.HandlerThread;
73import android.os.IBinder;
74import android.os.IRemoteCallback;
75import android.os.Looper;
76import android.os.Message;
77import android.os.RemoteCallback;
78import android.os.RemoteException;
79import android.os.UserHandle;
80import android.provider.Settings;
81import android.support.test.InstrumentationRegistry;
82import android.support.test.filters.MediumTest;
83import android.support.test.runner.AndroidJUnit4;
84
85import com.android.server.devicepolicy.MockUtils;
86
87import com.google.android.collect.Lists;
88
89import org.junit.After;
90import org.junit.Before;
91import org.junit.Test;
92import org.junit.runner.RunWith;
93import org.mockito.ArgumentCaptor;
94import org.mockito.Captor;
95import org.mockito.Mock;
96import org.mockito.MockitoAnnotations;
97import org.mockito.invocation.InvocationOnMock;
98import org.mockito.stubbing.Answer;
99
100import java.io.FileDescriptor;
101import java.io.PrintWriter;
102import java.io.StringWriter;
103import java.util.ArrayList;
104import java.util.Collections;
105import java.util.List;
106import java.util.concurrent.CountDownLatch;
107import java.util.concurrent.TimeUnit;
108import java.util.function.UnaryOperator;
109
110/**
111 * Tests for {@link NetworkScoreService}.
112 */
113@RunWith(AndroidJUnit4.class)
114@MediumTest
115public class NetworkScoreServiceTest {
116    private static final String SSID = "ssid";
117    private static final String SSID_2 = "ssid_2";
118    private static final String SSID_3 = "ssid_3";
119    private static final String INVALID_BSSID = "invalid_bssid";
120    private static final ComponentName RECOMMENDATION_SERVICE_COMP =
121            new ComponentName("newPackageName", "newScoringServiceClass");
122    private static final String RECOMMENDATION_SERVICE_LABEL = "Test Recommendation Service";
123    private static final ComponentName USE_WIFI_ENABLE_ACTIVITY_COMP =
124            new ComponentName("useWifiPackageName", "enableUseWifiActivityClass");
125    private static final ScoredNetwork SCORED_NETWORK =
126            new ScoredNetwork(new NetworkKey(new WifiKey(quote(SSID), "00:00:00:00:00:00")),
127                    null /* rssiCurve*/);
128    private static final ScoredNetwork SCORED_NETWORK_2 =
129            new ScoredNetwork(new NetworkKey(new WifiKey(quote(SSID_2), "00:00:00:00:00:00")),
130                    null /* rssiCurve*/);
131    private static final String NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID =
132            "networkAvailableNotificationChannelId";
133    private static final NetworkScorerAppData NEW_SCORER = new NetworkScorerAppData(
134            1, RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
135            USE_WIFI_ENABLE_ACTIVITY_COMP, NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);
136
137    @Mock private NetworkScorerAppManager mNetworkScorerAppManager;
138    @Mock private Context mContext;
139    @Mock private Resources mResources;
140    @Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2;
141    @Mock private IBinder mIBinder, mIBinder2;
142    @Mock private INetworkRecommendationProvider mRecommendationProvider;
143    @Mock private UnaryOperator<List<ScoredNetwork>> mCurrentNetworkFilter;
144    @Mock private UnaryOperator<List<ScoredNetwork>> mScanResultsFilter;
145    @Mock private WifiInfo mWifiInfo;
146    @Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor;
147
148    private ContentResolver mContentResolver;
149    private NetworkScoreService mNetworkScoreService;
150    private RecommendationRequest mRecommendationRequest;
151    private RemoteCallback mRemoteCallback;
152    private OnResultListener mOnResultListener;
153    private HandlerThread mHandlerThread;
154    private List<ScanResult> mScanResults;
155
156    private static String quote(String str) {
157        return String.format("\"%s\"", str);
158    }
159
160    @Before
161    public void setUp() throws Exception {
162        MockitoAnnotations.initMocks(this);
163        when(mNetworkScoreCache.asBinder()).thenReturn(mIBinder);
164        when(mNetworkScoreCache2.asBinder()).thenReturn(mIBinder2);
165        mContentResolver = InstrumentationRegistry.getContext().getContentResolver();
166        when(mContext.getContentResolver()).thenReturn(mContentResolver);
167        when(mContext.getResources()).thenReturn(mResources);
168        when(mWifiInfo.getSSID()).thenReturn(SCORED_NETWORK.networkKey.wifiKey.ssid);
169        when(mWifiInfo.getBSSID()).thenReturn(SCORED_NETWORK.networkKey.wifiKey.bssid);
170        mHandlerThread = new HandlerThread("NetworkScoreServiceTest");
171        mHandlerThread.start();
172        mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager,
173                mHandlerThread.getLooper());
174        WifiConfiguration configuration = new WifiConfiguration();
175        configuration.SSID = "NetworkScoreServiceTest_SSID";
176        configuration.BSSID = "NetworkScoreServiceTest_BSSID";
177        mRecommendationRequest = new RecommendationRequest.Builder()
178            .setDefaultWifiConfig(configuration).build();
179        mOnResultListener = new OnResultListener();
180        mRemoteCallback = new RemoteCallback(mOnResultListener);
181        Settings.Global.putLong(mContentResolver,
182                Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, -1L);
183        mNetworkScoreService.refreshRecommendationRequestTimeoutMs();
184        populateScanResults();
185    }
186
187    private void populateScanResults() {
188        mScanResults = new ArrayList<>();
189        mScanResults.add(createScanResult(SSID, SCORED_NETWORK.networkKey.wifiKey.bssid));
190        mScanResults.add(createScanResult(SSID_2, SCORED_NETWORK_2.networkKey.wifiKey.bssid));
191        mScanResults.add(createScanResult(SSID_3, "10:10:00:00:10:10"));
192    }
193
194    private ScanResult createScanResult(String ssid, String bssid) {
195        ScanResult result = new ScanResult();
196        result.wifiSsid = WifiSsid.createFromAsciiEncoded(ssid);
197        result.BSSID = bssid;
198        return result;
199    }
200
201    @After
202    public void tearDown() throws Exception {
203        mHandlerThread.quitSafely();
204    }
205
206    @Test
207    public void testOnUserUnlocked() {
208        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
209
210        mNetworkScoreService.onUserUnlocked(0);
211
212        verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
213                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
214                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
215                any(ServiceConnection.class),
216                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
217                eq(UserHandle.SYSTEM));
218    }
219
220    @Test
221    public void testRequestScores_noPermission() throws Exception {
222        doThrow(new SecurityException()).when(mContext)
223            .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
224                anyString());
225        try {
226            mNetworkScoreService.requestScores(null);
227            fail("REQUEST_NETWORK_SCORES not enforced.");
228        } catch (SecurityException e) {
229            // expected
230        }
231    }
232
233    @Test
234    public void testRequestScores_providerNotConnected() throws Exception {
235        assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0]));
236        verifyZeroInteractions(mRecommendationProvider);
237    }
238
239    @Test
240    public void testRequestScores_providerThrowsRemoteException() throws Exception {
241        injectProvider();
242        doThrow(new RemoteException()).when(mRecommendationProvider)
243            .requestScores(any(NetworkKey[].class));
244
245        assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0]));
246    }
247
248    @Test
249    public void testRequestScores_providerAvailable() throws Exception {
250        injectProvider();
251
252        final NetworkKey[] networks = new NetworkKey[0];
253        assertTrue(mNetworkScoreService.requestScores(networks));
254        verify(mRecommendationProvider).requestScores(networks);
255    }
256
257    @Test
258    public void testRequestRecommendation_noPermission() throws Exception {
259        doThrow(new SecurityException()).when(mContext)
260            .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
261                anyString());
262        try {
263            mNetworkScoreService.requestRecommendation(mRecommendationRequest);
264            fail("REQUEST_NETWORK_SCORES not enforced.");
265        } catch (SecurityException e) {
266            // expected
267        }
268    }
269
270    @Test
271    public void testRequestRecommendation_mainThread() throws Exception {
272        when(mContext.getMainLooper()).thenReturn(Looper.myLooper());
273        try {
274            mNetworkScoreService.requestRecommendation(mRecommendationRequest);
275            fail("requestRecommendation run on main thread.");
276        } catch (RuntimeException e) {
277            // expected
278        }
279    }
280
281    @Test
282    public void testRequestRecommendation_providerNotConnected() throws Exception {
283        when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
284
285        final RecommendationResult result =
286                mNetworkScoreService.requestRecommendation(mRecommendationRequest);
287        assertNotNull(result);
288        assertEquals(mRecommendationRequest.getDefaultWifiConfig(),
289                result.getWifiConfiguration());
290    }
291
292    @Test
293    public void testRequestRecommendation_providerThrowsRemoteException() throws Exception {
294        injectProvider();
295        when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
296        doThrow(new RemoteException()).when(mRecommendationProvider)
297                .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
298                        anyInt());
299
300        final RecommendationResult result =
301                mNetworkScoreService.requestRecommendation(mRecommendationRequest);
302        assertNotNull(result);
303        assertEquals(mRecommendationRequest.getDefaultWifiConfig(),
304                result.getWifiConfiguration());
305    }
306
307    @Test
308    public void testRequestRecommendation_resultReturned() throws Exception {
309        injectProvider();
310        when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
311        final WifiConfiguration wifiConfiguration = new WifiConfiguration();
312        wifiConfiguration.SSID = "testRequestRecommendation_resultReturned_SSID";
313        wifiConfiguration.BSSID = "testRequestRecommendation_resultReturned_BSSID";
314        final RecommendationResult providerResult = RecommendationResult
315                .createConnectRecommendation(wifiConfiguration);
316        final Bundle bundle = new Bundle();
317        bundle.putParcelable(EXTRA_RECOMMENDATION_RESULT, providerResult);
318        doAnswer(invocation -> {
319            bundle.putInt(EXTRA_SEQUENCE, invocation.getArgument(2));
320            invocation.<IRemoteCallback>getArgument(1).sendResult(bundle);
321            return null;
322        }).when(mRecommendationProvider)
323                .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
324                        anyInt());
325
326        final RecommendationResult result =
327                mNetworkScoreService.requestRecommendation(mRecommendationRequest);
328        assertNotNull(result);
329        assertEquals(providerResult.getWifiConfiguration().SSID,
330                result.getWifiConfiguration().SSID);
331        assertEquals(providerResult.getWifiConfiguration().BSSID,
332                result.getWifiConfiguration().BSSID);
333    }
334
335    @Test
336    public void testRequestRecommendationAsync_noPermission() throws Exception {
337        doThrow(new SecurityException()).when(mContext)
338                .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
339                        anyString());
340        try {
341            mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
342                    mRemoteCallback);
343            fail("REQUEST_NETWORK_SCORES not enforced.");
344        } catch (SecurityException e) {
345            // expected
346        }
347    }
348
349    @Test
350    public void testRequestRecommendationAsync_providerNotConnected() throws Exception {
351        mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
352                mRemoteCallback);
353        boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
354        assertTrue(callbackRan);
355        verifyZeroInteractions(mRecommendationProvider);
356    }
357
358    @Test
359    public void testRequestRecommendationAsync_requestTimesOut() throws Exception {
360        injectProvider();
361        Settings.Global.putLong(mContentResolver,
362                Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, 1L);
363        mNetworkScoreService.refreshRecommendationRequestTimeoutMs();
364        mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
365                mRemoteCallback);
366        boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
367        assertTrue(callbackRan);
368        verify(mRecommendationProvider).requestRecommendation(eq(mRecommendationRequest),
369                isA(IRemoteCallback.Stub.class), anyInt());
370
371        assertTrue(mOnResultListener.receivedBundle.containsKey(EXTRA_RECOMMENDATION_RESULT));
372        RecommendationResult result =
373                mOnResultListener.receivedBundle.getParcelable(EXTRA_RECOMMENDATION_RESULT);
374        assertTrue(result.hasRecommendation());
375        assertEquals(mRecommendationRequest.getDefaultWifiConfig().SSID,
376                result.getWifiConfiguration().SSID);
377    }
378
379    @Test
380    public void testRequestRecommendationAsync_requestSucceeds() throws Exception {
381        injectProvider();
382        final Bundle bundle = new Bundle();
383        doAnswer(invocation -> {
384            invocation.<IRemoteCallback>getArgument(1).sendResult(bundle);
385            return null;
386        }).when(mRecommendationProvider)
387                .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
388                        anyInt());
389
390        mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
391                mRemoteCallback);
392        boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
393        assertTrue(callbackRan);
394        // If it's not the same instance then something else ran the callback.
395        assertSame(bundle, mOnResultListener.receivedBundle);
396    }
397
398    @Test
399    public void testRequestRecommendationAsync_requestThrowsRemoteException() throws Exception {
400        injectProvider();
401        doThrow(new RemoteException()).when(mRecommendationProvider)
402                .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
403                        anyInt());
404
405        mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
406                mRemoteCallback);
407        boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
408        assertTrue(callbackRan);
409    }
410
411    @Test
412    public void dispatchingContentObserver_nullUri() throws Exception {
413        NetworkScoreService.DispatchingContentObserver observer =
414                new NetworkScoreService.DispatchingContentObserver(mContext, null /*handler*/);
415
416        observer.onChange(false, null);
417        // nothing to assert or verify but since we passed in a null handler we'd see a NPE
418        // if it were interacted with.
419    }
420
421    @Test
422    public void dispatchingContentObserver_dispatchUri() throws Exception {
423        final CountDownHandler handler = new CountDownHandler(mHandlerThread.getLooper());
424        NetworkScoreService.DispatchingContentObserver observer =
425                new NetworkScoreService.DispatchingContentObserver(mContext, handler);
426        Uri uri = Uri.parse("content://settings/global/network_score_service_test");
427        int expectedWhat = 24;
428        observer.observe(uri, expectedWhat);
429
430        observer.onChange(false, uri);
431        final boolean msgHandled = handler.latch.await(3, TimeUnit.SECONDS);
432        assertTrue(msgHandled);
433        assertEquals(expectedWhat, handler.receivedWhat);
434    }
435
436    @Test
437    public void oneTimeCallback_multipleCallbacks() throws Exception {
438        NetworkScoreService.OneTimeCallback callback =
439                new NetworkScoreService.OneTimeCallback(mRemoteCallback);
440        callback.sendResult(null);
441        callback.sendResult(null);
442        assertEquals(1, mOnResultListener.resultCount);
443    }
444
445    @Test
446    public void testUpdateScores_notActiveScorer() {
447        bindToScorer(false /*callerIsScorer*/);
448
449        try {
450            mNetworkScoreService.updateScores(new ScoredNetwork[0]);
451            fail("SecurityException expected");
452        } catch (SecurityException e) {
453            // expected
454        }
455    }
456
457    @Test
458    public void testUpdateScores_oneRegisteredCache() throws RemoteException {
459        bindToScorer(true /*callerIsScorer*/);
460
461        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
462                mNetworkScoreCache, CACHE_FILTER_NONE);
463
464        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
465
466        verify(mNetworkScoreCache).updateScores(mScoredNetworkCaptor.capture());
467
468        assertEquals(1, mScoredNetworkCaptor.getValue().size());
469        assertEquals(SCORED_NETWORK, mScoredNetworkCaptor.getValue().get(0));
470    }
471
472    @Test
473    public void testUpdateScores_twoRegisteredCaches() throws RemoteException {
474        bindToScorer(true /*callerIsScorer*/);
475
476        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
477                mNetworkScoreCache, CACHE_FILTER_NONE);
478        mNetworkScoreService.registerNetworkScoreCache(
479                NetworkKey.TYPE_WIFI, mNetworkScoreCache2, CACHE_FILTER_NONE);
480
481        // updateScores should update both caches
482        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
483
484        verify(mNetworkScoreCache).updateScores(anyListOf(ScoredNetwork.class));
485        verify(mNetworkScoreCache2).updateScores(anyListOf(ScoredNetwork.class));
486
487        mNetworkScoreService.unregisterNetworkScoreCache(
488                NetworkKey.TYPE_WIFI, mNetworkScoreCache2);
489
490        // updateScores should only update the first cache since the 2nd has been unregistered
491        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
492
493        verify(mNetworkScoreCache, times(2)).updateScores(anyListOf(ScoredNetwork.class));
494
495        mNetworkScoreService.unregisterNetworkScoreCache(
496                NetworkKey.TYPE_WIFI, mNetworkScoreCache);
497
498        // updateScores should not update any caches since they are both unregistered
499        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
500
501        // The register and unregister calls grab the binder from the score cache.
502        verify(mNetworkScoreCache, atLeastOnce()).asBinder();
503        verify(mNetworkScoreCache2, atLeastOnce()).asBinder();
504        verifyNoMoreInteractions(mNetworkScoreCache, mNetworkScoreCache2);
505    }
506
507    @Test
508    public void testClearScores_notActiveScorer_noRequestNetworkScoresPermission() {
509        bindToScorer(false /*callerIsScorer*/);
510        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
511            .thenReturn(PackageManager.PERMISSION_DENIED);
512        try {
513            mNetworkScoreService.clearScores();
514            fail("SecurityException expected");
515        } catch (SecurityException e) {
516            // expected
517        }
518    }
519
520    @Test
521    public void testClearScores_activeScorer_noRequestNetworkScoresPermission() {
522        bindToScorer(true /*callerIsScorer*/);
523        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
524            .thenReturn(PackageManager.PERMISSION_DENIED);
525
526        mNetworkScoreService.clearScores();
527    }
528
529    @Test
530    public void testClearScores_activeScorer() throws RemoteException {
531        bindToScorer(true /*callerIsScorer*/);
532
533        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
534                CACHE_FILTER_NONE);
535        mNetworkScoreService.clearScores();
536
537        verify(mNetworkScoreCache).clearScores();
538    }
539
540    @Test
541    public void testClearScores_notActiveScorer_hasRequestNetworkScoresPermission()
542            throws RemoteException {
543        bindToScorer(false /*callerIsScorer*/);
544        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
545                .thenReturn(PackageManager.PERMISSION_GRANTED);
546
547        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
548                CACHE_FILTER_NONE);
549        mNetworkScoreService.clearScores();
550
551        verify(mNetworkScoreCache).clearScores();
552    }
553
554    @Test
555    public void testSetActiveScorer_noRequestNetworkScoresPermission() {
556        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
557                .thenReturn(PackageManager.PERMISSION_DENIED);
558
559        try {
560            mNetworkScoreService.setActiveScorer(null);
561            fail("SecurityException expected");
562        } catch (SecurityException e) {
563            // expected
564        }
565    }
566
567    @Test
568    public void testSetActiveScorer_requestNetworkScoresPermission() {
569        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
570                .thenReturn(PackageManager.PERMISSION_GRANTED);
571
572        mNetworkScoreService.setActiveScorer(null);
573    }
574
575    @Test
576    public void testDisableScoring_notActiveScorer_noRequestNetworkScoresPermission() {
577        bindToScorer(false /*callerIsScorer*/);
578        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
579                .thenReturn(PackageManager.PERMISSION_DENIED);
580
581        try {
582            mNetworkScoreService.disableScoring();
583            fail("SecurityException expected");
584        } catch (SecurityException e) {
585            // expected
586        }
587    }
588
589    @Test
590    public void testDisableScoring_activeScorer_noRequestNetworkScoresPermission() {
591        bindToScorer(true /*callerIsScorer*/);
592        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
593                .thenReturn(PackageManager.PERMISSION_DENIED);
594
595        mNetworkScoreService.disableScoring();
596    }
597
598    @Test
599    public void testGetAllValidScorer_noRequestNetworkScoresPermission() {
600        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
601                .thenReturn(PackageManager.PERMISSION_DENIED);
602
603        try {
604            mNetworkScoreService.getAllValidScorers();
605            fail("SecurityException expected");
606        } catch (SecurityException e) {
607            // expected
608        }
609    }
610
611    @Test
612    public void testGetAllValidScorer_requestNetworkScoresPermission() {
613        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
614                .thenReturn(PackageManager.PERMISSION_GRANTED);
615
616        mNetworkScoreService.getAllValidScorers();
617    }
618
619    @Test
620    public void testRegisterNetworkScoreCache_noRequestNetworkScoresPermission() {
621        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
622                eq(permission.REQUEST_NETWORK_SCORES), anyString());
623
624        try {
625            mNetworkScoreService.registerNetworkScoreCache(
626                NetworkKey.TYPE_WIFI, mNetworkScoreCache, CACHE_FILTER_NONE);
627            fail("SecurityException expected");
628        } catch (SecurityException e) {
629            // expected
630        }
631    }
632
633    @Test
634    public void testUnregisterNetworkScoreCache_noRequestNetworkScoresPermission() {
635        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
636                eq(permission.REQUEST_NETWORK_SCORES), anyString());
637
638        try {
639            mNetworkScoreService.unregisterNetworkScoreCache(
640                    NetworkKey.TYPE_WIFI, mNetworkScoreCache);
641            fail("SecurityException expected");
642        } catch (SecurityException e) {
643            // expected
644        }
645    }
646
647    @Test
648    public void testDump_doesNotCrash() {
649        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
650        StringWriter stringWriter = new StringWriter();
651
652        mNetworkScoreService.dump(
653                new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
654
655        assertFalse(stringWriter.toString().isEmpty());
656    }
657
658    @Test
659    public void testIsCallerActiveScorer_noBoundService() throws Exception {
660        mNetworkScoreService.onUserUnlocked(0);
661
662        assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
663    }
664
665    @Test
666    public void testIsCallerActiveScorer_boundServiceIsNotCaller() throws Exception {
667        bindToScorer(false /*callerIsScorer*/);
668
669        assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
670    }
671
672    @Test
673    public void testIsCallerActiveScorer_boundServiceIsCaller() throws Exception {
674        bindToScorer(true /*callerIsScorer*/);
675
676        assertTrue(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
677    }
678
679    @Test
680    public void testGetActiveScorerPackage_notActive() throws Exception {
681        mNetworkScoreService.onUserUnlocked(0);
682
683        assertNull(mNetworkScoreService.getActiveScorerPackage());
684    }
685
686    @Test
687    public void testGetActiveScorerPackage_active() throws Exception {
688        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
689        mNetworkScoreService.onUserUnlocked(0);
690
691        assertEquals(NEW_SCORER.getRecommendationServicePackageName(),
692                mNetworkScoreService.getActiveScorerPackage());
693        assertEquals(NEW_SCORER.getEnableUseOpenWifiActivity(),
694                mNetworkScoreService.getActiveScorer().getEnableUseOpenWifiActivity());
695    }
696
697    @Test
698    public void testCacheUpdatingConsumer_nullFilter() throws Exception {
699        List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
700        NetworkScoreService.FilteringCacheUpdatingConsumer consumer =
701                new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
702                        new ArrayList<>(scoredNetworkList), NetworkKey.TYPE_WIFI,
703                        mCurrentNetworkFilter, mScanResultsFilter);
704
705        consumer.accept(mNetworkScoreCache, null /*cookie*/);
706
707        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
708        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
709    }
710
711    @Test
712    public void testCacheUpdatingConsumer_noneFilter() throws Exception {
713        List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
714        NetworkScoreService.FilteringCacheUpdatingConsumer
715                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
716                new ArrayList<>(scoredNetworkList),
717                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
718
719        consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
720
721        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
722        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
723    }
724
725    @Test
726    public void testCacheUpdatingConsumer_unknownFilter() throws Exception {
727        List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
728        NetworkScoreService.FilteringCacheUpdatingConsumer
729                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
730                new ArrayList<>(scoredNetworkList),
731                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
732
733        consumer.accept(mNetworkScoreCache, -1 /*cookie*/);
734
735        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
736        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
737    }
738
739    @Test
740    public void testCacheUpdatingConsumer_nonIntFilter() throws Exception {
741        List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
742        NetworkScoreService.FilteringCacheUpdatingConsumer
743                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
744                new ArrayList<>(scoredNetworkList),
745                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
746
747        consumer.accept(mNetworkScoreCache, "not an int" /*cookie*/);
748
749        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
750        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
751    }
752
753    @Test
754    public void testCacheUpdatingConsumer_emptyScoreList() throws Exception {
755        NetworkScoreService.FilteringCacheUpdatingConsumer
756                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
757                Collections.emptyList(),
758                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
759
760        consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
761
762        verifyZeroInteractions(mNetworkScoreCache, mCurrentNetworkFilter, mScanResultsFilter);
763    }
764
765    @Test
766    public void testCacheUpdatingConsumer_currentNetworkFilter() throws Exception {
767        List<ScoredNetwork> scoredNetworkList =
768                Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
769        NetworkScoreService.FilteringCacheUpdatingConsumer
770                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
771                new ArrayList<>(scoredNetworkList),
772                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
773
774        List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
775        filteredList.remove(SCORED_NETWORK);
776        when(mCurrentNetworkFilter.apply(scoredNetworkList)).thenReturn(filteredList);
777        consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
778
779        verify(mNetworkScoreCache).updateScores(filteredList);
780        verifyZeroInteractions(mScanResultsFilter);
781    }
782
783    @Test
784    public void testCacheUpdatingConsumer_scanResultsFilter() throws Exception {
785        List<ScoredNetwork> scoredNetworkList =
786                Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
787        NetworkScoreService.FilteringCacheUpdatingConsumer
788                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
789                new ArrayList<>(scoredNetworkList),
790                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
791
792        List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
793        filteredList.remove(SCORED_NETWORK);
794        when(mScanResultsFilter.apply(scoredNetworkList)).thenReturn(filteredList);
795        consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);
796
797        verify(mNetworkScoreCache).updateScores(filteredList);
798        verifyZeroInteractions(mCurrentNetworkFilter);
799    }
800
801    @Test
802    public void testCurrentNetworkScoreCacheFilter_nullWifiInfo() throws Exception {
803        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
804                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> null /*WifiInfo*/);
805
806        List<ScoredNetwork> actualList =
807                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
808
809        assertTrue(actualList.isEmpty());
810    }
811
812    @Test
813    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_nullSsid() throws Exception {
814        when(mWifiInfo.getSSID()).thenReturn(null);
815        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
816                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
817
818        List<ScoredNetwork> actualList =
819                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
820
821        assertTrue(actualList.isEmpty());
822    }
823
824    @Test
825    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_noneSsid() throws Exception {
826        when(mWifiInfo.getSSID()).thenReturn(WifiSsid.NONE);
827        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
828                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
829
830        List<ScoredNetwork> actualList =
831                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
832
833        assertTrue(actualList.isEmpty());
834    }
835
836    @Test
837    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_emptySsid() throws Exception {
838        when(mWifiInfo.getSSID()).thenReturn("");
839        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
840                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
841
842        List<ScoredNetwork> actualList =
843                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
844
845        assertTrue(actualList.isEmpty());
846    }
847
848    @Test
849    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_invalidBssid() throws Exception {
850        when(mWifiInfo.getBSSID()).thenReturn(INVALID_BSSID);
851        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
852                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
853
854        List<ScoredNetwork> actualList =
855                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
856
857        assertTrue(actualList.isEmpty());
858    }
859
860    @Test
861    public void testCurrentNetworkScoreCacheFilter_scoreFiltered() throws Exception {
862        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
863                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
864
865        List<ScoredNetwork> actualList =
866                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
867
868        List<ScoredNetwork> expectedList = Collections.singletonList(SCORED_NETWORK);
869        assertEquals(expectedList, actualList);
870    }
871
872    @Test
873    public void testCurrentNetworkScoreCacheFilter_currentNetworkNotInList() throws Exception {
874        when(mWifiInfo.getSSID()).thenReturn("\"notInList\"");
875        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
876                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
877
878        List<ScoredNetwork> actualList =
879                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
880
881        assertTrue(actualList.isEmpty());
882    }
883
884    @Test
885    public void testScanResultsScoreCacheFilter_emptyScanResults() throws Exception {
886        NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
887                new NetworkScoreService.ScanResultsScoreCacheFilter(Collections::emptyList);
888
889        List<ScoredNetwork> actualList =
890                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
891
892        assertTrue(actualList.isEmpty());
893    }
894
895    @Test
896    public void testScanResultsScoreCacheFilter_invalidScanResults() throws Exception {
897        List<ScanResult> invalidScanResults = Lists.newArrayList(
898                new ScanResult(),
899                createScanResult("", SCORED_NETWORK.networkKey.wifiKey.bssid),
900                createScanResult(WifiSsid.NONE, SCORED_NETWORK.networkKey.wifiKey.bssid),
901                createScanResult(SSID, null),
902                createScanResult(SSID, INVALID_BSSID)
903        );
904        NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
905                new NetworkScoreService.ScanResultsScoreCacheFilter(() -> invalidScanResults);
906
907        List<ScoredNetwork> actualList =
908                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
909
910        assertTrue(actualList.isEmpty());
911    }
912
913    @Test
914    public void testScanResultsScoreCacheFilter_scoresFiltered() throws Exception {
915        NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
916                new NetworkScoreService.ScanResultsScoreCacheFilter(() -> mScanResults);
917
918        ScoredNetwork unmatchedScore =
919                new ScoredNetwork(new NetworkKey(new WifiKey(quote("newSsid"),
920                        "00:00:00:00:00:00")), null /* rssiCurve*/);
921
922        List<ScoredNetwork> actualList =
923                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2,
924                        unmatchedScore));
925
926        List<ScoredNetwork> expectedList = Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
927        assertEquals(expectedList, actualList);
928    }
929
930    @Test
931    public void testGetActiveScorer_notConnected_canRequestScores() throws Exception {
932        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
933                .thenReturn(PackageManager.PERMISSION_GRANTED);
934        assertNull(mNetworkScoreService.getActiveScorer());
935    }
936
937    @Test
938    public void testGetActiveScorer_notConnected_canNotRequestScores() throws Exception {
939        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
940                .thenReturn(PackageManager.PERMISSION_DENIED);
941        try {
942            mNetworkScoreService.getActiveScorer();
943            fail("SecurityException expected.");
944        } catch (SecurityException e) {
945            // expected
946        }
947    }
948
949    @Test
950    public void testGetActiveScorer_connected_canRequestScores()
951            throws Exception {
952        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
953                .thenReturn(PackageManager.PERMISSION_GRANTED);
954        NetworkScorerAppData expectedAppData = new NetworkScorerAppData(Binder.getCallingUid(),
955                RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
956                USE_WIFI_ENABLE_ACTIVITY_COMP, NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);
957        bindToScorer(expectedAppData);
958        assertEquals(expectedAppData, mNetworkScoreService.getActiveScorer());
959    }
960
961    @Test
962    public void testGetActiveScorer_connected_canNotRequestScores()
963            throws Exception {
964        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
965                .thenReturn(PackageManager.PERMISSION_DENIED);
966        bindToScorer(false);
967        try {
968            mNetworkScoreService.getActiveScorer();
969            fail("SecurityException expected.");
970        } catch (SecurityException e) {
971            // expected
972        }
973    }
974
975    // "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
976    private void injectProvider() {
977        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
978        when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
979                isA(UserHandle.class))).thenAnswer(new Answer<Boolean>() {
980            @Override
981            public Boolean answer(InvocationOnMock invocation) throws Throwable {
982                IBinder mockBinder = mock(IBinder.class);
983                when(mockBinder.queryLocalInterface(anyString()))
984                        .thenReturn(mRecommendationProvider);
985                invocation.<ServiceConnection>getArgument(1)
986                        .onServiceConnected(NEW_SCORER.getRecommendationServiceComponent(),
987                                mockBinder);
988                return true;
989            }
990        });
991        mNetworkScoreService.onUserUnlocked(0);
992    }
993
994    private void bindToScorer(boolean callerIsScorer) {
995        final int callingUid = callerIsScorer ? Binder.getCallingUid() : Binder.getCallingUid() + 1;
996        NetworkScorerAppData appData = new NetworkScorerAppData(callingUid,
997                RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
998                USE_WIFI_ENABLE_ACTIVITY_COMP, NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);
999        bindToScorer(appData);
1000    }
1001
1002    private void bindToScorer(NetworkScorerAppData appData) {
1003        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
1004        when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
1005                isA(UserHandle.class))).thenReturn(true);
1006        mNetworkScoreService.onUserUnlocked(0);
1007    }
1008
1009    private static class OnResultListener implements RemoteCallback.OnResultListener {
1010        private final CountDownLatch countDownLatch = new CountDownLatch(1);
1011        private int resultCount;
1012        private Bundle receivedBundle;
1013
1014        @Override
1015        public void onResult(Bundle result) {
1016            countDownLatch.countDown();
1017            resultCount++;
1018            receivedBundle = result;
1019        }
1020    }
1021
1022    private static class CountDownHandler extends Handler {
1023        CountDownLatch latch = new CountDownLatch(1);
1024        int receivedWhat;
1025
1026        CountDownHandler(Looper looper) {
1027            super(looper);
1028        }
1029
1030        @Override
1031        public void handleMessage(Message msg) {
1032            latch.countDown();
1033            receivedWhat = msg.what;
1034        }
1035    }
1036}
1037