NetworkScoreServiceTest.java revision 8f5521aa679f21bc106dec90ecf21cd2283747a7
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.assertTrue; 27import static junit.framework.Assert.fail; 28 29import static org.mockito.Matchers.any; 30import static org.mockito.Matchers.anyInt; 31import static org.mockito.Matchers.anyListOf; 32import static org.mockito.Matchers.anyString; 33import static org.mockito.Matchers.eq; 34import static org.mockito.Matchers.isA; 35import static org.mockito.Mockito.atLeastOnce; 36import static org.mockito.Mockito.doAnswer; 37import static org.mockito.Mockito.doThrow; 38import static org.mockito.Mockito.mock; 39import static org.mockito.Mockito.times; 40import static org.mockito.Mockito.verify; 41import static org.mockito.Mockito.verifyNoMoreInteractions; 42import static org.mockito.Mockito.verifyZeroInteractions; 43import static org.mockito.Mockito.when; 44 45import android.Manifest.permission; 46import android.content.ComponentName; 47import android.content.ContentResolver; 48import android.content.Context; 49import android.content.Intent; 50import android.content.ServiceConnection; 51import android.content.pm.PackageManager; 52import android.content.res.Resources; 53import android.net.INetworkRecommendationProvider; 54import android.net.INetworkScoreCache; 55import android.net.NetworkKey; 56import android.net.NetworkScorerAppManager; 57import android.net.NetworkScorerAppManager.NetworkScorerAppData; 58import android.net.RecommendationRequest; 59import android.net.RecommendationResult; 60import android.net.ScoredNetwork; 61import android.net.WifiKey; 62import android.net.wifi.WifiConfiguration; 63import android.os.Bundle; 64import android.os.IBinder; 65import android.os.IRemoteCallback; 66import android.os.Looper; 67import android.os.RemoteException; 68import android.os.UserHandle; 69import android.support.test.InstrumentationRegistry; 70import android.support.test.filters.MediumTest; 71import android.support.test.runner.AndroidJUnit4; 72 73import com.android.server.devicepolicy.MockUtils; 74 75import org.junit.Before; 76import org.junit.Test; 77import org.junit.runner.RunWith; 78import org.mockito.ArgumentCaptor; 79import org.mockito.Captor; 80import org.mockito.Mock; 81import org.mockito.MockitoAnnotations; 82import org.mockito.invocation.InvocationOnMock; 83import org.mockito.stubbing.Answer; 84 85import java.io.FileDescriptor; 86import java.io.PrintWriter; 87import java.io.StringWriter; 88import java.util.List; 89 90/** 91 * Tests for {@link NetworkScoreService}. 92 */ 93@RunWith(AndroidJUnit4.class) 94@MediumTest 95public class NetworkScoreServiceTest { 96 private static final ScoredNetwork SCORED_NETWORK = 97 new ScoredNetwork(new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00")), 98 null /* rssiCurve*/); 99 private static final NetworkScorerAppData NEW_SCORER = 100 new NetworkScorerAppData("newPackageName", 1, "newScoringServiceClass"); 101 102 @Mock private PackageManager mPackageManager; 103 @Mock private NetworkScorerAppManager mNetworkScorerAppManager; 104 @Mock private Context mContext; 105 @Mock private Resources mResources; 106 @Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2; 107 @Mock private IBinder mIBinder, mIBinder2; 108 @Mock private INetworkRecommendationProvider mRecommendationProvider; 109 @Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor; 110 111 private ContentResolver mContentResolver; 112 private NetworkScoreService mNetworkScoreService; 113 private RecommendationRequest mRecommendationRequest; 114 115 @Before 116 public void setUp() throws Exception { 117 MockitoAnnotations.initMocks(this); 118 when(mNetworkScoreCache.asBinder()).thenReturn(mIBinder); 119 when(mNetworkScoreCache2.asBinder()).thenReturn(mIBinder2); 120 mContentResolver = InstrumentationRegistry.getContext().getContentResolver(); 121 when(mContext.getContentResolver()).thenReturn(mContentResolver); 122 when(mContext.getResources()).thenReturn(mResources); 123 mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager); 124 WifiConfiguration configuration = new WifiConfiguration(); 125 configuration.SSID = "NetworkScoreServiceTest_SSID"; 126 configuration.BSSID = "NetworkScoreServiceTest_BSSID"; 127 mRecommendationRequest = new RecommendationRequest.Builder() 128 .setCurrentRecommendedWifiConfig(configuration).build(); 129 } 130 131 @Test 132 public void testSystemRunning() { 133 when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER); 134 135 mNetworkScoreService.systemRunning(); 136 137 verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent( 138 new ComponentName(NEW_SCORER.packageName, 139 NEW_SCORER.recommendationServiceClassName))), 140 any(ServiceConnection.class), 141 eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE), 142 eq(UserHandle.SYSTEM)); 143 } 144 145 @Test 146 public void testRequestScores_noPermission() throws Exception { 147 doThrow(new SecurityException()).when(mContext) 148 .enforceCallingOrSelfPermission(eq(permission.BROADCAST_NETWORK_PRIVILEGED), 149 anyString()); 150 try { 151 mNetworkScoreService.requestScores(null); 152 fail("BROADCAST_NETWORK_PRIVILEGED not enforced."); 153 } catch (SecurityException e) { 154 // expected 155 } 156 } 157 158 @Test 159 public void testRequestScores_providerNotConnected() throws Exception { 160 assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0])); 161 verifyZeroInteractions(mRecommendationProvider); 162 } 163 164 @Test 165 public void testRequestScores_providerThrowsRemoteException() throws Exception { 166 injectProvider(); 167 doThrow(new RemoteException()).when(mRecommendationProvider) 168 .requestScores(any(NetworkKey[].class)); 169 170 assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0])); 171 } 172 173 @Test 174 public void testRequestScores_providerAvailable() throws Exception { 175 injectProvider(); 176 177 final NetworkKey[] networks = new NetworkKey[0]; 178 assertTrue(mNetworkScoreService.requestScores(networks)); 179 verify(mRecommendationProvider).requestScores(networks); 180 } 181 182 @Test 183 public void testRequestRecommendation_noPermission() throws Exception { 184 doThrow(new SecurityException()).when(mContext) 185 .enforceCallingOrSelfPermission(eq(permission.BROADCAST_NETWORK_PRIVILEGED), 186 anyString()); 187 try { 188 mNetworkScoreService.requestRecommendation(mRecommendationRequest); 189 fail("BROADCAST_NETWORK_PRIVILEGED not enforced."); 190 } catch (SecurityException e) { 191 // expected 192 } 193 } 194 195 @Test 196 public void testRequestRecommendation_mainThread() throws Exception { 197 when(mContext.getMainLooper()).thenReturn(Looper.myLooper()); 198 try { 199 mNetworkScoreService.requestRecommendation(mRecommendationRequest); 200 fail("requestRecommendation run on main thread."); 201 } catch (RuntimeException e) { 202 // expected 203 } 204 } 205 206 @Test 207 public void testRequestRecommendation_providerNotConnected() throws Exception { 208 when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper()); 209 210 final RecommendationResult result = 211 mNetworkScoreService.requestRecommendation(mRecommendationRequest); 212 assertNotNull(result); 213 assertEquals(mRecommendationRequest.getCurrentSelectedConfig(), 214 result.getWifiConfiguration()); 215 } 216 217 @Test 218 public void testRequestRecommendation_providerThrowsRemoteException() throws Exception { 219 injectProvider(); 220 when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper()); 221 doThrow(new RemoteException()).when(mRecommendationProvider) 222 .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class), 223 anyInt()); 224 225 final RecommendationResult result = 226 mNetworkScoreService.requestRecommendation(mRecommendationRequest); 227 assertNotNull(result); 228 assertEquals(mRecommendationRequest.getCurrentSelectedConfig(), 229 result.getWifiConfiguration()); 230 } 231 232 @Test 233 public void testRequestRecommendation_resultReturned() throws Exception { 234 injectProvider(); 235 when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper()); 236 final WifiConfiguration wifiConfiguration = new WifiConfiguration(); 237 wifiConfiguration.SSID = "testRequestRecommendation_resultReturned_SSID"; 238 wifiConfiguration.BSSID = "testRequestRecommendation_resultReturned_BSSID"; 239 final RecommendationResult providerResult = RecommendationResult 240 .createConnectRecommendation(wifiConfiguration); 241 final Bundle bundle = new Bundle(); 242 bundle.putParcelable(EXTRA_RECOMMENDATION_RESULT, providerResult); 243 doAnswer(invocation -> { 244 bundle.putInt(EXTRA_SEQUENCE, invocation.getArgumentAt(2, int.class)); 245 invocation.getArgumentAt(1, IRemoteCallback.class).sendResult(bundle); 246 return null; 247 }).when(mRecommendationProvider) 248 .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class), 249 anyInt()); 250 251 final RecommendationResult result = 252 mNetworkScoreService.requestRecommendation(mRecommendationRequest); 253 assertNotNull(result); 254 assertEquals(providerResult.getWifiConfiguration().SSID, 255 result.getWifiConfiguration().SSID); 256 assertEquals(providerResult.getWifiConfiguration().BSSID, 257 result.getWifiConfiguration().BSSID); 258 } 259 260 @Test 261 public void testUpdateScores_notActiveScorer() { 262 when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); 263 264 try { 265 mNetworkScoreService.updateScores(new ScoredNetwork[0]); 266 fail("SecurityException expected"); 267 } catch (SecurityException e) { 268 // expected 269 } 270 } 271 272 @Test 273 public void testUpdateScores_oneRegisteredCache() throws RemoteException { 274 when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true); 275 276 mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, 277 mNetworkScoreCache, CACHE_FILTER_NONE); 278 279 mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK}); 280 281 verify(mNetworkScoreCache).updateScores(mScoredNetworkCaptor.capture()); 282 283 assertEquals(1, mScoredNetworkCaptor.getValue().size()); 284 assertEquals(SCORED_NETWORK, mScoredNetworkCaptor.getValue().get(0)); 285 } 286 287 @Test 288 public void testUpdateScores_twoRegisteredCaches() throws RemoteException { 289 when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true); 290 291 mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, 292 mNetworkScoreCache, CACHE_FILTER_NONE); 293 mNetworkScoreService.registerNetworkScoreCache( 294 NetworkKey.TYPE_WIFI, mNetworkScoreCache2, CACHE_FILTER_NONE); 295 296 // updateScores should update both caches 297 mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK}); 298 299 verify(mNetworkScoreCache).updateScores(anyListOf(ScoredNetwork.class)); 300 verify(mNetworkScoreCache2).updateScores(anyListOf(ScoredNetwork.class)); 301 302 mNetworkScoreService.unregisterNetworkScoreCache( 303 NetworkKey.TYPE_WIFI, mNetworkScoreCache2); 304 305 // updateScores should only update the first cache since the 2nd has been unregistered 306 mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK}); 307 308 verify(mNetworkScoreCache, times(2)).updateScores(anyListOf(ScoredNetwork.class)); 309 310 mNetworkScoreService.unregisterNetworkScoreCache( 311 NetworkKey.TYPE_WIFI, mNetworkScoreCache); 312 313 // updateScores should not update any caches since they are both unregistered 314 mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK}); 315 316 // The register and unregister calls grab the binder from the score cache. 317 verify(mNetworkScoreCache, atLeastOnce()).asBinder(); 318 verify(mNetworkScoreCache2, atLeastOnce()).asBinder(); 319 verifyNoMoreInteractions(mNetworkScoreCache, mNetworkScoreCache2); 320 } 321 322 @Test 323 public void testClearScores_notActiveScorer_noBroadcastNetworkPermission() { 324 when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); 325 when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) 326 .thenReturn(PackageManager.PERMISSION_DENIED); 327 try { 328 mNetworkScoreService.clearScores(); 329 fail("SecurityException expected"); 330 } catch (SecurityException e) { 331 // expected 332 } 333 } 334 335 @Test 336 public void testClearScores_activeScorer_noBroadcastNetworkPermission() { 337 when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true); 338 when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) 339 .thenReturn(PackageManager.PERMISSION_DENIED); 340 341 mNetworkScoreService.clearScores(); 342 } 343 344 @Test 345 public void testClearScores_activeScorer() throws RemoteException { 346 when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true); 347 348 mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache, 349 CACHE_FILTER_NONE); 350 mNetworkScoreService.clearScores(); 351 352 verify(mNetworkScoreCache).clearScores(); 353 } 354 355 @Test 356 public void testClearScores_notActiveScorer_hasBroadcastNetworkPermission() 357 throws RemoteException { 358 when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); 359 when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) 360 .thenReturn(PackageManager.PERMISSION_GRANTED); 361 362 mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache, 363 CACHE_FILTER_NONE); 364 mNetworkScoreService.clearScores(); 365 366 verify(mNetworkScoreCache).clearScores(); 367 } 368 369 @Test 370 public void testSetActiveScorer_noScoreNetworksPermission() { 371 doThrow(new SecurityException()).when(mContext) 372 .enforceCallingOrSelfPermission(eq(permission.SCORE_NETWORKS), anyString()); 373 374 try { 375 mNetworkScoreService.setActiveScorer(null); 376 fail("SecurityException expected"); 377 } catch (SecurityException e) { 378 // expected 379 } 380 } 381 382 @Test 383 public void testDisableScoring_notActiveScorer_noBroadcastNetworkPermission() { 384 when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); 385 when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) 386 .thenReturn(PackageManager.PERMISSION_DENIED); 387 388 try { 389 mNetworkScoreService.disableScoring(); 390 fail("SecurityException expected"); 391 } catch (SecurityException e) { 392 // expected 393 } 394 } 395 396 @Test 397 public void testRegisterNetworkScoreCache_noBroadcastNetworkPermission() { 398 doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( 399 eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString()); 400 401 try { 402 mNetworkScoreService.registerNetworkScoreCache( 403 NetworkKey.TYPE_WIFI, mNetworkScoreCache, CACHE_FILTER_NONE); 404 fail("SecurityException expected"); 405 } catch (SecurityException e) { 406 // expected 407 } 408 } 409 410 @Test 411 public void testUnregisterNetworkScoreCache_noBroadcastNetworkPermission() { 412 doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( 413 eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString()); 414 415 try { 416 mNetworkScoreService.unregisterNetworkScoreCache( 417 NetworkKey.TYPE_WIFI, mNetworkScoreCache); 418 fail("SecurityException expected"); 419 } catch (SecurityException e) { 420 // expected 421 } 422 } 423 424 @Test 425 public void testDump_noDumpPermission() { 426 doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( 427 eq(permission.DUMP), anyString()); 428 429 try { 430 mNetworkScoreService.dump( 431 new FileDescriptor(), new PrintWriter(new StringWriter()), new String[0]); 432 fail("SecurityException expected"); 433 } catch (SecurityException e) { 434 // expected 435 } 436 } 437 438 @Test 439 public void testDump_doesNotCrash() { 440 when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER); 441 StringWriter stringWriter = new StringWriter(); 442 443 mNetworkScoreService.dump( 444 new FileDescriptor(), new PrintWriter(stringWriter), new String[0]); 445 446 assertFalse(stringWriter.toString().isEmpty()); 447 } 448 449 // "injects" the mock INetworkRecommendationProvider into the NetworkScoreService. 450 private void injectProvider() { 451 final ComponentName componentName = new ComponentName(NEW_SCORER.packageName, 452 NEW_SCORER.recommendationServiceClassName); 453 when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER); 454 when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(), 455 isA(UserHandle.class))).thenAnswer(new Answer<Boolean>() { 456 @Override 457 public Boolean answer(InvocationOnMock invocation) throws Throwable { 458 IBinder mockBinder = mock(IBinder.class); 459 when(mockBinder.queryLocalInterface(anyString())) 460 .thenReturn(mRecommendationProvider); 461 invocation.getArgumentAt(1, ServiceConnection.class) 462 .onServiceConnected(componentName, mockBinder); 463 return true; 464 } 465 }); 466 mNetworkScoreService.systemRunning(); 467 } 468} 469