1 /* 2 * Copyright (C) 2021 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 org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertThrows; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assert.fail; 24 import static org.mockito.ArgumentMatchers.anyInt; 25 import static org.mockito.ArgumentMatchers.anyString; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.ArgumentMatchers.isNull; 28 import static org.mockito.Mockito.doNothing; 29 import static org.mockito.Mockito.doReturn; 30 import static org.mockito.Mockito.doThrow; 31 import static org.mockito.Mockito.mock; 32 import static org.mockito.Mockito.never; 33 import static org.mockito.Mockito.spy; 34 import static org.mockito.Mockito.verify; 35 import static org.mockito.Mockito.when; 36 37 import android.app.AppOpsManager; 38 import android.compat.testing.PlatformCompatChangeRule; 39 import android.content.Context; 40 import android.content.SharedPreferences; 41 import android.content.pm.PackageManager; 42 import android.content.res.Resources; 43 import android.os.Build; 44 import android.permission.flags.Flags; 45 import android.platform.test.flag.junit.SetFlagsRule; 46 import android.telephony.RadioAccessFamily; 47 import android.telephony.TelephonyManager; 48 49 import androidx.test.annotation.UiThreadTest; 50 import androidx.test.ext.junit.runners.AndroidJUnit4; 51 52 import com.android.TelephonyTestBase; 53 import com.android.internal.telephony.IIntegerConsumer; 54 import com.android.internal.telephony.Phone; 55 import com.android.internal.telephony.RILConstants; 56 import com.android.internal.telephony.flags.FeatureFlags; 57 import com.android.internal.telephony.subscription.SubscriptionManagerService; 58 59 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; 60 61 import org.junit.Before; 62 import org.junit.Rule; 63 import org.junit.Test; 64 import org.junit.rules.TestRule; 65 import org.junit.runner.RunWith; 66 import org.mockito.Mock; 67 68 import java.lang.reflect.Field; 69 import java.lang.reflect.Modifier; 70 import java.util.Collections; 71 import java.util.Locale; 72 73 /** 74 * Unit Test for PhoneInterfaceManager. 75 */ 76 @RunWith(AndroidJUnit4.class) 77 public class PhoneInterfaceManagerTest extends TelephonyTestBase { 78 @Rule 79 public TestRule compatChangeRule = new PlatformCompatChangeRule(); 80 81 private PhoneInterfaceManager mPhoneInterfaceManager; 82 private SharedPreferences mSharedPreferences; 83 private IIntegerConsumer mIIntegerConsumer; 84 private static final String sDebugPackageName = 85 PhoneInterfaceManagerTest.class.getPackageName(); 86 87 @Mock 88 PhoneGlobals mPhoneGlobals; 89 @Mock 90 Phone mPhone; 91 @Mock 92 FeatureFlags mFeatureFlags; 93 @Mock 94 PackageManager mPackageManager; 95 @Mock 96 private SubscriptionManagerService mSubscriptionManagerService; 97 98 @Mock 99 private AppOpsManager mAppOps; 100 101 @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 102 103 @Before 104 @UiThreadTest setUp()105 public void setUp() throws Exception { 106 super.setUp(); 107 doReturn(sDebugPackageName).when(mPhoneGlobals).getOpPackageName(); 108 109 // Note that PhoneInterfaceManager is a singleton. Calling init gives us a handle to the 110 // global singleton, but the context that is passed in is unused if the phone app is already 111 // alive on a test devices. You must use the spy to mock behavior. Mocks stemming from the 112 // passed context will remain unused. 113 mPhoneInterfaceManager = spy(PhoneInterfaceManager.init(mPhoneGlobals, mFeatureFlags)); 114 doReturn(mSubscriptionManagerService).when(mPhoneInterfaceManager) 115 .getSubscriptionManagerService(); 116 TelephonyManager.setupISubForTest(mSubscriptionManagerService); 117 mSharedPreferences = mPhoneInterfaceManager.getSharedPreferences(); 118 mSharedPreferences.edit().remove(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED).commit(); 119 mSharedPreferences.edit().remove(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED).commit(); 120 mIIntegerConsumer = mock(IIntegerConsumer.class); 121 122 // In order not to affect the existing implementation, define a telephony features 123 // and disabled enforce_telephony_feature_mapping_for_public_apis feature flag 124 mPhoneInterfaceManager.setFeatureFlags(mFeatureFlags); 125 doReturn(false).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis(); 126 mPhoneInterfaceManager.setPackageManager(mPackageManager); 127 doReturn(true).when(mPackageManager).hasSystemFeature(anyString()); 128 129 mPhoneInterfaceManager.setAppOpsManager(mAppOps); 130 } 131 132 @Test cleanUpAllowedNetworkTypes_validPhoneAndSubId_doSetAllowedNetwork()133 public void cleanUpAllowedNetworkTypes_validPhoneAndSubId_doSetAllowedNetwork() { 134 long defaultNetworkType = RadioAccessFamily.getRafFromNetworkType( 135 RILConstants.PREFERRED_NETWORK_MODE); 136 137 mPhoneInterfaceManager.cleanUpAllowedNetworkTypes(mPhone, 1); 138 139 verify(mPhone).loadAllowedNetworksFromSubscriptionDatabase(); 140 verify(mPhone).setAllowedNetworkTypes(TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, 141 defaultNetworkType, null); 142 } 143 144 @Test cleanUpAllowedNetworkTypes_validPhoneAndInvalidSubId_doNotSetAllowedNetwork()145 public void cleanUpAllowedNetworkTypes_validPhoneAndInvalidSubId_doNotSetAllowedNetwork() { 146 long defaultNetworkType = RadioAccessFamily.getRafFromNetworkType( 147 RILConstants.PREFERRED_NETWORK_MODE); 148 149 mPhoneInterfaceManager.cleanUpAllowedNetworkTypes(mPhone, -1); 150 151 verify(mPhone, never()).loadAllowedNetworksFromSubscriptionDatabase(); 152 verify(mPhone, never()).setAllowedNetworkTypes( 153 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, defaultNetworkType, null); 154 } 155 156 @Test matchLocaleFromSupportedLocaleList_inputLocaleChangeToSupportedLocale_notMatched()157 public void matchLocaleFromSupportedLocaleList_inputLocaleChangeToSupportedLocale_notMatched() { 158 Context context = mock(Context.class); 159 when(mPhone.getContext()).thenReturn(context); 160 Resources resources = mock(Resources.class); 161 when(context.getResources()).thenReturn(resources); 162 when(resources.getStringArray(anyInt())) 163 .thenReturn(new String[]{"fi-FI", "ff-Adlm-BF", "en-US"}); 164 165 // Input empty string, then return default locale of ICU. 166 String resultInputEmpty = mPhoneInterfaceManager.matchLocaleFromSupportedLocaleList(mPhone, 167 Locale.forLanguageTag("")); 168 169 assertEquals("und", resultInputEmpty); 170 171 // Input en, then look up the matched supported locale. No matched, so return input locale. 172 String resultOnlyLanguage = mPhoneInterfaceManager.matchLocaleFromSupportedLocaleList( 173 mPhone, 174 Locale.forLanguageTag("en")); 175 176 assertEquals("en", resultOnlyLanguage); 177 } 178 179 @Test matchLocaleFromSupportedLocaleList_inputLocaleChangeToSupportedLocale()180 public void matchLocaleFromSupportedLocaleList_inputLocaleChangeToSupportedLocale() { 181 Context context = mock(Context.class); 182 when(mPhone.getContext()).thenReturn(context); 183 Resources resources = mock(Resources.class); 184 when(context.getResources()).thenReturn(resources); 185 when(resources.getStringArray(anyInt())).thenReturn(new String[]{"zh-Hant-TW"}); 186 187 // Input zh-TW, then look up the matched supported locale, zh-Hant-TW, instead. 188 String resultInputZhTw = mPhoneInterfaceManager.matchLocaleFromSupportedLocaleList(mPhone, 189 Locale.forLanguageTag("zh-TW")); 190 191 assertEquals("zh-Hant-TW", resultInputZhTw); 192 193 when(resources.getStringArray(anyInt())).thenReturn( 194 new String[]{"fi-FI", "ff-Adlm-BF", "ff-Latn-BF"}); 195 196 // Input ff-BF, then find the matched supported locale, ff-Latn-BF, instead. 197 String resultFfBf = mPhoneInterfaceManager.matchLocaleFromSupportedLocaleList(mPhone, 198 Locale.forLanguageTag("ff-BF")); 199 200 assertEquals("ff-Latn-BF", resultFfBf); 201 } 202 203 @Test setNullCipherAndIntegrityEnabled_successfullyEnable()204 public void setNullCipherAndIntegrityEnabled_successfullyEnable() { 205 whenModemSupportsNullCiphers(); 206 doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 207 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 208 assertFalse(mSharedPreferences.contains(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED)); 209 210 mPhoneInterfaceManager.setNullCipherAndIntegrityEnabled(true); 211 212 assertTrue( 213 mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED, false)); 214 } 215 216 @Test setNullCipherAndIntegrityEnabled_successfullyDisable()217 public void setNullCipherAndIntegrityEnabled_successfullyDisable() { 218 whenModemSupportsNullCiphers(); 219 doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 220 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 221 assertFalse(mSharedPreferences.contains(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED)); 222 223 mPhoneInterfaceManager.setNullCipherAndIntegrityEnabled(false); 224 225 assertFalse( 226 mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED, true)); 227 } 228 229 @Test setNullCipherAndIntegrityEnabled_lackingNecessaryHal()230 public void setNullCipherAndIntegrityEnabled_lackingNecessaryHal() { 231 doReturn(101).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 232 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 233 234 assertThrows(UnsupportedOperationException.class, () -> { 235 mPhoneInterfaceManager.setNullCipherAndIntegrityEnabled(true); 236 }); 237 238 } 239 240 @Test setNullCipherAndIntegrityEnabled_lackingPermissions()241 public void setNullCipherAndIntegrityEnabled_lackingPermissions() { 242 doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 243 doThrow(SecurityException.class).when(mPhoneInterfaceManager).enforceModifyPermission(); 244 245 assertThrows(SecurityException.class, () -> { 246 mPhoneInterfaceManager.setNullCipherAndIntegrityEnabled(true); 247 }); 248 } 249 250 @Test isNullCipherAndIntegrityPreferenceEnabled()251 public void isNullCipherAndIntegrityPreferenceEnabled() { 252 whenModemSupportsNullCiphers(); 253 doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 254 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 255 256 mPhoneInterfaceManager.setNullCipherAndIntegrityEnabled(false); 257 assertFalse( 258 mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED, true)); 259 } 260 261 @Test isNullCipherAndIntegrityPreferenceEnabled_lackingNecessaryHal()262 public void isNullCipherAndIntegrityPreferenceEnabled_lackingNecessaryHal() { 263 doReturn(101).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 264 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 265 266 assertThrows(UnsupportedOperationException.class, () -> { 267 mPhoneInterfaceManager.isNullCipherAndIntegrityPreferenceEnabled(); 268 }); 269 270 } 271 272 @Test isNullCipherAndIntegrityPreferenceEnabled_lackingModemSupport()273 public void isNullCipherAndIntegrityPreferenceEnabled_lackingModemSupport() { 274 whenModemDoesNotSupportNullCiphers(); 275 doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 276 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 277 278 assertThrows(UnsupportedOperationException.class, () -> { 279 mPhoneInterfaceManager.isNullCipherAndIntegrityPreferenceEnabled(); 280 }); 281 282 } 283 284 @Test isNullCipherAndIntegrityPreferenceEnabled_lackingPermissions()285 public void isNullCipherAndIntegrityPreferenceEnabled_lackingPermissions() { 286 doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 287 doThrow(SecurityException.class).when(mPhoneInterfaceManager).enforceReadPermission(); 288 289 assertThrows(SecurityException.class, () -> { 290 mPhoneInterfaceManager.isNullCipherAndIntegrityPreferenceEnabled(); 291 }); 292 } 293 whenModemDoesNotSupportNullCiphers()294 private void whenModemDoesNotSupportNullCiphers() { 295 doReturn(false).when(mPhone).isNullCipherAndIntegritySupported(); 296 doReturn(mPhone).when( 297 mPhoneInterfaceManager).getDefaultPhone(); 298 } 299 whenModemSupportsNullCiphers()300 private void whenModemSupportsNullCiphers() { 301 doReturn(true).when(mPhone).isNullCipherAndIntegritySupported(); 302 doReturn(mPhone).when( 303 mPhoneInterfaceManager).getDefaultPhone(); 304 } 305 306 @Test setNullCipherNotificationsEnabled_allReqsMet_successfullyEnabled()307 public void setNullCipherNotificationsEnabled_allReqsMet_successfullyEnabled() { 308 setModemSupportsNullCipherNotification(true); 309 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 310 doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 311 assertFalse(mSharedPreferences.contains(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED)); 312 313 mPhoneInterfaceManager.setNullCipherNotificationsEnabled(true); 314 315 assertTrue( 316 mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED, false)); 317 } 318 319 @Test setNullCipherNotificationsEnabled_allReqsMet_successfullyDisabled()320 public void setNullCipherNotificationsEnabled_allReqsMet_successfullyDisabled() { 321 setModemSupportsNullCipherNotification(true); 322 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 323 doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 324 assertFalse(mSharedPreferences.contains(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED)); 325 326 mPhoneInterfaceManager.setNullCipherNotificationsEnabled(false); 327 328 assertFalse( 329 mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED, true)); 330 } 331 332 @Test setNullCipherNotificationsEnabled_lackingNecessaryHal_throwsException()333 public void setNullCipherNotificationsEnabled_lackingNecessaryHal_throwsException() { 334 setModemSupportsNullCipherNotification(true); 335 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 336 doReturn(102).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 337 338 assertThrows(UnsupportedOperationException.class, 339 () -> mPhoneInterfaceManager.setNullCipherNotificationsEnabled(true)); 340 } 341 342 @Test setNullCipherNotificationsEnabled_lackingModemSupport_throwsException()343 public void setNullCipherNotificationsEnabled_lackingModemSupport_throwsException() { 344 setModemSupportsNullCipherNotification(false); 345 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 346 doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 347 348 assertThrows(UnsupportedOperationException.class, 349 () -> mPhoneInterfaceManager.setNullCipherNotificationsEnabled(true)); 350 } 351 352 @Test setNullCipherNotificationsEnabled_lackingPermissions_throwsException()353 public void setNullCipherNotificationsEnabled_lackingPermissions_throwsException() { 354 setModemSupportsNullCipherNotification(true); 355 doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 356 doThrow(SecurityException.class).when(mPhoneInterfaceManager).enforceModifyPermission(); 357 358 assertThrows(SecurityException.class, () -> 359 mPhoneInterfaceManager.setNullCipherNotificationsEnabled(true)); 360 } 361 362 @Test isNullCipherNotificationsEnabled_allReqsMet_returnsTrue()363 public void isNullCipherNotificationsEnabled_allReqsMet_returnsTrue() { 364 setModemSupportsNullCipherNotification(true); 365 doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 366 doNothing().when(mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString()); 367 doReturn(true).when(mPhone).getNullCipherNotificationsPreferenceEnabled(); 368 369 assertTrue(mPhoneInterfaceManager.isNullCipherNotificationsEnabled()); 370 } 371 372 @Test isNullCipherNotificationsEnabled_lackingNecessaryHal_throwsException()373 public void isNullCipherNotificationsEnabled_lackingNecessaryHal_throwsException() { 374 setModemSupportsNullCipherNotification(true); 375 doReturn(102).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 376 doNothing().when(mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString()); 377 378 assertThrows(UnsupportedOperationException.class, () -> 379 mPhoneInterfaceManager.isNullCipherNotificationsEnabled()); 380 } 381 382 @Test isNullCipherNotificationsEnabled_lackingModemSupport_throwsException()383 public void isNullCipherNotificationsEnabled_lackingModemSupport_throwsException() { 384 setModemSupportsNullCipherNotification(false); 385 doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 386 doNothing().when(mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString()); 387 388 assertThrows(UnsupportedOperationException.class, () -> 389 mPhoneInterfaceManager.isNullCipherNotificationsEnabled()); 390 } 391 392 @Test isNullCipherNotificationsEnabled_lackingPermissions_throwsException()393 public void isNullCipherNotificationsEnabled_lackingPermissions_throwsException() { 394 setModemSupportsNullCipherNotification(true); 395 doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt()); 396 doThrow(SecurityException.class).when( 397 mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString()); 398 399 assertThrows(SecurityException.class, () -> 400 mPhoneInterfaceManager.isNullCipherNotificationsEnabled()); 401 } 402 setModemSupportsNullCipherNotification(boolean enable)403 private void setModemSupportsNullCipherNotification(boolean enable) { 404 doReturn(enable).when(mPhone).isNullCipherNotificationSupported(); 405 doReturn(mPhone).when(mPhoneInterfaceManager).getDefaultPhone(); 406 } 407 408 /** 409 * Verify getCarrierRestrictionStatus throws exception for invalid caller package name. 410 */ 411 @Test getCarrierRestrictionStatus_ReadPrivilegedException2()412 public void getCarrierRestrictionStatus_ReadPrivilegedException2() { 413 doThrow(SecurityException.class).when( 414 mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString()); 415 assertThrows(SecurityException.class, () -> { 416 mPhoneInterfaceManager.getCarrierRestrictionStatus(mIIntegerConsumer, ""); 417 }); 418 } 419 420 /** 421 * Verify getCarrierRestrictionStatus doesn't throw any exception with valid package name 422 * and with READ_PHONE_STATE permission granted. 423 */ 424 @Test getCarrierRestrictionStatus()425 public void getCarrierRestrictionStatus() { 426 when(mPhoneInterfaceManager.validateCallerAndGetCarrierIds(anyString())).thenReturn( 427 Collections.singleton(1)); 428 mPhoneInterfaceManager.getCarrierRestrictionStatus(mIIntegerConsumer, 429 "com.test.package"); 430 } 431 432 @Test notifyEnableDataWithAppOps_enableByUser_doNoteOp()433 public void notifyEnableDataWithAppOps_enableByUser_doNoteOp() { 434 mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER); 435 String packageName = "INVALID_PACKAGE"; 436 mPhoneInterfaceManager.setDataEnabledForReason(1, 437 TelephonyManager.DATA_ENABLED_REASON_USER, true, packageName); 438 verify(mAppOps).noteOpNoThrow(eq(AppOpsManager.OPSTR_ENABLE_MOBILE_DATA_BY_USER), anyInt(), 439 eq(packageName), isNull(), isNull()); 440 } 441 442 @Test notifyEnableDataWithAppOps_enableByCarrier_doNotNoteOp()443 public void notifyEnableDataWithAppOps_enableByCarrier_doNotNoteOp() { 444 mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER); 445 String packageName = "INVALID_PACKAGE"; 446 verify(mAppOps, never()).noteOpNoThrow(eq(AppOpsManager.OPSTR_ENABLE_MOBILE_DATA_BY_USER), 447 anyInt(), eq(packageName), isNull(), isNull()); 448 } 449 450 @Test notifyEnableDataWithAppOps_disableByUser_doNotNoteOp()451 public void notifyEnableDataWithAppOps_disableByUser_doNotNoteOp() { 452 mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER); 453 String packageName = "INVALID_PACKAGE"; 454 String error = ""; 455 try { 456 mPhoneInterfaceManager.setDataEnabledForReason(1, 457 TelephonyManager.DATA_ENABLED_REASON_USER, false, packageName); 458 } catch (SecurityException expected) { 459 // The test doesn't have access to note the op, but we're just interested that it makes 460 // the attempt. 461 error = expected.getMessage(); 462 } 463 assertEquals("Expected error to be empty, was " + error, error, ""); 464 } 465 466 @Test notifyEnableDataWithAppOps_noPackageNameAndEnableByUser_doNotnoteOp()467 public void notifyEnableDataWithAppOps_noPackageNameAndEnableByUser_doNotnoteOp() { 468 mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER); 469 String error = ""; 470 try { 471 mPhoneInterfaceManager.setDataEnabledForReason(1, 472 TelephonyManager.DATA_ENABLED_REASON_USER, false, null); 473 } catch (SecurityException expected) { 474 // The test doesn't have access to note the op, but we're just interested that it makes 475 // the attempt. 476 error = expected.getMessage(); 477 } 478 assertEquals("Expected error to be empty, was " + error, error, ""); 479 } 480 481 @Test 482 @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING}) testWithTelephonyFeatureAndCompatChanges()483 public void testWithTelephonyFeatureAndCompatChanges() throws Exception { 484 doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis(); 485 mPhoneInterfaceManager.setFeatureFlags(mFeatureFlags); 486 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 487 488 try { 489 // FEATURE_TELEPHONY_CALLING 490 mPhoneInterfaceManager.handlePinMmiForSubscriber(1, "123456789"); 491 492 // FEATURE_TELEPHONY_RADIO_ACCESS 493 mPhoneInterfaceManager.toggleRadioOnOffForSubscriber(1); 494 } catch (Exception e) { 495 fail("Not expect exception " + e.getMessage()); 496 } 497 } 498 499 @Test 500 @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING}) testWithoutTelephonyFeatureAndCompatChanges()501 public void testWithoutTelephonyFeatureAndCompatChanges() throws Exception { 502 // Replace field to set SDK version of vendor partition to Android V 503 int vendorApiLevel = Build.VERSION_CODES.VANILLA_ICE_CREAM; 504 replaceInstance(PhoneInterfaceManager.class, "mVendorApiLevel", mPhoneInterfaceManager, 505 vendorApiLevel); 506 507 // telephony features is not defined, expect UnsupportedOperationException. 508 doReturn(false).when(mPackageManager).hasSystemFeature( 509 PackageManager.FEATURE_TELEPHONY_CALLING); 510 doReturn(false).when(mPackageManager).hasSystemFeature( 511 PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS); 512 mPhoneInterfaceManager.setPackageManager(mPackageManager); 513 doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis(); 514 mPhoneInterfaceManager.setFeatureFlags(mFeatureFlags); 515 doNothing().when(mPhoneInterfaceManager).enforceModifyPermission(); 516 517 assertThrows(UnsupportedOperationException.class, 518 () -> mPhoneInterfaceManager.handlePinMmiForSubscriber(1, "123456789")); 519 assertThrows(UnsupportedOperationException.class, 520 () -> mPhoneInterfaceManager.toggleRadioOnOffForSubscriber(1)); 521 } 522 523 @Test testGetCurrentPackageNameWithNoKnownPackage()524 public void testGetCurrentPackageNameWithNoKnownPackage() throws Exception { 525 Field field = PhoneInterfaceManager.class.getDeclaredField("mApp"); 526 field.setAccessible(true); 527 Field modifiersField = Field.class.getDeclaredField("accessFlags"); 528 modifiersField.setAccessible(true); 529 modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 530 field.set(mPhoneInterfaceManager, mPhoneGlobals); 531 532 doReturn(mPackageManager).when(mPhoneGlobals).getPackageManager(); 533 doReturn(null).when(mPackageManager).getPackagesForUid(anyInt()); 534 535 String packageName = mPhoneInterfaceManager.getCurrentPackageName(); 536 assertEquals(null, packageName); 537 } 538 } 539