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