• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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