blob: 50911cb32ddf3f5e1574fffd78436c8cea34c28b [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.NetworkScoreManager.CACHE_FILTER_NONE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
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.Mockito.atLeastOnce;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
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.INetworkScoreCache;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppManager;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.net.ScoredNetwork;
import android.net.WifiKey;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import com.android.internal.R;
import com.android.server.devicepolicy.MockUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
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.Mockito;
import org.mockito.MockitoAnnotations;
/**
* Tests for {@link NetworkScoreService}.
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
public class NetworkScoreServiceTest {
private static final ScoredNetwork SCORED_NETWORK =
new ScoredNetwork(new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00")),
null /* rssiCurve*/);
private static final NetworkScorerAppData PREV_SCORER = new NetworkScorerAppData(
"prevPackageName", 0, "prevScorerName", null /* configurationActivityClassName */,
"prevScoringServiceClass");
private static final NetworkScorerAppData NEW_SCORER = new NetworkScorerAppData(
"newPackageName", 1, "newScorerName", null /* configurationActivityClassName */,
"newScoringServiceClass");
@Mock private PackageManager mPackageManager;
@Mock private NetworkScorerAppManager mNetworkScorerAppManager;
@Mock private Context mContext;
@Mock private Resources mResources;
@Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2;
@Mock private IBinder mIBinder, mIBinder2;
@Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor;
private ContentResolver mContentResolver;
private NetworkScoreService mNetworkScoreService;
@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);
mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager);
}
@Test
public void testSystemReady_networkScorerProvisioned() throws Exception {
Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 1);
mNetworkScoreService.systemReady();
verify(mNetworkScorerAppManager, never()).setActiveScorer(anyString());
}
@Test
public void testSystemReady_networkScorerNotProvisioned_defaultScorer() throws Exception {
Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 0);
when(mResources.getString(R.string.config_defaultNetworkScorerPackageName))
.thenReturn(NEW_SCORER.mPackageName);
mNetworkScoreService.systemReady();
verify(mNetworkScorerAppManager).setActiveScorer(NEW_SCORER.mPackageName);
assertEquals(1,
Settings.Global.getInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED));
}
@Test
public void testSystemReady_networkScorerNotProvisioned_noDefaultScorer() throws Exception {
Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 0);
when(mResources.getString(R.string.config_defaultNetworkScorerPackageName))
.thenReturn(null);
mNetworkScoreService.systemReady();
verify(mNetworkScorerAppManager, never()).setActiveScorer(anyString());
assertEquals(1,
Settings.Global.getInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED));
}
@Test
public void testSystemRunning() {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
mNetworkScoreService.systemRunning();
verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent(
new ComponentName(NEW_SCORER.mPackageName, NEW_SCORER.mScoringServiceClassName))),
any(ServiceConnection.class),
eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
eq(UserHandle.SYSTEM));
}
@Test
public void testUpdateScores_notActiveScorer() {
when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
try {
mNetworkScoreService.updateScores(new ScoredNetwork[0]);
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testUpdateScores_oneRegisteredCache() throws RemoteException {
when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
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 {
when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
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_noBroadcastNetworkPermission() {
when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
mNetworkScoreService.clearScores();
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testClearScores_activeScorer_noBroadcastNetworkPermission() {
when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
.thenReturn(PackageManager.PERMISSION_DENIED);
mNetworkScoreService.clearScores();
}
@Test
public void testClearScores_activeScorer() throws RemoteException {
when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
CACHE_FILTER_NONE);
mNetworkScoreService.clearScores();
verify(mNetworkScoreCache).clearScores();
}
@Test
public void testClearScores_notActiveScorer_hasBroadcastNetworkPermission()
throws RemoteException {
when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
.thenReturn(PackageManager.PERMISSION_GRANTED);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
CACHE_FILTER_NONE);
mNetworkScoreService.clearScores();
verify(mNetworkScoreCache).clearScores();
}
@Test
public void testSetActiveScorer_noScoreNetworksPermission() {
doThrow(new SecurityException()).when(mContext)
.enforceCallingOrSelfPermission(eq(permission.SCORE_NETWORKS), anyString());
try {
mNetworkScoreService.setActiveScorer(null);
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testSetActiveScorer_failure() throws RemoteException {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER);
when(mNetworkScorerAppManager.setActiveScorer(NEW_SCORER.mPackageName)).thenReturn(false);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
CACHE_FILTER_NONE);
boolean success = mNetworkScoreService.setActiveScorer(NEW_SCORER.mPackageName);
assertFalse(success);
verify(mNetworkScoreCache).clearScores();
verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent(
new ComponentName(PREV_SCORER.mPackageName, PREV_SCORER.mScoringServiceClassName))),
any(ServiceConnection.class),
eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
eq(UserHandle.SYSTEM));
}
@Test
public void testSetActiveScorer_success() throws RemoteException {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, NEW_SCORER);
when(mNetworkScorerAppManager.setActiveScorer(NEW_SCORER.mPackageName)).thenReturn(true);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
CACHE_FILTER_NONE);
boolean success = mNetworkScoreService.setActiveScorer(NEW_SCORER.mPackageName);
assertTrue(success);
verify(mNetworkScoreCache).clearScores();
verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent(
new ComponentName(NEW_SCORER.mPackageName, NEW_SCORER.mScoringServiceClassName))),
any(ServiceConnection.class),
eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
eq(UserHandle.SYSTEM));
verify(mContext, times(2)).sendBroadcastAsUser(
MockUtils.checkIntentAction(NetworkScoreManager.ACTION_SCORER_CHANGED),
eq(UserHandle.SYSTEM));
}
@Test
public void testDisableScoring_notActiveScorer_noBroadcastNetworkPermission() {
when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
mNetworkScoreService.disableScoring();
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testDisableScoring_activeScorer() throws RemoteException {
when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, null);
when(mNetworkScorerAppManager.setActiveScorer(null)).thenReturn(true);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
CACHE_FILTER_NONE);
mNetworkScoreService.disableScoring();
verify(mNetworkScoreCache).clearScores();
verify(mContext).sendBroadcastAsUser(
MockUtils.checkIntent(new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED)
.setPackage(PREV_SCORER.mPackageName)),
eq(UserHandle.SYSTEM));
verify(mContext, never()).bindServiceAsUser(any(Intent.class),
any(ServiceConnection.class), anyInt(), any(UserHandle.class));
}
@Test
public void testDisableScoring_notActiveScorer_hasBroadcastNetworkPermission()
throws RemoteException {
when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
.thenReturn(PackageManager.PERMISSION_GRANTED);
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, null);
when(mNetworkScorerAppManager.setActiveScorer(null)).thenReturn(true);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
CACHE_FILTER_NONE);
mNetworkScoreService.disableScoring();
verify(mNetworkScoreCache).clearScores();
verify(mContext).sendBroadcastAsUser(
MockUtils.checkIntent(new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED)
.setPackage(PREV_SCORER.mPackageName)),
eq(UserHandle.SYSTEM));
verify(mContext, never()).bindServiceAsUser(any(Intent.class),
any(ServiceConnection.class), anyInt(), any(UserHandle.class));
}
@Test
public void testRegisterNetworkScoreCache_noBroadcastNetworkPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString());
try {
mNetworkScoreService.registerNetworkScoreCache(
NetworkKey.TYPE_WIFI, mNetworkScoreCache, CACHE_FILTER_NONE);
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
}
}
@Test
public void testUnregisterNetworkScoreCache_noBroadcastNetworkPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
eq(permission.BROADCAST_NETWORK_PRIVILEGED), 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());
}
}