blob: 6cca771539eaabcecafa20423e2591717401c968 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server;
import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
import static android.net.NetworkRecommendationProvider.EXTRA_SEQUENCE;
import static android.net.NetworkScoreManager.CACHE_FILTER_NONE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyListOf;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.Manifest.permission;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.INetworkRecommendationProvider;
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
import android.net.Uri;
import android.net.WifiKey;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiSsid;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import com.android.server.devicepolicy.MockUtils;
import com.google.android.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.UnaryOperator;
/**
* Tests for {@link NetworkScoreService}.
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
public class NetworkScoreServiceTest {
private static final String SSID = "ssid";
private static final String SSID_2 = "ssid_2";
private static final String SSID_3 = "ssid_3";
private static final String INVALID_BSSID = "invalid_bssid";
private static final ComponentName RECOMMENDATION_SERVICE_COMP =
new ComponentName("newPackageName", "newScoringServiceClass");
private static final String RECOMMENDATION_SERVICE_LABEL = "Test Recommendation Service";
private static final ComponentName USE_WIFI_ENABLE_ACTIVITY_COMP =
new ComponentName("useWifiPackageName", "enableUseWifiActivityClass");
private static final ScoredNetwork SCORED_NETWORK =
new ScoredNetwork(new NetworkKey(new WifiKey(quote(SSID), "00:00:00:00:00:00")),
null /* rssiCurve*/);
private static final ScoredNetwork SCORED_NETWORK_2 =
new ScoredNetwork(new NetworkKey(new WifiKey(quote(SSID_2), "00:00:00:00:00:00")),
null /* rssiCurve*/);
private static final NetworkScorerAppData NEW_SCORER = new NetworkScorerAppData(
1, RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
USE_WIFI_ENABLE_ACTIVITY_COMP);
@Mock private NetworkScorerAppManager mNetworkScorerAppManager;
@Mock private Context mContext;
@Mock private Resources mResources;
@Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2;
@Mock private IBinder mIBinder, mIBinder2;
@Mock private INetworkRecommendationProvider mRecommendationProvider;
@Mock private UnaryOperator<List<ScoredNetwork>> mCurrentNetworkFilter;
@Mock private UnaryOperator<List<ScoredNetwork>> mScanResultsFilter;
@Mock private WifiInfo mWifiInfo;
@Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor;
private ContentResolver mContentResolver;
private NetworkScoreService mNetworkScoreService;
private RecommendationRequest mRecommendationRequest;
private RemoteCallback mRemoteCallback;
private OnResultListener mOnResultListener;
private HandlerThread mHandlerThread;
private List<ScanResult> mScanResults;
private static String quote(String str) {
return String.format("\"%s\"", str);
}
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mNetworkScoreCache.asBinder()).thenReturn(mIBinder);
when(mNetworkScoreCache2.asBinder()).thenReturn(mIBinder2);
mContentResolver = InstrumentationRegistry.getContext().getContentResolver();
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getResources()).thenReturn(mResources);
when(mWifiInfo.getSSID()).thenReturn(SCORED_NETWORK.networkKey.wifiKey.ssid);
when(mWifiInfo.getBSSID()).thenReturn(SCORED_NETWORK.networkKey.wifiKey.bssid);
mHandlerThread = new HandlerThread("NetworkScoreServiceTest");
mHandlerThread.start();
mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager,
mHandlerThread.getLooper());
WifiConfiguration configuration = new WifiConfiguration();
configuration.SSID = "NetworkScoreServiceTest_SSID";
configuration.BSSID = "NetworkScoreServiceTest_BSSID";
mRecommendationRequest = new RecommendationRequest.Builder()
.setDefaultWifiConfig(configuration).build();
mOnResultListener = new OnResultListener();
mRemoteCallback = new RemoteCallback(mOnResultListener);
Settings.Global.putLong(mContentResolver,
Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, -1L);
mNetworkScoreService.refreshRecommendationRequestTimeoutMs();
populateScanResults();
}
private void populateScanResults() {
mScanResults = new ArrayList<>();
mScanResults.add(createScanResult(SSID, SCORED_NETWORK.networkKey.wifiKey.bssid));
mScanResults.add(createScanResult(SSID_2, SCORED_NETWORK_2.networkKey.wifiKey.bssid));
mScanResults.add(createScanResult(SSID_3, "10:10:00:00:10:10"));
}
private ScanResult createScanResult(String ssid, String bssid) {
ScanResult result = new ScanResult();
result.wifiSsid = WifiSsid.createFromAsciiEncoded(ssid);
result.BSSID = bssid;
return result;
}
@After
public void tearDown() throws Exception {
mHandlerThread.quitSafely();
}
@Test
public void testOnUserUnlocked() {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
mNetworkScoreService.onUserUnlocked(0);
verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
.setComponent(RECOMMENDATION_SERVICE_COMP)),
any(ServiceConnection.class),
eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
eq(UserHandle.SYSTEM));
}
@Test
public void testRequestScores_noPermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
anyString());
try {
mNetworkScoreService.requestScores(null);
fail("REQUEST_NETWORK_SCORES not enforced.");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testRequestScores_providerNotConnected() throws Exception {
assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0]));
verifyZeroInteractions(mRecommendationProvider);
}
@Test
public void testRequestScores_providerThrowsRemoteException() throws Exception {
injectProvider();
doThrow(new RemoteException()).when(mRecommendationProvider)
.requestScores(any(NetworkKey[].class));
assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0]));
}
@Test
public void testRequestScores_providerAvailable() throws Exception {
injectProvider();
final NetworkKey[] networks = new NetworkKey[0];
assertTrue(mNetworkScoreService.requestScores(networks));
verify(mRecommendationProvider).requestScores(networks);
}
@Test
public void testRequestRecommendation_noPermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
anyString());
try {
mNetworkScoreService.requestRecommendation(mRecommendationRequest);
fail("REQUEST_NETWORK_SCORES not enforced.");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testRequestRecommendation_mainThread() throws Exception {
when(mContext.getMainLooper()).thenReturn(Looper.myLooper());
try {
mNetworkScoreService.requestRecommendation(mRecommendationRequest);
fail("requestRecommendation run on main thread.");
} catch (RuntimeException e) {
// expected
}
}
@Test
public void testRequestRecommendation_providerNotConnected() throws Exception {
when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
final RecommendationResult result =
mNetworkScoreService.requestRecommendation(mRecommendationRequest);
assertNotNull(result);
assertEquals(mRecommendationRequest.getDefaultWifiConfig(),
result.getWifiConfiguration());
}
@Test
public void testRequestRecommendation_providerThrowsRemoteException() throws Exception {
injectProvider();
when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
doThrow(new RemoteException()).when(mRecommendationProvider)
.requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
anyInt());
final RecommendationResult result =
mNetworkScoreService.requestRecommendation(mRecommendationRequest);
assertNotNull(result);
assertEquals(mRecommendationRequest.getDefaultWifiConfig(),
result.getWifiConfiguration());
}
@Test
public void testRequestRecommendation_resultReturned() throws Exception {
injectProvider();
when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
final WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = "testRequestRecommendation_resultReturned_SSID";
wifiConfiguration.BSSID = "testRequestRecommendation_resultReturned_BSSID";
final RecommendationResult providerResult = RecommendationResult
.createConnectRecommendation(wifiConfiguration);
final Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_RECOMMENDATION_RESULT, providerResult);
doAnswer(invocation -> {
bundle.putInt(EXTRA_SEQUENCE, invocation.getArgument(2));
invocation.<IRemoteCallback>getArgument(1).sendResult(bundle);
return null;
}).when(mRecommendationProvider)
.requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
anyInt());
final RecommendationResult result =
mNetworkScoreService.requestRecommendation(mRecommendationRequest);
assertNotNull(result);
assertEquals(providerResult.getWifiConfiguration().SSID,
result.getWifiConfiguration().SSID);
assertEquals(providerResult.getWifiConfiguration().BSSID,
result.getWifiConfiguration().BSSID);
}
@Test
public void testRequestRecommendationAsync_noPermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
anyString());
try {
mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
mRemoteCallback);
fail("REQUEST_NETWORK_SCORES not enforced.");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testRequestRecommendationAsync_providerNotConnected() throws Exception {
mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
mRemoteCallback);
boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
assertTrue(callbackRan);
verifyZeroInteractions(mRecommendationProvider);
}
@Test
public void testRequestRecommendationAsync_requestTimesOut() throws Exception {
injectProvider();
Settings.Global.putLong(mContentResolver,
Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, 1L);
mNetworkScoreService.refreshRecommendationRequestTimeoutMs();
mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
mRemoteCallback);
boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
assertTrue(callbackRan);
verify(mRecommendationProvider).requestRecommendation(eq(mRecommendationRequest),
isA(IRemoteCallback.Stub.class), anyInt());
assertTrue(mOnResultListener.receivedBundle.containsKey(EXTRA_RECOMMENDATION_RESULT));
RecommendationResult result =
mOnResultListener.receivedBundle.getParcelable(EXTRA_RECOMMENDATION_RESULT);
assertTrue(result.hasRecommendation());
assertEquals(mRecommendationRequest.getDefaultWifiConfig().SSID,
result.getWifiConfiguration().SSID);
}
@Test
public void testRequestRecommendationAsync_requestSucceeds() throws Exception {
injectProvider();
final Bundle bundle = new Bundle();
doAnswer(invocation -> {
invocation.<IRemoteCallback>getArgument(1).sendResult(bundle);
return null;
}).when(mRecommendationProvider)
.requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
anyInt());
mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
mRemoteCallback);
boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
assertTrue(callbackRan);
// If it's not the same instance then something else ran the callback.
assertSame(bundle, mOnResultListener.receivedBundle);
}
@Test
public void testRequestRecommendationAsync_requestThrowsRemoteException() throws Exception {
injectProvider();
doThrow(new RemoteException()).when(mRecommendationProvider)
.requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
anyInt());
mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest,
mRemoteCallback);
boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS);
assertTrue(callbackRan);
}
@Test
public void dispatchingContentObserver_nullUri() throws Exception {
NetworkScoreService.DispatchingContentObserver observer =
new NetworkScoreService.DispatchingContentObserver(mContext, null /*handler*/);
observer.onChange(false, null);
// nothing to assert or verify but since we passed in a null handler we'd see a NPE
// if it were interacted with.
}
@Test
public void dispatchingContentObserver_dispatchUri() throws Exception {
final CountDownHandler handler = new CountDownHandler(mHandlerThread.getLooper());
NetworkScoreService.DispatchingContentObserver observer =
new NetworkScoreService.DispatchingContentObserver(mContext, handler);
Uri uri = Uri.parse("content://settings/global/network_score_service_test");
int expectedWhat = 24;
observer.observe(uri, expectedWhat);
observer.onChange(false, uri);
final boolean msgHandled = handler.latch.await(3, TimeUnit.SECONDS);
assertTrue(msgHandled);
assertEquals(expectedWhat, handler.receivedWhat);
}
@Test
public void oneTimeCallback_multipleCallbacks() throws Exception {
NetworkScoreService.OneTimeCallback callback =
new NetworkScoreService.OneTimeCallback(mRemoteCallback);
callback.sendResult(null);
callback.sendResult(null);
assertEquals(1, mOnResultListener.resultCount);
}
@Test
public void testUpdateScores_notActiveScorer() {
bindToScorer(false /*callerIsScorer*/);
try {
mNetworkScoreService.updateScores(new ScoredNetwork[0]);
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testUpdateScores_oneRegisteredCache() throws RemoteException {
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
mNetworkScoreCache, CACHE_FILTER_NONE);
mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
verify(mNetworkScoreCache).updateScores(mScoredNetworkCaptor.capture());
assertEquals(1, mScoredNetworkCaptor.getValue().size());
assertEquals(SCORED_NETWORK, mScoredNetworkCaptor.getValue().get(0));
}
@Test
public void testUpdateScores_twoRegisteredCaches() throws RemoteException {
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
mNetworkScoreCache, CACHE_FILTER_NONE);
mNetworkScoreService.registerNetworkScoreCache(
NetworkKey.TYPE_WIFI, mNetworkScoreCache2, CACHE_FILTER_NONE);
// updateScores should update both caches
mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
verify(mNetworkScoreCache).updateScores(anyListOf(ScoredNetwork.class));
verify(mNetworkScoreCache2).updateScores(anyListOf(ScoredNetwork.class));
mNetworkScoreService.unregisterNetworkScoreCache(
NetworkKey.TYPE_WIFI, mNetworkScoreCache2);
// updateScores should only update the first cache since the 2nd has been unregistered
mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
verify(mNetworkScoreCache, times(2)).updateScores(anyListOf(ScoredNetwork.class));
mNetworkScoreService.unregisterNetworkScoreCache(
NetworkKey.TYPE_WIFI, mNetworkScoreCache);
// updateScores should not update any caches since they are both unregistered
mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
// The register and unregister calls grab the binder from the score cache.
verify(mNetworkScoreCache, atLeastOnce()).asBinder();
verify(mNetworkScoreCache2, atLeastOnce()).asBinder();
verifyNoMoreInteractions(mNetworkScoreCache, mNetworkScoreCache2);
}
@Test
public void testClearScores_notActiveScorer_noRequestNetworkScoresPermission() {
bindToScorer(false /*callerIsScorer*/);
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
mNetworkScoreService.clearScores();
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testClearScores_activeScorer_noRequestNetworkScoresPermission() {
bindToScorer(true /*callerIsScorer*/);
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
mNetworkScoreService.clearScores();
}
@Test
public void testClearScores_activeScorer() throws RemoteException {
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
CACHE_FILTER_NONE);
mNetworkScoreService.clearScores();
verify(mNetworkScoreCache).clearScores();
}
@Test
public void testClearScores_notActiveScorer_hasRequestNetworkScoresPermission()
throws RemoteException {
bindToScorer(false /*callerIsScorer*/);
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_GRANTED);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
CACHE_FILTER_NONE);
mNetworkScoreService.clearScores();
verify(mNetworkScoreCache).clearScores();
}
@Test
public void testSetActiveScorer_noRequestNetworkScoresPermission() {
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
mNetworkScoreService.setActiveScorer(null);
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testDisableScoring_notActiveScorer_noRequestNetworkScoresPermission() {
bindToScorer(false /*callerIsScorer*/);
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
mNetworkScoreService.disableScoring();
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testRegisterNetworkScoreCache_noRequestNetworkScoresPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(permission.REQUEST_NETWORK_SCORES), anyString());
try {
mNetworkScoreService.registerNetworkScoreCache(
NetworkKey.TYPE_WIFI, mNetworkScoreCache, CACHE_FILTER_NONE);
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testUnregisterNetworkScoreCache_noRequestNetworkScoresPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(permission.REQUEST_NETWORK_SCORES), anyString());
try {
mNetworkScoreService.unregisterNetworkScoreCache(
NetworkKey.TYPE_WIFI, mNetworkScoreCache);
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testDump_noDumpPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(permission.DUMP), anyString());
try {
mNetworkScoreService.dump(
new FileDescriptor(), new PrintWriter(new StringWriter()), new String[0]);
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testDump_doesNotCrash() {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
StringWriter stringWriter = new StringWriter();
mNetworkScoreService.dump(
new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
assertFalse(stringWriter.toString().isEmpty());
}
@Test
public void testIsCallerActiveScorer_noBoundService() throws Exception {
mNetworkScoreService.onUserUnlocked(0);
assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
}
@Test
public void testIsCallerActiveScorer_boundServiceIsNotCaller() throws Exception {
bindToScorer(false /*callerIsScorer*/);
assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
}
@Test
public void testIsCallerActiveScorer_boundServiceIsCaller() throws Exception {
bindToScorer(true /*callerIsScorer*/);
assertTrue(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
}
@Test
public void testGetActiveScorerPackage_notActive() throws Exception {
mNetworkScoreService.onUserUnlocked(0);
assertNull(mNetworkScoreService.getActiveScorerPackage());
}
@Test
public void testGetActiveScorerPackage_active() throws Exception {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
mNetworkScoreService.onUserUnlocked(0);
assertEquals(NEW_SCORER.getRecommendationServicePackageName(),
mNetworkScoreService.getActiveScorerPackage());
assertEquals(NEW_SCORER.getEnableUseOpenWifiActivity(),
mNetworkScoreService.getActiveScorer().getEnableUseOpenWifiActivity());
}
@Test
public void testCacheUpdatingConsumer_nullFilter() throws Exception {
List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
NetworkScoreService.FilteringCacheUpdatingConsumer consumer =
new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
new ArrayList<>(scoredNetworkList), NetworkKey.TYPE_WIFI,
mCurrentNetworkFilter, mScanResultsFilter);
consumer.accept(mNetworkScoreCache, null /*cookie*/);
verify(mNetworkScoreCache).updateScores(scoredNetworkList);
verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
}
@Test
public void testCacheUpdatingConsumer_noneFilter() throws Exception {
List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
NetworkScoreService.FilteringCacheUpdatingConsumer
consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
new ArrayList<>(scoredNetworkList),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
verify(mNetworkScoreCache).updateScores(scoredNetworkList);
verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
}
@Test
public void testCacheUpdatingConsumer_unknownFilter() throws Exception {
List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
NetworkScoreService.FilteringCacheUpdatingConsumer
consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
new ArrayList<>(scoredNetworkList),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
consumer.accept(mNetworkScoreCache, -1 /*cookie*/);
verify(mNetworkScoreCache).updateScores(scoredNetworkList);
verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
}
@Test
public void testCacheUpdatingConsumer_nonIntFilter() throws Exception {
List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK);
NetworkScoreService.FilteringCacheUpdatingConsumer
consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
new ArrayList<>(scoredNetworkList),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
consumer.accept(mNetworkScoreCache, "not an int" /*cookie*/);
verify(mNetworkScoreCache).updateScores(scoredNetworkList);
verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
}
@Test
public void testCacheUpdatingConsumer_emptyScoreList() throws Exception {
NetworkScoreService.FilteringCacheUpdatingConsumer
consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
Collections.emptyList(),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
verifyZeroInteractions(mNetworkScoreCache, mCurrentNetworkFilter, mScanResultsFilter);
}
@Test
public void testCacheUpdatingConsumer_currentNetworkFilter() throws Exception {
List<ScoredNetwork> scoredNetworkList =
Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
NetworkScoreService.FilteringCacheUpdatingConsumer
consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
new ArrayList<>(scoredNetworkList),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
filteredList.remove(SCORED_NETWORK);
when(mCurrentNetworkFilter.apply(scoredNetworkList)).thenReturn(filteredList);
consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
verify(mNetworkScoreCache).updateScores(filteredList);
verifyZeroInteractions(mScanResultsFilter);
}
@Test
public void testCacheUpdatingConsumer_scanResultsFilter() throws Exception {
List<ScoredNetwork> scoredNetworkList =
Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
NetworkScoreService.FilteringCacheUpdatingConsumer
consumer = new NetworkScoreService.FilteringCacheUpdatingConsumer(mContext,
new ArrayList<>(scoredNetworkList),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
filteredList.remove(SCORED_NETWORK);
when(mScanResultsFilter.apply(scoredNetworkList)).thenReturn(filteredList);
consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);
verify(mNetworkScoreCache).updateScores(filteredList);
verifyZeroInteractions(mCurrentNetworkFilter);
}
@Test
public void testCurrentNetworkScoreCacheFilter_nullWifiInfo() throws Exception {
NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> null /*WifiInfo*/);
List<ScoredNetwork> actualList =
cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
assertTrue(actualList.isEmpty());
}
@Test
public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_nullSsid() throws Exception {
when(mWifiInfo.getSSID()).thenReturn(null);
NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
List<ScoredNetwork> actualList =
cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
assertTrue(actualList.isEmpty());
}
@Test
public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_noneSsid() throws Exception {
when(mWifiInfo.getSSID()).thenReturn(WifiSsid.NONE);
NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
List<ScoredNetwork> actualList =
cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
assertTrue(actualList.isEmpty());
}
@Test
public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_emptySsid() throws Exception {
when(mWifiInfo.getSSID()).thenReturn("");
NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
List<ScoredNetwork> actualList =
cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
assertTrue(actualList.isEmpty());
}
@Test
public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_invalidBssid() throws Exception {
when(mWifiInfo.getBSSID()).thenReturn(INVALID_BSSID);
NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
List<ScoredNetwork> actualList =
cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
assertTrue(actualList.isEmpty());
}
@Test
public void testCurrentNetworkScoreCacheFilter_scoreFiltered() throws Exception {
NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
List<ScoredNetwork> actualList =
cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
List<ScoredNetwork> expectedList = Collections.singletonList(SCORED_NETWORK);
assertEquals(expectedList, actualList);
}
@Test
public void testCurrentNetworkScoreCacheFilter_currentNetworkNotInList() throws Exception {
when(mWifiInfo.getSSID()).thenReturn("\"notInList\"");
NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter =
new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo);
List<ScoredNetwork> actualList =
cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
assertTrue(actualList.isEmpty());
}
@Test
public void testScanResultsScoreCacheFilter_emptyScanResults() throws Exception {
NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
new NetworkScoreService.ScanResultsScoreCacheFilter(Collections::emptyList);
List<ScoredNetwork> actualList =
cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
assertTrue(actualList.isEmpty());
}
@Test
public void testScanResultsScoreCacheFilter_invalidScanResults() throws Exception {
List<ScanResult> invalidScanResults = Lists.newArrayList(
new ScanResult(),
createScanResult("", SCORED_NETWORK.networkKey.wifiKey.bssid),
createScanResult(WifiSsid.NONE, SCORED_NETWORK.networkKey.wifiKey.bssid),
createScanResult(SSID, null),
createScanResult(SSID, INVALID_BSSID)
);
NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
new NetworkScoreService.ScanResultsScoreCacheFilter(() -> invalidScanResults);
List<ScoredNetwork> actualList =
cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2));
assertTrue(actualList.isEmpty());
}
@Test
public void testScanResultsScoreCacheFilter_scoresFiltered() throws Exception {
NetworkScoreService.ScanResultsScoreCacheFilter cacheFilter =
new NetworkScoreService.ScanResultsScoreCacheFilter(() -> mScanResults);
ScoredNetwork unmatchedScore =
new ScoredNetwork(new NetworkKey(new WifiKey(quote("newSsid"),
"00:00:00:00:00:00")), null /* rssiCurve*/);
List<ScoredNetwork> actualList =
cacheFilter.apply(Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2,
unmatchedScore));
List<ScoredNetwork> expectedList = Lists.newArrayList(SCORED_NETWORK, SCORED_NETWORK_2);
assertEquals(expectedList, actualList);
}
@Test
public void testGetActiveScorer_notConnected_canRequestScores() throws Exception {
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_GRANTED);
assertNull(mNetworkScoreService.getActiveScorer());
}
@Test
public void testGetActiveScorer_notConnected_canNotRequestScores() throws Exception {
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
mNetworkScoreService.getActiveScorer();
fail("SecurityException expected.");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testGetActiveScorer_connected_canRequestScores()
throws Exception {
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_GRANTED);
NetworkScorerAppData expectedAppData = new NetworkScorerAppData(Binder.getCallingUid(),
RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
USE_WIFI_ENABLE_ACTIVITY_COMP);
bindToScorer(expectedAppData);
assertEquals(expectedAppData, mNetworkScoreService.getActiveScorer());
}
@Test
public void testGetActiveScorer_connected_canNotRequestScores()
throws Exception {
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
bindToScorer(false);
try {
mNetworkScoreService.getActiveScorer();
fail("SecurityException expected.");
} catch (SecurityException e) {
// expected
}
}
// "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
private void injectProvider() {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
isA(UserHandle.class))).thenAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
IBinder mockBinder = mock(IBinder.class);
when(mockBinder.queryLocalInterface(anyString()))
.thenReturn(mRecommendationProvider);
invocation.<ServiceConnection>getArgument(1)
.onServiceConnected(NEW_SCORER.getRecommendationServiceComponent(),
mockBinder);
return true;
}
});
mNetworkScoreService.onUserUnlocked(0);
}
private void bindToScorer(boolean callerIsScorer) {
final int callingUid = callerIsScorer ? Binder.getCallingUid() : Binder.getCallingUid() + 1;
NetworkScorerAppData appData = new NetworkScorerAppData(callingUid,
RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
USE_WIFI_ENABLE_ACTIVITY_COMP);
bindToScorer(appData);
}
private void bindToScorer(NetworkScorerAppData appData) {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
isA(UserHandle.class))).thenReturn(true);
mNetworkScoreService.onUserUnlocked(0);
}
private static class OnResultListener implements RemoteCallback.OnResultListener {
private final CountDownLatch countDownLatch = new CountDownLatch(1);
private int resultCount;
private Bundle receivedBundle;
@Override
public void onResult(Bundle result) {
countDownLatch.countDown();
resultCount++;
receivedBundle = result;
}
}
private static class CountDownHandler extends Handler {
CountDownLatch latch = new CountDownLatch(1);
int receivedWhat;
CountDownHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
latch.countDown();
receivedWhat = msg.what;
}
}
}