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