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