NetworkScoreServiceTest.java revision d601360904df9b811205f44f15c89f12703d6d72
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_noDumpPermission() {
649        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
650                eq(permission.DUMP), anyString());
651
652        try {
653            mNetworkScoreService.dump(
654                    new FileDescriptor(), new PrintWriter(new StringWriter()), new String[0]);
655            fail("SecurityException expected");
656        } catch (SecurityException e) {
657            // expected
658        }
659    }
660
661    @Test
662    public void testDump_doesNotCrash() {
663        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
664        StringWriter stringWriter = new StringWriter();
665
666        mNetworkScoreService.dump(
667                new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
668
669        assertFalse(stringWriter.toString().isEmpty());
670    }
671
672    @Test
673    public void testIsCallerActiveScorer_noBoundService() throws Exception {
674        mNetworkScoreService.onUserUnlocked(0);
675
676        assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
677    }
678
679    @Test
680    public void testIsCallerActiveScorer_boundServiceIsNotCaller() throws Exception {
681        bindToScorer(false /*callerIsScorer*/);
682
683        assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
684    }
685
686    @Test
687    public void testIsCallerActiveScorer_boundServiceIsCaller() throws Exception {
688        bindToScorer(true /*callerIsScorer*/);
689
690        assertTrue(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
691    }
692
693    @Test
694    public void testGetActiveScorerPackage_notActive() throws Exception {
695        mNetworkScoreService.onUserUnlocked(0);
696
697        assertNull(mNetworkScoreService.getActiveScorerPackage());
698    }
699
700    @Test
701    public void testGetActiveScorerPackage_active() throws Exception {
702        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
703        mNetworkScoreService.onUserUnlocked(0);
704
705        assertEquals(NEW_SCORER.getRecommendationServicePackageName(),
706                mNetworkScoreService.getActiveScorerPackage());
707        assertEquals(NEW_SCORER.getEnableUseOpenWifiActivity(),
708                mNetworkScoreService.getActiveScorer().getEnableUseOpenWifiActivity());
709    }
710
711    @Test
712    public void testCacheUpdatingConsumer_nullFilter() throws Exception {
713        List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
714        NetworkScoreService.FilteringCacheUpdatingConsumer consumer =
715                new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
716                        new ArrayList<>(scoredNetworkList), NetworkKey.TYPE_WIFI,
717                        mCurrentNetworkFilter, mScanResultsFilter);
718
719        consumer.accept(mNetworkScoreCache, null /*cookie*/);
720
721        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
722        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
723    }
724
725    @Test
726    public void testCacheUpdatingConsumer_noneFilter() 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, NetworkScoreManager.CACHE_FILTER_NONE);
734
735        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
736        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
737    }
738
739    @Test
740    public void testCacheUpdatingConsumer_unknownFilter() 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, -1 /*cookie*/);
748
749        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
750        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
751    }
752
753    @Test
754    public void testCacheUpdatingConsumer_nonIntFilter() throws Exception {
755        List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
756        NetworkScoreService.FilteringCacheUpdatingConsumer
757                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
758                new ArrayList<>(scoredNetworkList),
759                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
760
761        consumer.accept(mNetworkScoreCache, "not an int" /*cookie*/);
762
763        verify(mNetworkScoreCache).updateScores(scoredNetworkList);
764        verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
765    }
766
767    @Test
768    public void testCacheUpdatingConsumer_emptyScoreList() throws Exception {
769        NetworkScoreService.FilteringCacheUpdatingConsumer
770                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
771                Collections.emptyList(),
772                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
773
774        consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
775
776        verifyZeroInteractions(mNetworkScoreCache, mCurrentNetworkFilter, mScanResultsFilter);
777    }
778
779    @Test
780    public void testCacheUpdatingConsumer_currentNetworkFilter() throws Exception {
781        List<ScoredNetwork> scoredNetworkList =
782                Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
783        NetworkScoreService.FilteringCacheUpdatingConsumer
784                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
785                new ArrayList<>(scoredNetworkList),
786                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
787
788        List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
789        filteredList.remove(SCORED_NETWORK);
790        when(mCurrentNetworkFilter.apply(scoredNetworkList)).thenReturn(filteredList);
791        consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
792
793        verify(mNetworkScoreCache).updateScores(filteredList);
794        verifyZeroInteractions(mScanResultsFilter);
795    }
796
797    @Test
798    public void testCacheUpdatingConsumer_scanResultsFilter() throws Exception {
799        List<ScoredNetwork> scoredNetworkList =
800                Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
801        NetworkScoreService.FilteringCacheUpdatingConsumer
802                consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
803                new ArrayList<>(scoredNetworkList),
804                NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
805
806        List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
807        filteredList.remove(SCORED_NETWORK);
808        when(mScanResultsFilter.apply(scoredNetworkList)).thenReturn(filteredList);
809        consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);
810
811        verify(mNetworkScoreCache).updateScores(filteredList);
812        verifyZeroInteractions(mCurrentNetworkFilter);
813    }
814
815    @Test
816    public void testCurrentNetworkScoreCacheFilter_nullWifiInfo() throws Exception {
817        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
818                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> null /*WifiInfo*/);
819
820        List<ScoredNetwork> actualList =
821                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
822
823        assertTrue(actualList.isEmpty());
824    }
825
826    @Test
827    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_nullSsid() throws Exception {
828        when(mWifiInfo.getSSID()).thenReturn(null);
829        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
830                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
831
832        List<ScoredNetwork> actualList =
833                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
834
835        assertTrue(actualList.isEmpty());
836    }
837
838    @Test
839    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_noneSsid() throws Exception {
840        when(mWifiInfo.getSSID()).thenReturn(WifiSsid.NONE);
841        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
842                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
843
844        List<ScoredNetwork> actualList =
845                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
846
847        assertTrue(actualList.isEmpty());
848    }
849
850    @Test
851    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_emptySsid() throws Exception {
852        when(mWifiInfo.getSSID()).thenReturn("");
853        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
854                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
855
856        List<ScoredNetwork> actualList =
857                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
858
859        assertTrue(actualList.isEmpty());
860    }
861
862    @Test
863    public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_invalidBssid() throws Exception {
864        when(mWifiInfo.getBSSID()).thenReturn(INVALID_BSSID);
865        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
866                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
867
868        List<ScoredNetwork> actualList =
869                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
870
871        assertTrue(actualList.isEmpty());
872    }
873
874    @Test
875    public void testCurrentNetworkScoreCacheFilter_scoreFiltered() throws Exception {
876        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
877                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
878
879        List<ScoredNetwork> actualList =
880                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
881
882        List<ScoredNetwork> expectedList = Collections.singletonList(SCORED_NETWORK);
883        assertEquals(expectedList, actualList);
884    }
885
886    @Test
887    public void testCurrentNetworkScoreCacheFilter_currentNetworkNotInList() throws Exception {
888        when(mWifiInfo.getSSID()).thenReturn("\"notInList\"");
889        NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
890                new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
891
892        List<ScoredNetwork> actualList =
893                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
894
895        assertTrue(actualList.isEmpty());
896    }
897
898    @Test
899    public void testScanResultsScoreCacheFilter_emptyScanResults() throws Exception {
900        NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
901                new NetworkScoreService.ScanResultsScoreCacheFilter(Collections::emptyList);
902
903        List<ScoredNetwork> actualList =
904                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
905
906        assertTrue(actualList.isEmpty());
907    }
908
909    @Test
910    public void testScanResultsScoreCacheFilter_invalidScanResults() throws Exception {
911        List<ScanResult> invalidScanResults = Lists.newArrayList(
912                new ScanResult(),
913                createScanResult("", SCORED_NETWORK.networkKey.wifiKey.bssid),
914                createScanResult(WifiSsid.NONE, SCORED_NETWORK.networkKey.wifiKey.bssid),
915                createScanResult(SSID, null),
916                createScanResult(SSID, INVALID_BSSID)
917        );
918        NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
919                new NetworkScoreService.ScanResultsScoreCacheFilter(() -> invalidScanResults);
920
921        List<ScoredNetwork> actualList =
922                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
923
924        assertTrue(actualList.isEmpty());
925    }
926
927    @Test
928    public void testScanResultsScoreCacheFilter_scoresFiltered() throws Exception {
929        NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
930                new NetworkScoreService.ScanResultsScoreCacheFilter(() -> mScanResults);
931
932        ScoredNetwork unmatchedScore =
933                new ScoredNetwork(new NetworkKey(new WifiKey(quote("newSsid"),
934                        "00:00:00:00:00:00")), null /* rssiCurve*/);
935
936        List<ScoredNetwork> actualList =
937                cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2,
938                        unmatchedScore));
939
940        List<ScoredNetwork> expectedList = Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
941        assertEquals(expectedList, actualList);
942    }
943
944    @Test
945    public void testGetActiveScorer_notConnected_canRequestScores() throws Exception {
946        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
947                .thenReturn(PackageManager.PERMISSION_GRANTED);
948        assertNull(mNetworkScoreService.getActiveScorer());
949    }
950
951    @Test
952    public void testGetActiveScorer_notConnected_canNotRequestScores() throws Exception {
953        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
954                .thenReturn(PackageManager.PERMISSION_DENIED);
955        try {
956            mNetworkScoreService.getActiveScorer();
957            fail("SecurityException expected.");
958        } catch (SecurityException e) {
959            // expected
960        }
961    }
962
963    @Test
964    public void testGetActiveScorer_connected_canRequestScores()
965            throws Exception {
966        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
967                .thenReturn(PackageManager.PERMISSION_GRANTED);
968        NetworkScorerAppData expectedAppData = new NetworkScorerAppData(Binder.getCallingUid(),
969                RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
970                USE_WIFI_ENABLE_ACTIVITY_COMP, NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);
971        bindToScorer(expectedAppData);
972        assertEquals(expectedAppData, mNetworkScoreService.getActiveScorer());
973    }
974
975    @Test
976    public void testGetActiveScorer_connected_canNotRequestScores()
977            throws Exception {
978        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
979                .thenReturn(PackageManager.PERMISSION_DENIED);
980        bindToScorer(false);
981        try {
982            mNetworkScoreService.getActiveScorer();
983            fail("SecurityException expected.");
984        } catch (SecurityException e) {
985            // expected
986        }
987    }
988
989    // "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
990    private void injectProvider() {
991        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
992        when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
993                isA(UserHandle.class))).thenAnswer(new Answer<Boolean>() {
994            @Override
995            public Boolean answer(InvocationOnMock invocation) throws Throwable {
996                IBinder mockBinder = mock(IBinder.class);
997                when(mockBinder.queryLocalInterface(anyString()))
998                        .thenReturn(mRecommendationProvider);
999                invocation.<ServiceConnection>getArgument(1)
1000                        .onServiceConnected(NEW_SCORER.getRecommendationServiceComponent(),
1001                                mockBinder);
1002                return true;
1003            }
1004        });
1005        mNetworkScoreService.onUserUnlocked(0);
1006    }
1007
1008    private void bindToScorer(boolean callerIsScorer) {
1009        final int callingUid = callerIsScorer ? Binder.getCallingUid() : Binder.getCallingUid() + 1;
1010        NetworkScorerAppData appData = new NetworkScorerAppData(callingUid,
1011                RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
1012                USE_WIFI_ENABLE_ACTIVITY_COMP, NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);
1013        bindToScorer(appData);
1014    }
1015
1016    private void bindToScorer(NetworkScorerAppData appData) {
1017        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
1018        when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
1019                isA(UserHandle.class))).thenReturn(true);
1020        mNetworkScoreService.onUserUnlocked(0);
1021    }
1022
1023    private static class OnResultListener implements RemoteCallback.OnResultListener {
1024        private final CountDownLatch countDownLatch = new CountDownLatch(1);
1025        private int resultCount;
1026        private Bundle receivedBundle;
1027
1028        @Override
1029        public void onResult(Bundle result) {
1030            countDownLatch.countDown();
1031            resultCount++;
1032            receivedBundle = result;
1033        }
1034    }
1035
1036    private static class CountDownHandler extends Handler {
1037        CountDownLatch latch = new CountDownLatch(1);
1038        int receivedWhat;
1039
1040        CountDownHandler(Looper looper) {
1041            super(looper);
1042        }
1043
1044        @Override
1045        public void handleMessage(Message msg) {
1046            latch.countDown();
1047            receivedWhat = msg.what;
1048        }
1049    }
1050}
1051