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 com.android.TestContext.STUB_PERMISSION_ENABLE_ALL;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import static org.junit.Assert.assertThrows;
24 import static org.junit.Assert.fail;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.ArgumentMatchers.anyInt;
27 import static org.mockito.ArgumentMatchers.anyString;
28 import static org.mockito.ArgumentMatchers.eq;
29 import static org.mockito.Mockito.doNothing;
30 import static org.mockito.Mockito.doReturn;
31 import static org.mockito.Mockito.verify;
32 import static org.mockito.Mockito.when;
33 
34 import android.compat.testing.PlatformCompatChangeRule;
35 import android.content.Context;
36 import android.content.Intent;
37 import android.content.ServiceConnection;
38 import android.content.SharedPreferences;
39 import android.content.pm.PackageInfo;
40 import android.content.pm.PackageManager;
41 import android.content.res.Resources;
42 import android.os.Build;
43 import android.os.Handler;
44 import android.os.HandlerThread;
45 import android.os.PermissionEnforcer;
46 import android.os.PersistableBundle;
47 import android.os.UserHandle;
48 import android.os.test.FakePermissionEnforcer;
49 import android.service.carrier.CarrierIdentifier;
50 import android.telephony.CarrierConfigManager;
51 import android.telephony.SubscriptionManager;
52 import android.telephony.TelephonyManager;
53 import android.telephony.TelephonyRegistryManager;
54 import android.testing.TestableLooper;
55 
56 import androidx.test.InstrumentationRegistry;
57 import androidx.test.ext.junit.runners.AndroidJUnit4;
58 
59 import com.android.TelephonyTestBase;
60 import com.android.internal.telephony.IccCardConstants;
61 import com.android.internal.telephony.flags.FeatureFlags;
62 import com.android.internal.telephony.subscription.SubscriptionManagerService;
63 
64 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
65 
66 import org.junit.After;
67 import org.junit.Before;
68 import org.junit.Ignore;
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 import org.mockito.MockitoAnnotations;
76 
77 import java.io.FileDescriptor;
78 import java.io.PrintWriter;
79 import java.io.StringWriter;
80 
81 /**
82  * Unit Test for CarrierConfigLoader.
83  */
84 @RunWith(AndroidJUnit4.class)
85 public class CarrierConfigLoaderTest extends TelephonyTestBase {
86     @Rule
87     public TestRule compatChangeRule = new PlatformCompatChangeRule();
88 
89     private static final String TAG = CarrierConfigLoaderTest.class.getSimpleName();
90     private static final int DEFAULT_PHONE_ID = 0;
91     private static final int DEFAULT_SUB_ID = SubscriptionManager.getDefaultSubscriptionId();
92     private static final String PLATFORM_CARRIER_CONFIG_PACKAGE = "com.android.carrierconfig";
93     private static final String PLATFORM_CARRIER_CONFIG_FEATURE = "com.android.carrierconfig";
94     private static final long PLATFORM_CARRIER_CONFIG_PACKAGE_VERSION_CODE = 1;
95     private static final String CARRIER_CONFIG_EXAMPLE_KEY =
96             CarrierConfigManager.KEY_CARRIER_USSD_METHOD_INT;
97     private static final int CARRIER_CONFIG_EXAMPLE_VALUE =
98             CarrierConfigManager.USSD_OVER_CS_PREFERRED;
99 
100     @Mock Resources mResources;
101     @Mock PackageManager mPackageManager;
102     @Mock PackageInfo mPackageInfo;
103     @Mock SubscriptionManagerService mSubscriptionManagerService;
104     @Mock SharedPreferences mSharedPreferences;
105     @Mock TelephonyRegistryManager mTelephonyRegistryManager;
106     @Mock FeatureFlags mFeatureFlags;
107 
108     private TelephonyManager mTelephonyManager;
109     private CarrierConfigLoader mCarrierConfigLoader;
110     private Handler mHandler;
111     private HandlerThread mHandlerThread;
112     private TestableLooper mTestableLooper;
113 
114     // The AIDL stub will use PermissionEnforcer to check permission from the caller.
115     private FakePermissionEnforcer mFakePermissionEnforcer = new FakePermissionEnforcer();
116 
117     @Before
setUp()118     public void setUp() throws Exception {
119         super.setUp();
120         MockitoAnnotations.initMocks(this);
121         doReturn(Context.PERMISSION_ENFORCER_SERVICE).when(mContext).getSystemServiceName(
122                 eq(PermissionEnforcer.class));
123         doReturn(mFakePermissionEnforcer).when(mContext).getSystemService(
124                 eq(Context.PERMISSION_ENFORCER_SERVICE));
125         replaceInstance(SubscriptionManagerService.class, "sInstance", null,
126                 mSubscriptionManagerService);
127 
128         // TODO: replace doReturn/when with when/thenReturn which is more readable
129         doReturn(mSharedPreferences).when(mContext).getSharedPreferences(anyString(), anyInt());
130         doReturn(Build.FINGERPRINT).when(mSharedPreferences).getString(eq("build_fingerprint"),
131                 any());
132         doReturn(mPackageManager).when(mContext).getPackageManager();
133         doReturn(new String[]{TAG}).when(mPackageManager).getPackagesForUid(anyInt());
134 
135         doReturn(mResources).when(mContext).getResources();
136         doReturn(InstrumentationRegistry.getTargetContext().getFilesDir()).when(
137                 mContext).getFilesDir();
138         doReturn(PLATFORM_CARRIER_CONFIG_PACKAGE).when(mResources).getString(
139                 eq(R.string.platform_carrier_config_package));
140         mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
141         doReturn(1).when(mTelephonyManager).getSupportedModemCount();
142         doReturn(1).when(mTelephonyManager).getActiveModemCount();
143         doReturn("spn").when(mTelephonyManager).getSimOperatorNameForPhone(anyInt());
144         doReturn("310260").when(mTelephonyManager).getSimOperatorNumericForPhone(anyInt());
145         doReturn(mPackageInfo).when(mPackageManager).getPackageInfo(
146                 eq(PLATFORM_CARRIER_CONFIG_PACKAGE), eq(0) /*flags*/);
147         doReturn(PLATFORM_CARRIER_CONFIG_PACKAGE_VERSION_CODE).when(
148                 mPackageInfo).getLongVersionCode();
149         when(mContext.getSystemServiceName(TelephonyRegistryManager.class)).thenReturn(
150                 Context.TELEPHONY_REGISTRY_SERVICE);
151         when(mContext.getSystemService(TelephonyRegistryManager.class)).thenReturn(
152                 mTelephonyRegistryManager);
153 
154         mHandlerThread = new HandlerThread("CarrierConfigLoaderTest");
155         mHandlerThread.start();
156 
157         mTestableLooper = new TestableLooper(mHandlerThread.getLooper());
158         mCarrierConfigLoader = new CarrierConfigLoader(mContext, mTestableLooper.getLooper(),
159                 mFeatureFlags);
160         mHandler = mCarrierConfigLoader.getHandler();
161 
162         // Clear all configs to have the same starting point.
163         mCarrierConfigLoader.clearConfigForPhone(DEFAULT_PHONE_ID, false);
164     }
165 
166     @After
tearDown()167     public void tearDown() throws Exception {
168         mContext.revokeAllPermissions();
169         mFakePermissionEnforcer.revoke(android.Manifest.permission.DUMP);
170         mFakePermissionEnforcer.revoke(android.Manifest.permission.MODIFY_PHONE_STATE);
171         mFakePermissionEnforcer.revoke(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
172         mTestableLooper.destroy();
173         mHandlerThread.quit();
174         super.tearDown();
175     }
176 
177     /**
178      * Verifies that SecurityException should throw when call #updateConfigForPhoneId() without
179      * MODIFY_PHONE_STATE permission.
180      */
181     @Test
testUpdateConfigForPhoneId_noPermission()182     public void testUpdateConfigForPhoneId_noPermission() throws Exception {
183         assertThrows(SecurityException.class,
184                 () -> mCarrierConfigLoader.updateConfigForPhoneId(DEFAULT_PHONE_ID,
185                         IccCardConstants.INTENT_VALUE_ICC_ABSENT));
186     }
187 
188     /**
189      * Verifies that IllegalArgumentException should throw when call #updateConfigForPhoneId() with
190      * invalid phoneId.
191      */
192     @Test
testUpdateConfigForPhoneId_invalidPhoneId()193     public void testUpdateConfigForPhoneId_invalidPhoneId() throws Exception {
194         mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
195 
196         assertThrows(IllegalArgumentException.class,
197                 () -> mCarrierConfigLoader.updateConfigForPhoneId(
198                         SubscriptionManager.INVALID_PHONE_INDEX,
199                         IccCardConstants.INTENT_VALUE_ICC_ABSENT));
200     }
201 
202     /**
203      * Verifies that when call #updateConfigForPhoneId() with SIM absence, both carrier config from
204      * default app and carrier should be cleared but no-sim config should be loaded.
205      */
206     @Test
testUpdateConfigForPhoneId_simAbsent()207     public void testUpdateConfigForPhoneId_simAbsent() throws Exception {
208         // Bypass case if default subId is not supported by device to reduce flakiness
209         if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
210             return;
211         }
212         mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
213         doNothing().when(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class));
214 
215         // Prepare a cached config to fetch from xml
216         PersistableBundle config = getTestConfig();
217         mCarrierConfigLoader.saveNoSimConfigToXml(PLATFORM_CARRIER_CONFIG_PACKAGE, config);
218         mCarrierConfigLoader.updateConfigForPhoneId(DEFAULT_PHONE_ID,
219                 IccCardConstants.INTENT_VALUE_ICC_ABSENT);
220         mTestableLooper.processAllMessages();
221 
222         assertThat(mCarrierConfigLoader.getConfigFromDefaultApp(DEFAULT_PHONE_ID)).isNull();
223         assertThat(mCarrierConfigLoader.getConfigFromCarrierApp(DEFAULT_PHONE_ID)).isNull();
224         assertThat(mCarrierConfigLoader.getNoSimConfig().getInt(CARRIER_CONFIG_EXAMPLE_KEY))
225                 .isEqualTo(CARRIER_CONFIG_EXAMPLE_VALUE);
226         verify(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class));
227         verify(mTelephonyRegistryManager).notifyCarrierConfigChanged(
228                 eq(DEFAULT_PHONE_ID),
229                 eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID),
230                 eq(TelephonyManager.UNKNOWN_CARRIER_ID),
231                 eq(TelephonyManager.UNKNOWN_CARRIER_ID));
232     }
233 
234     /**
235      * Verifies that with cached config in XML, calling #updateConfigForPhoneId() with SIM loaded
236      * will return the right config in the XML.
237      */
238     @Test
239     @Ignore("b/257169357")
testUpdateConfigForPhoneId_simLoaded_withCachedConfigInXml()240     public void testUpdateConfigForPhoneId_simLoaded_withCachedConfigInXml() throws Exception {
241         // Bypass case if default subId is not supported by device to reduce flakiness
242         if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
243             return;
244         }
245         mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
246 
247         // Prepare to make sure we can save the config into the XML file which used as cache
248         doReturn(PLATFORM_CARRIER_CONFIG_PACKAGE).when(mTelephonyManager)
249                 .getCarrierServicePackageNameForLogicalSlot(anyInt());
250 
251         // Save the sample config into the XML file
252         PersistableBundle config = getTestConfig();
253         CarrierIdentifier carrierId = mCarrierConfigLoader.getCarrierIdentifierForPhoneId(
254                 DEFAULT_PHONE_ID);
255         mCarrierConfigLoader.saveConfigToXml(PLATFORM_CARRIER_CONFIG_PACKAGE, "",
256                 DEFAULT_PHONE_ID, carrierId, config);
257         mCarrierConfigLoader.updateConfigForPhoneId(DEFAULT_PHONE_ID,
258                 IccCardConstants.INTENT_VALUE_ICC_LOADED);
259         mTestableLooper.processAllMessages();
260 
261         assertThat(mCarrierConfigLoader.getConfigFromDefaultApp(DEFAULT_PHONE_ID).getInt(
262                 CARRIER_CONFIG_EXAMPLE_KEY)).isEqualTo(CARRIER_CONFIG_EXAMPLE_VALUE);
263 
264     }
265 
266     /**
267      * Verifies that SecurityException should throw if call #overrideConfig() without
268      * MODIFY_PHONE_STATE permission.
269      */
270     @Test
testOverrideConfig_noPermission()271     public void testOverrideConfig_noPermission() throws Exception {
272         assertThrows(SecurityException.class,
273                 () -> mCarrierConfigLoader.overrideConfig(DEFAULT_SUB_ID, PersistableBundle.EMPTY,
274                         false));
275     }
276 
277     /**
278      * Verifies IllegalArgumentException should throw if call #overrideConfig() with invalid subId.
279      */
280     @Test
testOverrideConfig_invalidSubId()281     public void testOverrideConfig_invalidSubId() throws Exception {
282         mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
283 
284         assertThrows(IllegalArgumentException.class, () -> mCarrierConfigLoader.overrideConfig(
285                 SubscriptionManager.INVALID_SUBSCRIPTION_ID, new PersistableBundle(), false));
286     }
287 
288     /**
289      * Verifies that override config is not null when calling #overrideConfig with null bundle.
290      */
291     @Test
testOverrideConfig_withNullBundle()292     public void testOverrideConfig_withNullBundle() throws Exception {
293         // Bypass case if default subId is not supported by device to reduce flakiness
294         if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
295             return;
296         }
297         mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
298 
299         mCarrierConfigLoader.overrideConfig(DEFAULT_SUB_ID, null /*overrides*/,
300                 false/*persistent*/);
301         mTestableLooper.processAllMessages();
302 
303         assertThat(mCarrierConfigLoader.getOverrideConfig(DEFAULT_PHONE_ID).isEmpty()).isTrue();
304         verify(mSubscriptionManagerService).updateSubscriptionByCarrierConfig(
305                 eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
306                 any(PersistableBundle.class), any(Runnable.class));
307     }
308 
309     /**
310      * Verifies that override config is not null when calling #overrideConfig with non-null bundle.
311      */
312     @Test
testOverrideConfig_withNonNullBundle()313     public void testOverrideConfig_withNonNullBundle() throws Exception {
314         // Bypass case if default subId is not supported by device to reduce flakiness
315         if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
316             return;
317         }
318         mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
319 
320         PersistableBundle config = getTestConfig();
321         mCarrierConfigLoader.overrideConfig(DEFAULT_SUB_ID, config /*overrides*/,
322                 false/*persistent*/);
323         mTestableLooper.processAllMessages();
324 
325         assertThat(mCarrierConfigLoader.getOverrideConfig(DEFAULT_PHONE_ID).getInt(
326                 CARRIER_CONFIG_EXAMPLE_KEY)).isEqualTo(CARRIER_CONFIG_EXAMPLE_VALUE);
327         verify(mSubscriptionManagerService).updateSubscriptionByCarrierConfig(
328                 eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
329                 any(PersistableBundle.class), any(Runnable.class));
330     }
331 
332     /**
333      * Verifies that IllegalArgumentException should throw when calling
334      * #notifyConfigChangedForSubId() with invalid subId.
335      */
336     @Test
testNotifyConfigChangedForSubId_invalidSubId()337     public void testNotifyConfigChangedForSubId_invalidSubId() throws Exception {
338         mFakePermissionEnforcer.grant(STUB_PERMISSION_ENABLE_ALL);
339 
340         assertThrows(IllegalArgumentException.class,
341                 () -> mCarrierConfigLoader.notifyConfigChangedForSubId(
342                         SubscriptionManager.INVALID_SUBSCRIPTION_ID));
343     }
344 
345     // TODO(b/184040111): Enable test case when support disabling carrier privilege
346     // Phone/System UID always has carrier privilege (TelephonyPermission#getCarrierPrivilegeStatus)
347     // when running the test here.
348     /**
349      * Verifies that SecurityException should throw when calling notifyConfigChangedForSubId without
350      * MODIFY_PHONE_STATE permission.
351      */
352     @Ignore
testNotifyConfigChangedForSubId_noPermission()353     public void testNotifyConfigChangedForSubId_noPermission() throws Exception {
354         setCarrierPrivilegesForSubId(false, DEFAULT_SUB_ID);
355 
356         assertThrows(SecurityException.class,
357                 () -> mCarrierConfigLoader.notifyConfigChangedForSubId(DEFAULT_SUB_ID));
358     }
359 
360     /**
361      * Verifies that SecurityException should throw when calling getDefaultCarrierServicePackageName
362      * without READ_PRIVILEGED_PHONE_STATE permission.
363      */
364     @Test
testGetDefaultCarrierServicePackageName_noPermission()365     public void testGetDefaultCarrierServicePackageName_noPermission() {
366         assertThrows(SecurityException.class,
367                 () -> mCarrierConfigLoader.getDefaultCarrierServicePackageName());
368     }
369 
370     /**
371      * Verifies that the right default carrier service package name is return when calling
372      * getDefaultCarrierServicePackageName with permission.
373      */
374     @Test
testGetDefaultCarrierServicePackageName_withPermission()375     public void testGetDefaultCarrierServicePackageName_withPermission() {
376         mFakePermissionEnforcer.grant(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
377 
378         assertThat(mCarrierConfigLoader.getDefaultCarrierServicePackageName())
379                 .isEqualTo(PLATFORM_CARRIER_CONFIG_PACKAGE);
380     }
381 
382     // TODO(b/184040111): Enable test case when support disabling carrier privilege
383     // Phone/System UID always has carrier privilege (TelephonyPermission#getCarrierPrivilegeStatus)
384     // when running the test here.
385     /**
386      * Verifies that without permission, #getConfigForSubId will return an empty PersistableBundle.
387      */
388     @Ignore
testGetConfigForSubId_noPermission()389     public void testGetConfigForSubId_noPermission() {
390         // Bypass case if default subId is not supported by device to reduce flakiness
391         if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
392             return;
393         }
394         setCarrierPrivilegesForSubId(false, DEFAULT_SUB_ID);
395 
396         assertThat(mCarrierConfigLoader.getConfigForSubId(DEFAULT_SUB_ID,
397                 PLATFORM_CARRIER_CONFIG_PACKAGE)).isEqualTo(PersistableBundle.EMPTY);
398     }
399 
400     /**
401      * Verifies that when have no DUMP permission, the #dump() method shows permission denial.
402      */
403     @Test
testDump_noPermission()404     public void testDump_noPermission() {
405         StringWriter stringWriter = new StringWriter();
406         mCarrierConfigLoader.dump(new FileDescriptor(), new PrintWriter(stringWriter),
407                 new String[0]);
408         stringWriter.flush();
409 
410         assertThat(stringWriter.toString()).contains("Permission Denial:");
411     }
412 
413     /**
414      * Verifies that when have DUMP permission, the #dump() method can dump the CarrierConfigLoader.
415      */
416     @Test
testDump_withPermission()417     public void testDump_withPermission() {
418         mContext.grantPermission(android.Manifest.permission.DUMP);
419 
420         StringWriter stringWriter = new StringWriter();
421         mCarrierConfigLoader.dump(new FileDescriptor(), new PrintWriter(stringWriter),
422                 new String[0]);
423         stringWriter.flush();
424 
425         String dumpContent = stringWriter.toString();
426         assertThat(dumpContent).contains("CarrierConfigLoader:");
427         assertThat(dumpContent).doesNotContain("Permission Denial:");
428     }
429 
430     @Test
431     @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
testGetConfigForSubIdWithFeature_withTelephonyFeatureMapping()432     public void testGetConfigForSubIdWithFeature_withTelephonyFeatureMapping() throws Exception {
433         doNothing().when(mContext).enforcePermission(
434                 eq(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE),
435                 anyInt(), anyInt(), anyString());
436 
437         // Replace field to set SDK version of vendor partition to Android V
438         int vendorApiLevel = Build.VERSION_CODES.VANILLA_ICE_CREAM;
439         replaceInstance(CarrierConfigLoader.class, "mVendorApiLevel", mCarrierConfigLoader,
440                 vendorApiLevel);
441 
442         doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
443         doReturn(false).when(mPackageManager).hasSystemFeature(
444                 eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
445 
446         // Not defined required feature, expect UnsupportedOperationException
447         assertThrows(UnsupportedOperationException.class,
448                 () -> mCarrierConfigLoader.getConfigForSubIdWithFeature(DEFAULT_SUB_ID,
449                         PLATFORM_CARRIER_CONFIG_PACKAGE, PLATFORM_CARRIER_CONFIG_FEATURE));
450 
451         doReturn(true).when(mPackageManager).hasSystemFeature(
452                 eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
453 
454         // Defined required feature, not expect UnsupportedOperationException
455         try {
456             mCarrierConfigLoader.getConfigForSubIdWithFeature(DEFAULT_SUB_ID,
457                     PLATFORM_CARRIER_CONFIG_PACKAGE, PLATFORM_CARRIER_CONFIG_FEATURE);
458         } catch (UnsupportedOperationException e) {
459             fail("not expected UnsupportedOperationException");
460         }
461     }
462 
getTestConfig()463     private static PersistableBundle getTestConfig() {
464         PersistableBundle config = new PersistableBundle();
465         config.putInt(CARRIER_CONFIG_EXAMPLE_KEY, CARRIER_CONFIG_EXAMPLE_VALUE);
466         return config;
467     }
468 
setCarrierPrivilegesForSubId(boolean hasCarrierPrivileges, int subId)469     private void setCarrierPrivilegesForSubId(boolean hasCarrierPrivileges, int subId) {
470         TelephonyManager mockTelephonyManager = Mockito.mock(TelephonyManager.class);
471         doReturn(mockTelephonyManager).when(mTelephonyManager).createForSubscriptionId(subId);
472         doReturn(hasCarrierPrivileges ? TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
473                 : TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS).when(
474                 mockTelephonyManager).getCarrierPrivilegeStatus(anyInt());
475     }
476 
477     @Test
testMultiSimConfigChanged()478     public void testMultiSimConfigChanged() throws Exception {
479         replaceInstance(TelephonyManager.class, "sInstance", null, mTelephonyManager);
480         mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
481 
482         // Changed from 1 to 2.
483         doReturn(2).when(mTelephonyManager).getActiveModemCount();
484         doReturn(true).when(mContext).bindService(
485                 any(Intent.class), any(ServiceConnection.class), anyInt());
486         doNothing().when(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class));
487         mHandler.sendMessage(mHandler.obtainMessage(17 /* EVENT_MULTI_SIM_CONFIG_CHANGED */));
488         mTestableLooper.processAllMessages();
489 
490         mCarrierConfigLoader.updateConfigForPhoneId(1, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
491         mTestableLooper.processAllMessages();
492     }
493 }
494