1 /* 2 * Copyright (C) 2019 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 17 package com.android.phone; 18 19 import static android.content.pm.PackageManager.PERMISSION_DENIED; 20 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 21 import static android.provider.Telephony.ServiceStateTable; 22 import static android.provider.Telephony.ServiceStateTable.DATA_NETWORK_TYPE; 23 import static android.provider.Telephony.ServiceStateTable.DATA_REG_STATE; 24 import static android.provider.Telephony.ServiceStateTable.DUPLEX_MODE; 25 import static android.provider.Telephony.ServiceStateTable.VOICE_OPERATOR_NUMERIC; 26 import static android.provider.Telephony.ServiceStateTable.VOICE_REG_STATE; 27 import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionId; 28 import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME; 29 30 import static com.android.phone.ServiceStateProvider.ENFORCE_LOCATION_PERMISSION_CHECK; 31 import static com.android.phone.ServiceStateProvider.NETWORK_ID; 32 33 import static org.junit.Assert.assertEquals; 34 import static org.junit.Assert.assertFalse; 35 import static org.junit.Assert.assertNotNull; 36 import static org.junit.Assert.assertThrows; 37 import static org.junit.Assert.assertTrue; 38 import static org.mockito.ArgumentMatchers.any; 39 import static org.mockito.ArgumentMatchers.anyInt; 40 import static org.mockito.ArgumentMatchers.anyString; 41 import static org.mockito.ArgumentMatchers.eq; 42 import static org.mockito.ArgumentMatchers.nullable; 43 import static org.mockito.Mockito.doReturn; 44 import static org.mockito.Mockito.never; 45 import static org.mockito.Mockito.verify; 46 import static org.mockito.Mockito.when; 47 48 import android.Manifest; 49 import android.app.AppOpsManager; 50 import android.compat.testing.PlatformCompatChangeRule; 51 import android.content.Context; 52 import android.content.pm.ApplicationInfo; 53 import android.content.pm.PackageManager; 54 import android.content.pm.ProviderInfo; 55 import android.database.ContentObserver; 56 import android.database.Cursor; 57 import android.location.LocationManager; 58 import android.net.Uri; 59 import android.os.Build; 60 import android.os.UserHandle; 61 import android.telephony.AccessNetworkConstants; 62 import android.telephony.NetworkRegistrationInfo; 63 import android.telephony.ServiceState; 64 import android.telephony.SubscriptionManager; 65 import android.telephony.TelephonyManager; 66 import android.test.mock.MockContentResolver; 67 import android.test.suitebuilder.annotation.SmallTest; 68 69 import androidx.test.ext.junit.runners.AndroidJUnit4; 70 71 import libcore.junit.util.compat.CoreCompatChangeRule; 72 73 import org.junit.After; 74 import org.junit.Before; 75 import org.junit.Ignore; 76 import org.junit.Rule; 77 import org.junit.Test; 78 import org.junit.rules.TestRule; 79 import org.junit.runner.RunWith; 80 import org.mockito.Mock; 81 import org.mockito.MockitoAnnotations; 82 83 /** 84 * Tests for simple queries of ServiceStateProvider. 85 * 86 * Build, install and run the tests by running the commands below: 87 * atest ServiceStateProviderTest 88 */ 89 @RunWith(AndroidJUnit4.class) 90 public class ServiceStateProviderTest { 91 private static final String TAG = "ServiceStateProviderTest"; 92 private static final int TEST_NETWORK_ID = 123; 93 private static final int TEST_SYSTEM_ID = 123; 94 95 private MockContentResolver mContentResolver; 96 private ServiceState mTestServiceState; 97 private ServiceState mTestServiceStateForSubId1; 98 99 @Mock Context mContext; 100 @Mock AppOpsManager mAppOpsManager; 101 @Mock LocationManager mLocationManager; 102 @Mock PackageManager mPackageManager; 103 104 @Rule 105 public TestRule compatChangeRule = new PlatformCompatChangeRule(); 106 107 // Exception used internally to verify if the Resolver#notifyChange has been called. 108 private class TestNotifierException extends RuntimeException { TestNotifierException()109 TestNotifierException() { 110 super(); 111 } 112 } 113 114 @Before setUp()115 public void setUp() throws Exception { 116 MockitoAnnotations.initMocks(this); 117 mockSystemService(AppOpsManager.class, mAppOpsManager, Context.APP_OPS_SERVICE); 118 mockSystemService(LocationManager.class, mLocationManager, Context.LOCATION_SERVICE); 119 doReturn(mPackageManager).when(mContext).getPackageManager(); 120 121 mContentResolver = new MockContentResolver() { 122 @Override 123 public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) { 124 throw new TestNotifierException(); 125 } 126 }; 127 doReturn(mContentResolver).when(mContext).getContentResolver(); 128 129 mTestServiceState = new ServiceState(); 130 mTestServiceState.setStateOutOfService(); 131 mTestServiceState.setCdmaSystemAndNetworkId(TEST_SYSTEM_ID, TEST_NETWORK_ID); 132 mTestServiceStateForSubId1 = new ServiceState(); 133 mTestServiceStateForSubId1.setStateOff(); 134 135 // Add NRI to trigger SS with non-default values (e.g. duplex mode) 136 NetworkRegistrationInfo nriWwan = new NetworkRegistrationInfo.Builder() 137 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 138 .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE) 139 .setDomain(NetworkRegistrationInfo.DOMAIN_PS) 140 .build(); 141 mTestServiceStateForSubId1.addNetworkRegistrationInfo(nriWwan); 142 mTestServiceStateForSubId1.setChannelNumber(65536); // EutranBand.BAND_65, DUPLEX_MODE_FDD 143 144 // Mock out the actual phone state 145 ServiceStateProvider provider = new ServiceStateProvider() { 146 @Override 147 public ServiceState getServiceState(int subId) { 148 if (subId == 1) { 149 return mTestServiceStateForSubId1; 150 } else { 151 return mTestServiceState; 152 } 153 } 154 155 @Override 156 public int getDefaultSubId() { 157 return 0; 158 } 159 }; 160 ProviderInfo providerInfo = new ProviderInfo(); 161 providerInfo.authority = "service-state"; 162 provider.attachInfoForTesting(mContext, providerInfo); 163 mContentResolver.addProvider("service-state", provider); 164 165 // By default, test with app target R, no READ_PRIVILEGED_PHONE_STATE permission 166 setTargetSdkVersion(Build.VERSION_CODES.R); 167 setCanReadPrivilegedPhoneState(false); 168 169 // TODO(b/191995565): Turn on all ignored cases once location access is allow to be off 170 // Do not allow phone process to always access location so we can test various scenarios 171 // LocationAccessPolicy.alwaysAllowPrivilegedProcessToAccessLocationForTesting(false); 172 } 173 174 @After tearDown()175 public void tearDown() throws Exception { 176 // LocationAccessPolicy.alwaysAllowPrivilegedProcessToAccessLocationForTesting(true); 177 } 178 179 /** 180 * Verify that when calling query with no subId in the uri the default ServiceState is returned. 181 * In this case the subId is set to 0 and the expected service state is mTestServiceState. 182 */ 183 // TODO(b/191995565): Turn this on when location access can be off 184 @Ignore 185 @SmallTest 186 @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) testQueryServiceState_withNoSubId_withoutLocation()187 public void testQueryServiceState_withNoSubId_withoutLocation() { 188 setLocationPermissions(false); 189 190 verifyServiceStateForSubId(ServiceStateTable.CONTENT_URI, mTestServiceState, 191 false /*hasLocation*/); 192 } 193 194 @Test 195 @SmallTest testQueryServiceState_withNoSubId_withLocation()196 public void testQueryServiceState_withNoSubId_withLocation() { 197 setLocationPermissions(true); 198 199 verifyServiceStateForSubId(ServiceStateTable.CONTENT_URI, mTestServiceState, 200 true /*hasLocation*/); 201 } 202 203 /** 204 * Verify that when calling with the DEFAULT_SUBSCRIPTION_ID the correct ServiceState is 205 * returned. In this case the subId is set to 0 and the expected service state is 206 * mTestServiceState. 207 */ 208 // TODO(b/191995565): Turn case on when location access can be off 209 @Ignore 210 @SmallTest testGetServiceState_withDefaultSubId_withoutLocation()211 public void testGetServiceState_withDefaultSubId_withoutLocation() { 212 setLocationPermissions(false); 213 214 verifyServiceStateForSubId( 215 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), 216 mTestServiceState, false /*hasLocation*/); 217 } 218 219 @Test 220 @SmallTest testGetServiceState_withDefaultSubId_withLocation()221 public void testGetServiceState_withDefaultSubId_withLocation() { 222 setLocationPermissions(true); 223 224 verifyServiceStateForSubId( 225 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), 226 mTestServiceState, true /*hasLocation*/); 227 } 228 229 /** 230 * Verify that when calling with a specific subId the correct ServiceState is returned. In this 231 * case the subId is set to 1 and the expected service state is mTestServiceStateForSubId1 232 */ 233 @Test 234 @SmallTest testGetServiceStateForSubId_withoutLocation()235 public void testGetServiceStateForSubId_withoutLocation() { 236 setLocationPermissions(false); 237 238 verifyServiceStateForSubId(getUriForSubscriptionId(1), mTestServiceStateForSubId1, 239 false /*hasLocation*/); 240 } 241 242 @Test 243 @SmallTest testGetServiceStateForSubId_withLocation()244 public void testGetServiceStateForSubId_withLocation() { 245 setLocationPermissions(true); 246 247 verifyServiceStateForSubId(getUriForSubscriptionId(1), mTestServiceStateForSubId1, 248 true /*hasLocation*/); 249 } 250 251 /** 252 * Verify that apps target S+ without READ_PRIVILEGED_PHONE_STATE permission can access the 253 * public columns of ServiceStateTable. 254 */ 255 @Test 256 @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) 257 public void query_publicColumns_enforceLocatoinEnabled_targetS_noReadPrivilege_getPublicColumns()258 query_publicColumns_enforceLocatoinEnabled_targetS_noReadPrivilege_getPublicColumns() { 259 setTargetSdkVersion(Build.VERSION_CODES.S); 260 setCanReadPrivilegedPhoneState(false); 261 262 verifyServiceStateWithPublicColumns(mTestServiceState, null /*projection*/); 263 } 264 265 @Test 266 @CoreCompatChangeRule.DisableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) 267 public void query_publicColumns_enforceLocationDisabled_targetS_noReadPrivilege_getPublicColumns()268 query_publicColumns_enforceLocationDisabled_targetS_noReadPrivilege_getPublicColumns() { 269 setTargetSdkVersion(Build.VERSION_CODES.S); 270 setCanReadPrivilegedPhoneState(false); 271 272 verifyServiceStateWithPublicColumns(mTestServiceState, null /*projection*/); 273 } 274 275 /** 276 * Verify that apps target S+ without READ_PRIVILEGED_PHONE_STATE permission try to access 277 * non-public columns should throw IllegalArgumentException. 278 */ 279 @Test 280 @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) query_hideColumn_targetS_noReadPrivilege_throwIllegalArgumentException()281 public void query_hideColumn_targetS_noReadPrivilege_throwIllegalArgumentException() { 282 setTargetSdkVersion(Build.VERSION_CODES.S); 283 setCanReadPrivilegedPhoneState(false); 284 285 // DATA_ROAMING_TYPE is a non-public column 286 String[] projection = new String[]{"data_roaming_type"}; 287 288 assertThrows(IllegalArgumentException.class, 289 () -> verifyServiceStateWithPublicColumns(mTestServiceState, projection)); 290 } 291 292 /** 293 * Verify that with changeId ENFORCE_LOCATION_PERMISSION_CHECK enabled, apps target S+ with 294 * READ_PRIVILEGED_PHONE_STATE and location permissions should be able to access all columns. 295 */ 296 @Test 297 @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) 298 public void query_allColumn_enforceLocationEnabled_targetS_withReadPrivilegedAndLocation_getUnredacted()299 query_allColumn_enforceLocationEnabled_targetS_withReadPrivilegedAndLocation_getUnredacted() { 300 setTargetSdkVersion(Build.VERSION_CODES.S); 301 setCanReadPrivilegedPhoneState(true); 302 setLocationPermissions(true); 303 304 verifyServiceStateForSubId( 305 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), 306 mTestServiceState, true /*hasPermission*/); 307 } 308 309 /** 310 * Verify that with changeId ENFORCE_LOCATION_PERMISSION_CHECK disabled, apps target S+ with 311 * READ_PRIVILEGED_PHONE_STATE and location permissions should be able to access all columns. 312 */ 313 @Test 314 @CoreCompatChangeRule.DisableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) 315 public void query_allColumn_enforceLocationDisabled_targetS_withReadPrivilegedAndLocation_getUnredacted()316 query_allColumn_enforceLocationDisabled_targetS_withReadPrivilegedAndLocation_getUnredacted() { 317 setTargetSdkVersion(Build.VERSION_CODES.S); 318 setCanReadPrivilegedPhoneState(true); 319 setLocationPermissions(true); 320 321 verifyServiceStateForSubId( 322 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), 323 mTestServiceState, true /*hasPermission*/); 324 } 325 326 /** 327 * Verify that apps target S+ with READ_PRIVILEGED_PHONE_STATE permission but no location 328 * permission, try to access location sensitive columns should throw SecurityException. 329 */ 330 // TODO(b/191995565): Turn this on once b/191995565 is integrated 331 @Ignore 332 @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) query_locationColumn_targetS_withReadPrivilegeNoLocation_throwSecurityExecption()333 public void query_locationColumn_targetS_withReadPrivilegeNoLocation_throwSecurityExecption() { 334 setTargetSdkVersion(Build.VERSION_CODES.S); 335 setCanReadPrivilegedPhoneState(true); 336 setLocationPermissions(false); 337 338 assertThrows(SecurityException.class, 339 () -> verifyServiceStateWithLocationColumns(mTestServiceState)); 340 } 341 342 /** 343 * Verify that when changeId ENFORCE_LOCATION_PERMISSION_CHECK is enabled, apps target R- with 344 * location permissions should be able to access all columns. 345 */ 346 @Test 347 @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) query_allColumn_enforceLocationEnabled_targetR_withLocation_getUnredacted()348 public void query_allColumn_enforceLocationEnabled_targetR_withLocation_getUnredacted() { 349 setTargetSdkVersion(Build.VERSION_CODES.R); 350 setLocationPermissions(true); 351 352 verifyServiceStateForSubId( 353 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), 354 mTestServiceState, true /*hasPermission*/); 355 } 356 357 /** 358 * Verify that when changeId ENFORCE_LOCATION_PERMISSION_CHECK is disabled, apps target R- with 359 * location permissions should be able to access all columns. 360 */ 361 @Test 362 @CoreCompatChangeRule.DisableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) query_allColumn_enforceLocationDisabled_targetR_withLocation_getUnredacted()363 public void query_allColumn_enforceLocationDisabled_targetR_withLocation_getUnredacted() { 364 setTargetSdkVersion(Build.VERSION_CODES.R); 365 setLocationPermissions(true); 366 367 verifyServiceStateForSubId( 368 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), 369 mTestServiceState, true /*hasPermission*/); 370 } 371 372 /** 373 * Verify that changeId ENFORCE_LOCATION_PERMISSION_CHECK is enabled, apps target R- w/o 374 * location permissions should be able to access all columns but with redacted ServiceState. 375 */ 376 // TODO(b/191995565): Turn case on when location access can be off 377 @Ignore 378 @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) query_allColumn_enforceLocationEnabled_targetR_noLocation_getRedacted()379 public void query_allColumn_enforceLocationEnabled_targetR_noLocation_getRedacted() { 380 setTargetSdkVersion(Build.VERSION_CODES.R); 381 setLocationPermissions(false); 382 383 verifyServiceStateForSubId( 384 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), 385 ServiceStateProvider.getLocationRedactedServiceState(mTestServiceState), 386 true /*hasPermission*/); 387 } 388 389 /** 390 * Verify that changeId ENFORCE_LOCATION_PERMISSION_CHECK is disabled, apps target R- w/o 391 * location permissions should be able to access all columns and with unredacted ServiceState. 392 */ 393 // TODO(b/191995565): Turn case on when location access can be off 394 @Ignore 395 @CoreCompatChangeRule.DisableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) query_allColumn_enforceLocationDisabled_targetR_noLocation_getUnredacted()396 public void query_allColumn_enforceLocationDisabled_targetR_noLocation_getUnredacted() { 397 setTargetSdkVersion(Build.VERSION_CODES.R); 398 setLocationPermissions(false); 399 400 verifyServiceStateForSubId( 401 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), 402 mTestServiceState, true /*hasPermission*/); 403 } 404 405 /** 406 * Verify that when caller with targetSDK S+ has location permission and try to query 407 * location non-sensitive info, it should not get blamed. 408 */ 409 @Test 410 @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK}) testQuery_noLocationBlamed_whenQueryNonLocationInfo_withPermission()411 public void testQuery_noLocationBlamed_whenQueryNonLocationInfo_withPermission() { 412 setTargetSdkVersion(Build.VERSION_CODES.S); 413 setLocationPermissions(true); 414 415 verifyServiceStateWithPublicColumns(mTestServiceState, null /*projection*/); 416 verify(mAppOpsManager, never()).noteOpNoThrow(any(), anyInt(), any(), any(), any()); 417 } 418 verifyServiceStateWithLocationColumns(ServiceState ss)419 private void verifyServiceStateWithLocationColumns(ServiceState ss) { 420 // NETWORK_ID is a location-sensitive column 421 try (Cursor cursor = mContentResolver.query(ServiceStateTable.CONTENT_URI, 422 new String[]{NETWORK_ID}, null, null)) { 423 assertNotNull(cursor); 424 } 425 } 426 verifyServiceStateWithPublicColumns(ServiceState ss, String[] projection)427 private void verifyServiceStateWithPublicColumns(ServiceState ss, String[] projection) { 428 try (Cursor cursor = mContentResolver.query(ServiceStateTable.CONTENT_URI, projection, null, 429 null)) { 430 assertNotNull(cursor); 431 432 cursor.moveToFirst(); 433 assertEquals(ss.getVoiceRegState(), 434 cursor.getInt(cursor.getColumnIndex(VOICE_REG_STATE))); 435 assertEquals(ss.getDataRegistrationState(), 436 cursor.getInt(cursor.getColumnIndex(DATA_REG_STATE))); 437 assertEquals(ss.getOperatorNumeric(), 438 cursor.getString(cursor.getColumnIndex(VOICE_OPERATOR_NUMERIC))); 439 assertEquals(ss.getDataNetworkType(), 440 cursor.getInt(cursor.getColumnIndex(DATA_NETWORK_TYPE))); 441 assertEquals(ss.getDuplexMode(), cursor.getInt(cursor.getColumnIndex(DUPLEX_MODE))); 442 } 443 } 444 verifyServiceStateForSubId(Uri uri, ServiceState ss, boolean hasLocation)445 private void verifyServiceStateForSubId(Uri uri, ServiceState ss, boolean hasLocation) { 446 Cursor cursor = mContentResolver.query(uri, ServiceStateProvider.ALL_COLUMNS, "", 447 null, null); 448 assertNotNull(cursor); 449 cursor.moveToFirst(); 450 451 final int voiceRegState = ss.getState(); 452 final int dataRegState = ss.getDataRegistrationState(); 453 final int voiceRoamingType = ss.getVoiceRoamingType(); 454 final int dataRoamingType = ss.getDataRoamingType(); 455 final String voiceOperatorAlphaLong = hasLocation ? ss.getOperatorAlphaLong() : null; 456 final String voiceOperatorAlphaShort = hasLocation ? ss.getOperatorAlphaShort() : null; 457 final String voiceOperatorNumeric = hasLocation ? ss.getOperatorNumeric() : null; 458 final String dataOperatorAlphaLong = hasLocation ? ss.getOperatorAlphaLong() : null; 459 final String dataOperatorAlphaShort = hasLocation ? ss.getOperatorAlphaShort() : null; 460 final String dataOperatorNumeric = hasLocation ? ss.getOperatorNumeric() : null; 461 final int isManualNetworkSelection = (ss.getIsManualSelection()) ? 1 : 0; 462 final int rilVoiceRadioTechnology = ss.getRilVoiceRadioTechnology(); 463 final int rilDataRadioTechnology = ss.getRilDataRadioTechnology(); 464 final int cssIndicator = ss.getCssIndicator(); 465 final int networkId = hasLocation ? ss.getCdmaNetworkId() : ServiceState.UNKNOWN_ID; 466 final int systemId = hasLocation ? ss.getCdmaSystemId() : ServiceState.UNKNOWN_ID; 467 final int cdmaRoamingIndicator = ss.getCdmaRoamingIndicator(); 468 final int cdmaDefaultRoamingIndicator = ss.getCdmaDefaultRoamingIndicator(); 469 final int cdmaEriIconIndex = ss.getCdmaEriIconIndex(); 470 final int cdmaEriIconMode = ss.getCdmaEriIconMode(); 471 final int isEmergencyOnly = (ss.isEmergencyOnly()) ? 1 : 0; 472 final int isUsingCarrierAggregation = (ss.isUsingCarrierAggregation()) ? 1 : 0; 473 final String operatorAlphaLongRaw = ss.getOperatorAlphaLongRaw(); 474 final String operatorAlphaShortRaw = ss.getOperatorAlphaShortRaw(); 475 final int dataNetworkType = ss.getDataNetworkType(); 476 final int duplexMode = ss.getDuplexMode(); 477 478 assertEquals(voiceRegState, cursor.getInt(0)); 479 assertEquals(dataRegState, cursor.getInt(1)); 480 assertEquals(voiceRoamingType, cursor.getInt(2)); 481 assertEquals(dataRoamingType, cursor.getInt(3)); 482 assertEquals(voiceOperatorAlphaLong, cursor.getString(4)); 483 assertEquals(voiceOperatorAlphaShort, cursor.getString(5)); 484 assertEquals(voiceOperatorNumeric, cursor.getString(6)); 485 assertEquals(dataOperatorAlphaLong, cursor.getString(7)); 486 assertEquals(dataOperatorAlphaShort, cursor.getString(8)); 487 assertEquals(dataOperatorNumeric, cursor.getString(9)); 488 assertEquals(isManualNetworkSelection, cursor.getInt(10)); 489 assertEquals(rilVoiceRadioTechnology, cursor.getInt(11)); 490 assertEquals(rilDataRadioTechnology, cursor.getInt(12)); 491 assertEquals(cssIndicator, cursor.getInt(13)); 492 assertEquals(networkId, cursor.getInt(14)); 493 assertEquals(systemId, cursor.getInt(15)); 494 assertEquals(cdmaRoamingIndicator, cursor.getInt(16)); 495 assertEquals(cdmaDefaultRoamingIndicator, cursor.getInt(17)); 496 assertEquals(cdmaEriIconIndex, cursor.getInt(18)); 497 assertEquals(cdmaEriIconMode, cursor.getInt(19)); 498 assertEquals(isEmergencyOnly, cursor.getInt(20)); 499 assertEquals(isUsingCarrierAggregation, cursor.getInt(21)); 500 assertEquals(operatorAlphaLongRaw, cursor.getString(22)); 501 assertEquals(operatorAlphaShortRaw, cursor.getString(23)); 502 assertEquals(dataNetworkType, cursor.getInt(24)); 503 assertEquals(duplexMode, cursor.getInt(25)); 504 } 505 506 /** 507 * Test that we don't notify for certain field changes. (e.g. we don't notify when the NetworkId 508 * or SystemId change) This is an intentional behavior change from the broadcast. 509 */ 510 @Test 511 @SmallTest testNoNotify()512 public void testNoNotify() { 513 int subId = 0; 514 515 ServiceState oldSS = new ServiceState(); 516 oldSS.setStateOutOfService(); 517 oldSS.setCdmaSystemAndNetworkId(1, 1); 518 519 ServiceState newSS = new ServiceState(); 520 newSS.setStateOutOfService(); 521 newSS.setCdmaSystemAndNetworkId(0, 0); 522 523 // Test that notifyChange is not called for these fields 524 assertFalse(notifyChangeCalledForSubIdAndField(oldSS, newSS, subId)); 525 } 526 527 @Test 528 @SmallTest testNotifyChanged_noStateUpdated()529 public void testNotifyChanged_noStateUpdated() { 530 int subId = 0; 531 532 ServiceState oldSS = new ServiceState(); 533 oldSS.setStateOutOfService(); 534 oldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE); 535 536 ServiceState copyOfOldSS = new ServiceState(); 537 copyOfOldSS.setStateOutOfService(); 538 copyOfOldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE); 539 540 // Test that notifyChange is not called with no change in notifyChangeForSubIdAndField 541 assertFalse(notifyChangeCalledForSubId(oldSS, copyOfOldSS, subId)); 542 543 // Test that notifyChange is not called with no change in notifyChangeForSubId 544 assertFalse(notifyChangeCalledForSubIdAndField(oldSS, copyOfOldSS, subId)); 545 } 546 547 @Test 548 @SmallTest testNotifyChanged_voiceRegStateUpdated()549 public void testNotifyChanged_voiceRegStateUpdated() { 550 int subId = 0; 551 552 ServiceState oldSS = new ServiceState(); 553 oldSS.setStateOutOfService(); 554 oldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE); 555 556 ServiceState newSS = new ServiceState(); 557 newSS.setStateOutOfService(); 558 newSS.setVoiceRegState(ServiceState.STATE_POWER_OFF); 559 560 // Test that notifyChange is called by notifyChangeForSubIdAndField when the voice_reg_state 561 // changes 562 assertTrue(notifyChangeCalledForSubId(oldSS, newSS, subId)); 563 564 // Test that notifyChange is called by notifyChangeForSubId when the voice_reg_state changes 565 assertTrue(notifyChangeCalledForSubIdAndField(oldSS, newSS, subId)); 566 } 567 568 @Test 569 @SmallTest testNotifyChanged_dataNetworkTypeUpdated()570 public void testNotifyChanged_dataNetworkTypeUpdated() { 571 int subId = 0; 572 573 // While we don't have a method to directly set dataNetworkType, we emulate a ServiceState 574 // change that will trigger the change of dataNetworkType, according to the logic in 575 // ServiceState#getDataNetworkType 576 ServiceState oldSS = new ServiceState(); 577 oldSS.setStateOutOfService(); 578 579 ServiceState newSS = new ServiceState(); 580 newSS.setStateOutOfService(); 581 582 NetworkRegistrationInfo nriWwan = new NetworkRegistrationInfo.Builder() 583 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 584 .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE) 585 .setDomain(NetworkRegistrationInfo.DOMAIN_PS) 586 .setRegistrationState(REGISTRATION_STATE_HOME) 587 .build(); 588 newSS.addNetworkRegistrationInfo(nriWwan); 589 590 // Test that notifyChange is called by notifyChangeForSubId when the 591 // data_network_type changes 592 assertTrue(notifyChangeCalledForSubId(oldSS, newSS, subId)); 593 594 // Test that notifyChange is called by notifyChangeForSubIdAndField when the 595 // data_network_type changes 596 assertTrue(notifyChangeCalledForSubIdAndField(oldSS, newSS, subId)); 597 } 598 599 @Test 600 @SmallTest testNotifyChanged_dataRegStateUpdated()601 public void testNotifyChanged_dataRegStateUpdated() { 602 int subId = 0; 603 604 ServiceState oldSS = new ServiceState(); 605 oldSS.setStateOutOfService(); 606 oldSS.setDataRegState(ServiceState.STATE_OUT_OF_SERVICE); 607 608 ServiceState newSS = new ServiceState(); 609 newSS.setStateOutOfService(); 610 newSS.setDataRegState(ServiceState.STATE_POWER_OFF); 611 612 // Test that notifyChange is called by notifyChangeForSubId 613 // when the data_reg_state changes 614 assertTrue(notifyChangeCalledForSubId(oldSS, newSS, subId)); 615 616 // Test that notifyChange is called by notifyChangeForSubIdAndField 617 // when the data_reg_state changes 618 assertTrue(notifyChangeCalledForSubIdAndField(oldSS, newSS, subId)); 619 } 620 621 // Check if notifyChange was called by notifyChangeForSubId notifyChangeCalledForSubId(ServiceState oldSS, ServiceState newSS, int subId)622 private boolean notifyChangeCalledForSubId(ServiceState oldSS, 623 ServiceState newSS, int subId) { 624 try { 625 ServiceStateProvider.notifyChangeForSubId(mContext, oldSS, newSS, subId); 626 } catch (TestNotifierException e) { 627 return true; 628 } 629 return false; 630 } 631 632 // Check if notifyChange was called by notifyChangeForSubIdAndField notifyChangeCalledForSubIdAndField(ServiceState oldSS, ServiceState newSS, int subId)633 private boolean notifyChangeCalledForSubIdAndField(ServiceState oldSS, 634 ServiceState newSS, int subId) { 635 try { 636 ServiceStateProvider.notifyChangeForSubIdAndField(mContext, oldSS, newSS, subId); 637 } catch (TestNotifierException e) { 638 return true; 639 } 640 return false; 641 } 642 setLocationPermissions(boolean hasPermission)643 private void setLocationPermissions(boolean hasPermission) { 644 if (!hasPermission) { 645 // System location off, LocationAccessPolicy#checkLocationPermission returns DENIED_SOFT 646 when(mLocationManager.isLocationEnabledForUser(any(UserHandle.class))) 647 .thenReturn(false); 648 } else { 649 // Turn on all to let LocationAccessPolicy#checkLocationPermission returns ALLOWED 650 when(mContext.checkPermission(eq(Manifest.permission.ACCESS_FINE_LOCATION), 651 anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); 652 653 when(mContext.checkPermission(eq(Manifest.permission.ACCESS_COARSE_LOCATION), 654 anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); 655 656 when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OPSTR_FINE_LOCATION), 657 anyInt(), anyString(), nullable(String.class), nullable(String.class))) 658 .thenReturn(AppOpsManager.MODE_ALLOWED); 659 when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OPSTR_COARSE_LOCATION), 660 anyInt(), anyString(), nullable(String.class), nullable(String.class))) 661 .thenReturn(AppOpsManager.MODE_ALLOWED); 662 663 when(mLocationManager.isLocationEnabledForUser(any(UserHandle.class))).thenReturn(true); 664 when(mContext.checkPermission(eq(Manifest.permission.INTERACT_ACROSS_USERS_FULL), 665 anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); 666 } 667 } 668 mockSystemService(Class<T> clazz , T obj, String serviceName)669 private <T> void mockSystemService(Class<T> clazz , T obj, String serviceName) { 670 when(mContext.getSystemServiceName(eq(clazz))).thenReturn(serviceName); 671 when(mContext.getSystemService(eq(serviceName))).thenReturn(obj); 672 } 673 setTargetSdkVersion(int version)674 private void setTargetSdkVersion(int version) { 675 ApplicationInfo testAppInfo = new ApplicationInfo(); 676 testAppInfo.targetSdkVersion = version; 677 try { 678 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) 679 .thenReturn(testAppInfo); 680 } catch (Exception ignored) { 681 } 682 } 683 setCanReadPrivilegedPhoneState(boolean granted)684 private void setCanReadPrivilegedPhoneState(boolean granted) { 685 doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED).when(mContext) 686 .checkCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 687 } 688 } 689