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