NetworkScoreServiceTest.java revision 122957b0b0585068d82934afa2b02f8f0ad8a584
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.NetworkScorerAppManager;
60import android.net.NetworkScorerAppManager.NetworkScorerAppData;
61import android.net.RecommendationRequest;
62import android.net.RecommendationResult;
63import android.net.ScoredNetwork;
64import android.net.Uri;
65import android.net.WifiKey;
66import android.net.wifi.WifiConfiguration;
67import android.os.Binder;
68import android.os.Bundle;
69import android.os.Handler;
70import android.os.HandlerThread;
71import android.os.IBinder;
72import android.os.IRemoteCallback;
73import android.os.Looper;
74import android.os.Message;
75import android.os.RemoteCallback;
76import android.os.RemoteException;
77import android.os.UserHandle;
78import android.provider.Settings;
79import android.support.test.InstrumentationRegistry;
80import android.support.test.filters.MediumTest;
81import android.support.test.runner.AndroidJUnit4;
82
83import com.android.server.devicepolicy.MockUtils;
84
85import org.junit.After;
86import org.junit.Before;
87import org.junit.Test;
88import org.junit.runner.RunWith;
89import org.mockito.ArgumentCaptor;
90import org.mockito.Captor;
91import org.mockito.Mock;
92import org.mockito.MockitoAnnotations;
93import org.mockito.invocation.InvocationOnMock;
94import org.mockito.stubbing.Answer;
95
96import java.io.FileDescriptor;
97import java.io.PrintWriter;
98import java.io.StringWriter;
99import java.util.List;
100import java.util.concurrent.CountDownLatch;
101import java.util.concurrent.TimeUnit;
102
103/**
104 * Tests for {@link NetworkScoreService}.
105 */
106@RunWith(AndroidJUnit4.class)
107@MediumTest
108public class NetworkScoreServiceTest {
109    private static final ScoredNetwork SCORED_NETWORK =
110            new ScoredNetwork(new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00")),
111                    null /* rssiCurve*/);
112    private static final NetworkScorerAppData NEW_SCORER =
113        new NetworkScorerAppData("newPackageName", 1, "newScoringServiceClass");
114
115    @Mock private PackageManager mPackageManager;
116    @Mock private NetworkScorerAppManager mNetworkScorerAppManager;
117    @Mock private Context mContext;
118    @Mock private Resources mResources;
119    @Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2;
120    @Mock private IBinder mIBinder, mIBinder2;
121    @Mock private INetworkRecommendationProvider mRecommendationProvider;
122    @Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor;
123
124    private ContentResolver mContentResolver;
125    private NetworkScoreService mNetworkScoreService;
126    private RecommendationRequest mRecommendationRequest;
127    private RemoteCallback mRemoteCallback;
128    private OnResultListener mOnResultListener;
129    private HandlerThread mHandlerThread;
130
131    @Before
132    public void setUp() throws Exception {
133        MockitoAnnotations.initMocks(this);
134        when(mNetworkScoreCache.asBinder()).thenReturn(mIBinder);
135        when(mNetworkScoreCache2.asBinder()).thenReturn(mIBinder2);
136        mContentResolver = InstrumentationRegistry.getContext().getContentResolver();
137        when(mContext.getContentResolver()).thenReturn(mContentResolver);
138        when(mContext.getResources()).thenReturn(mResources);
139        mHandlerThread = new HandlerThread("NetworkScoreServiceTest");
140        mHandlerThread.start();
141        mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager,
142                mHandlerThread.getLooper());
143        WifiConfiguration configuration = new WifiConfiguration();
144        configuration.SSID = "NetworkScoreServiceTest_SSID";
145        configuration.BSSID = "NetworkScoreServiceTest_BSSID";
146        mRecommendationRequest = new RecommendationRequest.Builder()
147            .setDefaultWifiConfig(configuration).build();
148        mOnResultListener = new OnResultListener();
149        mRemoteCallback = new RemoteCallback(mOnResultListener);
150        Settings.Global.putLong(mContentResolver,
151                Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, -1L);
152        mNetworkScoreService.refreshRecommendationRequestTimeoutMs();
153    }
154
155    @After
156    public void tearDown() throws Exception {
157        mHandlerThread.quitSafely();
158    }
159
160    @Test
161    public void testSystemRunning() {
162        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
163
164        mNetworkScoreService.systemRunning();
165
166        verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
167                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
168                        .setComponent(new ComponentName(NEW_SCORER.packageName,
169                                NEW_SCORER.recommendationServiceClassName))),
170                any(ServiceConnection.class),
171                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
172                eq(UserHandle.SYSTEM));
173    }
174
175    @Test
176    public void testRequestScores_noPermission() throws Exception {
177        doThrow(new SecurityException()).when(mContext)
178            .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
179                anyString());
180        try {
181            mNetworkScoreService.requestScores(null);
182            fail("REQUEST_NETWORK_SCORES not enforced.");
183        } catch (SecurityException e) {
184            // expected
185        }
186    }
187
188    @Test
189    public void testRequestScores_providerNotConnected() throws Exception {
190        assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0]));
191        verifyZeroInteractions(mRecommendationProvider);
192    }
193
194    @Test
195    public void testRequestScores_providerThrowsRemoteException() throws Exception {
196        injectProvider();
197        doThrow(new RemoteException()).when(mRecommendationProvider)
198            .requestScores(any(NetworkKey[].class));
199
200        assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0]));
201    }
202
203    @Test
204    public void testRequestScores_providerAvailable() throws Exception {
205        injectProvider();
206
207        final NetworkKey[] networks = new NetworkKey[0];
208        assertTrue(mNetworkScoreService.requestScores(networks));
209        verify(mRecommendationProvider).requestScores(networks);
210    }
211
212    @Test
213    public void testRequestRecommendation_noPermission() throws Exception {
214        doThrow(new SecurityException()).when(mContext)
215            .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
216                anyString());
217        try {
218            mNetworkScoreService.requestRecommendation(mRecommendationRequest);
219            fail("REQUEST_NETWORK_SCORES not enforced.");
220        } catch (SecurityException e) {
221            // expected
222        }
223    }
224
225    @Test
226    public void testRequestRecommendation_mainThread() throws Exception {
227        when(mContext.getMainLooper()).thenReturn(Looper.myLooper());
228        try {
229            mNetworkScoreService.requestRecommendation(mRecommendationRequest);
230            fail("requestRecommendation run on main thread.");
231        } catch (RuntimeException e) {
232            // expected
233        }
234    }
235
236    @Test
237    public void testRequestRecommendation_providerNotConnected() throws Exception {
238        when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
239
240        final RecommendationResult result =
241                mNetworkScoreService.requestRecommendation(mRecommendationRequest);
242        assertNotNull(result);
243        assertEquals(mRecommendationRequest.getDefaultWifiConfig(),
244                result.getWifiConfiguration());
245    }
246
247    @Test
248    public void testRequestRecommendation_providerThrowsRemoteException() throws Exception {
249        injectProvider();
250        when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
251        doThrow(new RemoteException()).when(mRecommendationProvider)
252                .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
253                        anyInt());
254
255        final RecommendationResult result =
256                mNetworkScoreService.requestRecommendation(mRecommendationRequest);
257        assertNotNull(result);
258        assertEquals(mRecommendationRequest.getDefaultWifiConfig(),
259                result.getWifiConfiguration());
260    }
261
262    @Test
263    public void testRequestRecommendation_resultReturned() throws Exception {
264        injectProvider();
265        when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
266        final WifiConfiguration wifiConfiguration = new WifiConfiguration();
267        wifiConfiguration.SSID = "testRequestRecommendation_resultReturned_SSID";
268        wifiConfiguration.BSSID = "testRequestRecommendation_resultReturned_BSSID";
269        final RecommendationResult providerResult = RecommendationResult
270                .createConnectRecommendation(wifiConfiguration);
271        final Bundle bundle = new Bundle();
272        bundle.putParcelable(EXTRA_RECOMMENDATION_RESULT, providerResult);
273        doAnswer(invocation -> {
274            bundle.putInt(EXTRA_SEQUENCE, invocation.getArgumentAt(2, int.class));
275            invocation.getArgumentAt(1, IRemoteCallback.class).sendResult(bundle);
276            return null;
277        }).when(mRecommendationProvider)
278                .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
279                        anyInt());
280
281        final RecommendationResult result =
282                mNetworkScoreService.requestRecommendation(mRecommendationRequest);
283        assertNotNull(result);
284        assertEquals(providerResult.getWifiConfiguration().SSID,
285                result.getWifiConfiguration().SSID);
286        assertEquals(providerResult.getWifiConfiguration().BSSID,
287                result.getWifiConfiguration().BSSID);
288    }
289
290    @Test
291    public void testRequestRecommendationAsync_noPermission() throws Exception {
292        doThrow(new SecurityException()).when(mContext)
293                .enforceCallingOrSelfPermission(eq(permission.BROADCAST_NETWORK_PRIVILEGED),
294                        anyString());
295        try {
296            mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
297                    mRemoteCallback);
298            fail("BROADCAST_NETWORK_PRIVILEGED not enforced.");
299        } catch (SecurityException e) {
300            // expected
301        }
302    }
303
304    @Test
305    public void testRequestRecommendationAsync_providerNotConnected() throws Exception {
306        mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
307                mRemoteCallback);
308        boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
309        assertTrue(callbackRan);
310        verifyZeroInteractions(mRecommendationProvider);
311    }
312
313    @Test
314    public void testRequestRecommendationAsync_requestTimesOut() throws Exception {
315        injectProvider();
316        Settings.Global.putLong(mContentResolver,
317                Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, 1L);
318        mNetworkScoreService.refreshRecommendationRequestTimeoutMs();
319        mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
320                mRemoteCallback);
321        boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
322        assertTrue(callbackRan);
323        verify(mRecommendationProvider).requestRecommendation(eq(mRecommendationRequest),
324                isA(IRemoteCallback.Stub.class), anyInt());
325
326        assertTrue(mOnResultListener.receivedBundle.containsKey(EXTRA_RECOMMENDATION_RESULT));
327        RecommendationResult result =
328                mOnResultListener.receivedBundle.getParcelable(EXTRA_RECOMMENDATION_RESULT);
329        assertTrue(result.hasRecommendation());
330        assertEquals(mRecommendationRequest.getDefaultWifiConfig().SSID,
331                result.getWifiConfiguration().SSID);
332    }
333
334    @Test
335    public void testRequestRecommendationAsync_requestSucceeds() throws Exception {
336        injectProvider();
337        final Bundle bundle = new Bundle();
338        doAnswer(invocation -> {
339            invocation.getArgumentAt(1, IRemoteCallback.class).sendResult(bundle);
340            return null;
341        }).when(mRecommendationProvider)
342                .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
343                        anyInt());
344
345        mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
346                mRemoteCallback);
347        boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
348        assertTrue(callbackRan);
349        // If it's not the same instance then something else ran the callback.
350        assertSame(bundle, mOnResultListener.receivedBundle);
351    }
352
353    @Test
354    public void testRequestRecommendationAsync_requestThrowsRemoteException() throws Exception {
355        injectProvider();
356        doThrow(new RemoteException()).when(mRecommendationProvider)
357                .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
358                        anyInt());
359
360        mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
361                mRemoteCallback);
362        boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
363        assertTrue(callbackRan);
364    }
365
366    @Test
367    public void dispatchingContentObserver_nullUri() throws Exception {
368        NetworkScoreService.DispatchingContentObserver observer =
369                new NetworkScoreService.DispatchingContentObserver(mContext, null /*handler*/);
370
371        observer.onChange(false, null);
372        // nothing to assert or verify but since we passed in a null handler we'd see a NPE
373        // if it were interacted with.
374    }
375
376    @Test
377    public void dispatchingContentObserver_dispatchUri() throws Exception {
378        final CountDownHandler handler = new CountDownHandler(mHandlerThread.getLooper());
379        NetworkScoreService.DispatchingContentObserver observer =
380                new NetworkScoreService.DispatchingContentObserver(mContext, handler);
381        Uri uri = Uri.parse("content://settings/global/network_score_service_test");
382        int expectedWhat = 24;
383        observer.observe(uri, expectedWhat);
384
385        observer.onChange(false, uri);
386        final boolean msgHandled = handler.latch.await(3, TimeUnit.SECONDS);
387        assertTrue(msgHandled);
388        assertEquals(expectedWhat, handler.receivedWhat);
389    }
390
391    @Test
392    public void oneTimeCallback_multipleCallbacks() throws Exception {
393        NetworkScoreService.OneTimeCallback callback =
394                new NetworkScoreService.OneTimeCallback(mRemoteCallback);
395        callback.sendResult(null);
396        callback.sendResult(null);
397        assertEquals(1, mOnResultListener.resultCount);
398    }
399
400    @Test
401    public void testUpdateScores_notActiveScorer() {
402        bindToScorer(false /*callerIsScorer*/);
403
404        try {
405            mNetworkScoreService.updateScores(new ScoredNetwork[0]);
406            fail("SecurityException expected");
407        } catch (SecurityException e) {
408            // expected
409        }
410    }
411
412    @Test
413    public void testUpdateScores_oneRegisteredCache() throws RemoteException {
414        bindToScorer(true /*callerIsScorer*/);
415
416        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
417                mNetworkScoreCache, CACHE_FILTER_NONE);
418
419        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
420
421        verify(mNetworkScoreCache).updateScores(mScoredNetworkCaptor.capture());
422
423        assertEquals(1, mScoredNetworkCaptor.getValue().size());
424        assertEquals(SCORED_NETWORK, mScoredNetworkCaptor.getValue().get(0));
425    }
426
427    @Test
428    public void testUpdateScores_twoRegisteredCaches() throws RemoteException {
429        bindToScorer(true /*callerIsScorer*/);
430
431        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
432                mNetworkScoreCache, CACHE_FILTER_NONE);
433        mNetworkScoreService.registerNetworkScoreCache(
434                NetworkKey.TYPE_WIFI, mNetworkScoreCache2, CACHE_FILTER_NONE);
435
436        // updateScores should update both caches
437        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
438
439        verify(mNetworkScoreCache).updateScores(anyListOf(ScoredNetwork.class));
440        verify(mNetworkScoreCache2).updateScores(anyListOf(ScoredNetwork.class));
441
442        mNetworkScoreService.unregisterNetworkScoreCache(
443                NetworkKey.TYPE_WIFI, mNetworkScoreCache2);
444
445        // updateScores should only update the first cache since the 2nd has been unregistered
446        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
447
448        verify(mNetworkScoreCache, times(2)).updateScores(anyListOf(ScoredNetwork.class));
449
450        mNetworkScoreService.unregisterNetworkScoreCache(
451                NetworkKey.TYPE_WIFI, mNetworkScoreCache);
452
453        // updateScores should not update any caches since they are both unregistered
454        mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
455
456        // The register and unregister calls grab the binder from the score cache.
457        verify(mNetworkScoreCache, atLeastOnce()).asBinder();
458        verify(mNetworkScoreCache2, atLeastOnce()).asBinder();
459        verifyNoMoreInteractions(mNetworkScoreCache, mNetworkScoreCache2);
460    }
461
462    @Test
463    public void testClearScores_notActiveScorer_noRequestNetworkScoresPermission() {
464        bindToScorer(false /*callerIsScorer*/);
465        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
466            .thenReturn(PackageManager.PERMISSION_DENIED);
467        try {
468            mNetworkScoreService.clearScores();
469            fail("SecurityException expected");
470        } catch (SecurityException e) {
471            // expected
472        }
473    }
474
475    @Test
476    public void testClearScores_activeScorer_noRequestNetworkScoresPermission() {
477        bindToScorer(true /*callerIsScorer*/);
478        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
479            .thenReturn(PackageManager.PERMISSION_DENIED);
480
481        mNetworkScoreService.clearScores();
482    }
483
484    @Test
485    public void testClearScores_activeScorer() throws RemoteException {
486        bindToScorer(true /*callerIsScorer*/);
487
488        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
489                CACHE_FILTER_NONE);
490        mNetworkScoreService.clearScores();
491
492        verify(mNetworkScoreCache).clearScores();
493    }
494
495    @Test
496    public void testClearScores_notActiveScorer_hasRequestNetworkScoresPermission()
497            throws RemoteException {
498        bindToScorer(false /*callerIsScorer*/);
499        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
500                .thenReturn(PackageManager.PERMISSION_GRANTED);
501
502        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
503                CACHE_FILTER_NONE);
504        mNetworkScoreService.clearScores();
505
506        verify(mNetworkScoreCache).clearScores();
507    }
508
509    @Test
510    public void testSetActiveScorer_noScoreNetworksPermission() {
511        doThrow(new SecurityException()).when(mContext)
512                .enforceCallingOrSelfPermission(eq(permission.SCORE_NETWORKS), anyString());
513
514        try {
515            mNetworkScoreService.setActiveScorer(null);
516            fail("SecurityException expected");
517        } catch (SecurityException e) {
518            // expected
519        }
520    }
521
522    @Test
523    public void testDisableScoring_notActiveScorer_noRequestNetworkScoresPermission() {
524        bindToScorer(false /*callerIsScorer*/);
525        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
526                .thenReturn(PackageManager.PERMISSION_DENIED);
527
528        try {
529            mNetworkScoreService.disableScoring();
530            fail("SecurityException expected");
531        } catch (SecurityException e) {
532            // expected
533        }
534    }
535
536    @Test
537    public void testRegisterNetworkScoreCache_noRequestNetworkScoresPermission() {
538        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
539                eq(permission.REQUEST_NETWORK_SCORES), anyString());
540
541        try {
542            mNetworkScoreService.registerNetworkScoreCache(
543                NetworkKey.TYPE_WIFI, mNetworkScoreCache, CACHE_FILTER_NONE);
544            fail("SecurityException expected");
545        } catch (SecurityException e) {
546            // expected
547        }
548    }
549
550    @Test
551    public void testUnregisterNetworkScoreCache_noRequestNetworkScoresPermission() {
552        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
553                eq(permission.REQUEST_NETWORK_SCORES), anyString());
554
555        try {
556            mNetworkScoreService.unregisterNetworkScoreCache(
557                    NetworkKey.TYPE_WIFI, mNetworkScoreCache);
558            fail("SecurityException expected");
559        } catch (SecurityException e) {
560            // expected
561        }
562    }
563
564    @Test
565    public void testDump_noDumpPermission() {
566        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
567                eq(permission.DUMP), anyString());
568
569        try {
570            mNetworkScoreService.dump(
571                    new FileDescriptor(), new PrintWriter(new StringWriter()), new String[0]);
572            fail("SecurityException expected");
573        } catch (SecurityException e) {
574            // expected
575        }
576    }
577
578    @Test
579    public void testDump_doesNotCrash() {
580        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
581        StringWriter stringWriter = new StringWriter();
582
583        mNetworkScoreService.dump(
584                new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
585
586        assertFalse(stringWriter.toString().isEmpty());
587    }
588
589    @Test
590    public void testIsCallerActiveScorer_noBoundService() throws Exception {
591        mNetworkScoreService.systemRunning();
592
593        assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
594    }
595
596    @Test
597    public void testIsCallerActiveScorer_boundServiceIsNotCaller() throws Exception {
598        bindToScorer(false /*callerIsScorer*/);
599
600        assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
601    }
602
603    @Test
604    public void testIsCallerActiveScorer_boundServiceIsCaller() throws Exception {
605        bindToScorer(true /*callerIsScorer*/);
606
607        assertTrue(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
608    }
609
610    @Test
611    public void testGetActiveScorerPackage_notActive() throws Exception {
612        mNetworkScoreService.systemRunning();
613
614        assertNull(mNetworkScoreService.getActiveScorerPackage());
615    }
616
617    @Test
618    public void testGetActiveScorerPackage_active() throws Exception {
619        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
620        mNetworkScoreService.systemRunning();
621
622        assertEquals(NEW_SCORER.packageName, mNetworkScoreService.getActiveScorerPackage());
623    }
624
625    // "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
626    private void injectProvider() {
627        final ComponentName componentName = new ComponentName(NEW_SCORER.packageName,
628                NEW_SCORER.recommendationServiceClassName);
629        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
630        when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
631                isA(UserHandle.class))).thenAnswer(new Answer<Boolean>() {
632            @Override
633            public Boolean answer(InvocationOnMock invocation) throws Throwable {
634                IBinder mockBinder = mock(IBinder.class);
635                when(mockBinder.queryLocalInterface(anyString()))
636                        .thenReturn(mRecommendationProvider);
637                invocation.getArgumentAt(1, ServiceConnection.class)
638                        .onServiceConnected(componentName, mockBinder);
639                return true;
640            }
641        });
642        mNetworkScoreService.systemRunning();
643    }
644
645    private void bindToScorer(boolean callerIsScorer) {
646        final int callingUid = callerIsScorer ? Binder.getCallingUid() : 0;
647        NetworkScorerAppData appData = new NetworkScorerAppData(NEW_SCORER.packageName,
648                callingUid, NEW_SCORER.recommendationServiceClassName);
649        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
650        when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
651                isA(UserHandle.class))).thenReturn(true);
652        mNetworkScoreService.systemRunning();
653    }
654
655    private static class OnResultListener implements RemoteCallback.OnResultListener {
656        private final CountDownLatch countDownLatch = new CountDownLatch(1);
657        private int resultCount;
658        private Bundle receivedBundle;
659
660        @Override
661        public void onResult(Bundle result) {
662            countDownLatch.countDown();
663            resultCount++;
664            receivedBundle = result;
665        }
666    }
667
668    private static class CountDownHandler extends Handler {
669        CountDownLatch latch = new CountDownLatch(1);
670        int receivedWhat;
671
672        CountDownHandler(Looper looper) {
673            super(looper);
674        }
675
676        @Override
677        public void handleMessage(Message msg) {
678            latch.countDown();
679            receivedWhat = msg.what;
680        }
681    }
682}
683