• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 android.telephony.cts;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.assertTrue;
26 import static org.junit.Assert.fail;
27 
28 import android.Manifest;
29 import android.Manifest.permission;
30 import android.app.UiAutomation;
31 import android.bluetooth.BluetoothAdapter;
32 import android.content.ComponentName;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.content.ServiceConnection;
36 import android.content.pm.PackageManager;
37 import android.net.ConnectivityManager;
38 import android.net.wifi.WifiInfo;
39 import android.net.wifi.WifiManager;
40 import android.os.AsyncTask;
41 import android.os.Build;
42 import android.os.IBinder;
43 import android.os.Looper;
44 import android.os.RemoteException;
45 import android.telecom.PhoneAccount;
46 import android.telecom.PhoneAccountHandle;
47 import android.telecom.TelecomManager;
48 import android.telephony.AccessNetworkConstants;
49 import android.telephony.AvailableNetworkInfo;
50 import android.telephony.CellLocation;
51 import android.telephony.NetworkRegistrationInfo;
52 import android.telephony.PhoneStateListener;
53 import android.telephony.ServiceState;
54 import android.telephony.SubscriptionInfo;
55 import android.telephony.SubscriptionManager;
56 import android.telephony.TelephonyManager;
57 import android.telephony.UiccCardInfo;
58 import android.telephony.UiccSlotInfo;
59 import android.telephony.cts.locationaccessingapp.CtsLocationAccessService;
60 import android.telephony.cts.locationaccessingapp.ICtsLocationAccessControl;
61 import android.telephony.emergency.EmergencyNumber;
62 import android.text.TextUtils;
63 import android.util.Log;
64 import android.util.Pair;
65 
66 import androidx.test.InstrumentationRegistry;
67 
68 import com.android.compatibility.common.util.ShellIdentityUtils;
69 import com.android.compatibility.common.util.TestThread;
70 
71 import org.junit.After;
72 import org.junit.Before;
73 import org.junit.Test;
74 
75 import java.util.ArrayList;
76 import java.util.Arrays;
77 import java.util.HashSet;
78 import java.util.List;
79 import java.util.Locale;
80 import java.util.Map;
81 import java.util.Objects;
82 import java.util.Set;
83 import java.util.concurrent.LinkedBlockingQueue;
84 import java.util.concurrent.TimeUnit;
85 import java.util.function.Consumer;
86 import java.util.regex.Pattern;
87 import java.util.stream.Collectors;
88 
89 /**
90  * Build, install and run the tests by running the commands below:
91  *  make cts -j64
92  *  cts-tradefed run cts -m CtsTelephonyTestCases --test android.telephony.cts.TelephonyManagerTest
93  */
94 public class TelephonyManagerTest {
95     private TelephonyManager mTelephonyManager;
96     private SubscriptionManager mSubscriptionManager;
97     private PackageManager mPackageManager;
98     private boolean mOnCellLocationChangedCalled = false;
99     private boolean mServiceStateChangedCalled = false;
100     private boolean mRadioRebootTriggered = false;
101     private boolean mHasRadioPowerOff = false;
102     private ServiceState mServiceState;
103     private final Object mLock = new Object();
104     private static final int TOLERANCE = 1000;
105     private PhoneStateListener mListener;
106     private static ConnectivityManager mCm;
107     private static final String TAG = "TelephonyManagerTest";
108     private static final List<Integer> ROAMING_TYPES = Arrays.asList(
109             ServiceState.ROAMING_TYPE_DOMESTIC,
110             ServiceState.ROAMING_TYPE_INTERNATIONAL,
111             ServiceState.ROAMING_TYPE_NOT_ROAMING,
112             ServiceState.ROAMING_TYPE_UNKNOWN);
113     private static final List<Integer> NETWORK_TYPES = Arrays.asList(
114             TelephonyManager.NETWORK_TYPE_UNKNOWN,
115             TelephonyManager.NETWORK_TYPE_GPRS,
116             TelephonyManager.NETWORK_TYPE_EDGE,
117             TelephonyManager.NETWORK_TYPE_UMTS,
118             TelephonyManager.NETWORK_TYPE_CDMA,
119             TelephonyManager.NETWORK_TYPE_EVDO_0,
120             TelephonyManager.NETWORK_TYPE_EVDO_A,
121             TelephonyManager.NETWORK_TYPE_1xRTT,
122             TelephonyManager.NETWORK_TYPE_HSDPA,
123             TelephonyManager.NETWORK_TYPE_HSUPA,
124             TelephonyManager.NETWORK_TYPE_HSPA,
125             TelephonyManager.NETWORK_TYPE_IDEN,
126             TelephonyManager.NETWORK_TYPE_EVDO_B,
127             TelephonyManager.NETWORK_TYPE_LTE,
128             TelephonyManager.NETWORK_TYPE_EHRPD,
129             TelephonyManager.NETWORK_TYPE_HSPAP,
130             TelephonyManager.NETWORK_TYPE_GSM,
131             TelephonyManager.NETWORK_TYPE_TD_SCDMA,
132             TelephonyManager.NETWORK_TYPE_IWLAN,
133             TelephonyManager.NETWORK_TYPE_LTE_CA,
134             TelephonyManager.NETWORK_TYPE_NR);
135 
136     private static final int EMERGENCY_NUMBER_SOURCE_RIL_ECCLIST = 0;
137     private static final Set<Integer> EMERGENCY_NUMBER_SOURCE_SET;
138     static {
139         EMERGENCY_NUMBER_SOURCE_SET = new HashSet<Integer>();
140         EMERGENCY_NUMBER_SOURCE_SET.add(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING);
141         EMERGENCY_NUMBER_SOURCE_SET.add(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_SIM);
142         EMERGENCY_NUMBER_SOURCE_SET.add(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE);
143         EMERGENCY_NUMBER_SOURCE_SET.add(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG);
144         EMERGENCY_NUMBER_SOURCE_SET.add(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DEFAULT);
145     }
146 
147     private static final Set<Integer> EMERGENCY_SERVICE_CATEGORY_SET;
148     static {
149         EMERGENCY_SERVICE_CATEGORY_SET = new HashSet<Integer>();
150         EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE);
151         EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_AMBULANCE);
152         EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE);
153         EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD);
154         EMERGENCY_SERVICE_CATEGORY_SET.add(
155                 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE);
156         EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MIEC);
157         EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_AIEC);
158     }
159 
160     @Before
setUp()161     public void setUp() throws Exception {
162         mTelephonyManager =
163                 (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
164         mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
165         mSubscriptionManager = (SubscriptionManager) getContext()
166                 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
167         mPackageManager = getContext().getPackageManager();
168     }
169 
170     @After
tearDown()171     public void tearDown() throws Exception {
172         if (mListener != null) {
173             // unregister the listener
174             mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
175         }
176     }
177 
grantLocationPermissions()178     public static void grantLocationPermissions() {
179         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
180         String packageName = getContext().getPackageName();
181         uiAutomation.grantRuntimePermission(packageName, permission.ACCESS_COARSE_LOCATION);
182         uiAutomation.grantRuntimePermission(packageName, permission.ACCESS_FINE_LOCATION);
183         uiAutomation.grantRuntimePermission(packageName, permission.ACCESS_BACKGROUND_LOCATION);
184     }
185 
186     @Test
testListen()187     public void testListen() throws Throwable {
188         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
189             Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
190             return;
191         }
192 
193         if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
194             // TODO: temp workaround, need to adjust test to for CDMA
195             return;
196         }
197 
198         grantLocationPermissions();
199 
200         TestThread t = new TestThread(new Runnable() {
201             public void run() {
202                 Looper.prepare();
203                 mListener = new PhoneStateListener() {
204                     @Override
205                     public void onCellLocationChanged(CellLocation location) {
206                         if(!mOnCellLocationChangedCalled) {
207                             synchronized (mLock) {
208                                 mOnCellLocationChangedCalled = true;
209                                 mLock.notify();
210                             }
211                         }
212                     }
213                 };
214 
215                 synchronized (mLock) {
216                     mLock.notify(); // mListener is ready
217                 }
218 
219                 Looper.loop();
220             }
221         });
222 
223         synchronized (mLock) {
224             t.start();
225             mLock.wait(TOLERANCE); // wait for mListener
226         }
227 
228         // Test register
229         synchronized (mLock) {
230             // .listen generates an onCellLocationChanged event
231             mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_CELL_LOCATION);
232             mLock.wait(TOLERANCE);
233 
234             assertTrue("Test register, mOnCellLocationChangedCalled should be true.",
235                 mOnCellLocationChangedCalled);
236         }
237 
238         synchronized (mLock) {
239             mOnCellLocationChangedCalled = false;
240             CellLocation.requestLocationUpdate();
241             mLock.wait(TOLERANCE);
242 
243             assertTrue("Test register, mOnCellLocationChangedCalled should be true.",
244                 mOnCellLocationChangedCalled);
245         }
246 
247         // unregister the listener
248         mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
249         Thread.sleep(TOLERANCE);
250 
251         // Test unregister
252         synchronized (mLock) {
253             mOnCellLocationChangedCalled = false;
254             // unregister again, to make sure doing so does not call the listener
255             mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
256             CellLocation.requestLocationUpdate();
257             mLock.wait(TOLERANCE);
258 
259             assertFalse("Test unregister, mOnCellLocationChangedCalled should be false.",
260                 mOnCellLocationChangedCalled);
261         }
262     }
263 
264     /**
265      * The getter methods here are all related to the information about the telephony.
266      * These getters are related to concrete location, phone, service provider company, so
267      * it's no need to get details of these information, just make sure they are in right
268      * condition(>0 or not null).
269      */
270     @Test
testTelephonyManager()271     public void testTelephonyManager() {
272         assertTrue(mTelephonyManager.getNetworkType() >= TelephonyManager.NETWORK_TYPE_UNKNOWN);
273         assertTrue(mTelephonyManager.getPhoneType() >= TelephonyManager.PHONE_TYPE_NONE);
274         assertTrue(mTelephonyManager.getSimState() >= TelephonyManager.SIM_STATE_UNKNOWN);
275         assertTrue(mTelephonyManager.getDataActivity() >= TelephonyManager.DATA_ACTIVITY_NONE);
276         assertTrue(mTelephonyManager.getDataState() >= TelephonyManager.DATA_DISCONNECTED);
277         assertTrue(mTelephonyManager.getCallState() >= TelephonyManager.CALL_STATE_IDLE);
278 
279         for (int i = 0; i < mTelephonyManager.getPhoneCount(); ++i) {
280             assertTrue(mTelephonyManager.getSimState(i) >= TelephonyManager.SIM_STATE_UNKNOWN);
281         }
282 
283         // Make sure devices without MMS service won't fail on this
284         if (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE) {
285             assertFalse(mTelephonyManager.getMmsUserAgent().isEmpty());
286             assertFalse(mTelephonyManager.getMmsUAProfUrl().isEmpty());
287         }
288 
289         // The following methods may return any value depending on the state of the device. Simply
290         // call them to make sure they do not throw any exceptions.
291         mTelephonyManager.getVoiceMailNumber();
292         mTelephonyManager.getSimOperatorName();
293         mTelephonyManager.getNetworkCountryIso();
294         mTelephonyManager.getCellLocation();
295         mTelephonyManager.getSimCarrierId();
296         mTelephonyManager.getSimCarrierIdName();
297         mTelephonyManager.getSimSpecificCarrierId();
298         mTelephonyManager.getSimSpecificCarrierIdName();
299         mTelephonyManager.getCarrierIdFromSimMccMnc();
300         mTelephonyManager.isDataRoamingEnabled();
301         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
302                 (tm) -> tm.getSimSerialNumber());
303         mTelephonyManager.getSimOperator();
304         mTelephonyManager.getSignalStrength();
305         mTelephonyManager.getNetworkOperatorName();
306         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
307                 (tm) -> tm.getSubscriberId());
308         mTelephonyManager.getLine1Number();
309         mTelephonyManager.getNetworkOperator();
310         mTelephonyManager.getSimCountryIso();
311         mTelephonyManager.getVoiceMailAlphaTag();
312         mTelephonyManager.isNetworkRoaming();
313         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
314                 (tm) -> tm.getDeviceId());
315         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
316                 (tm) -> tm.getDeviceId(mTelephonyManager.getSlotIndex()));
317         mTelephonyManager.getDeviceSoftwareVersion();
318         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
319                 (tm) -> tm.getImei());
320         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
321                 (tm) -> tm.getImei(mTelephonyManager.getSlotIndex()));
322         mTelephonyManager.getPhoneCount();
323         mTelephonyManager.getDataEnabled();
324         mTelephonyManager.getNetworkSpecifier();
325         mTelephonyManager.getNai();
326         TelecomManager telecomManager = (TelecomManager) getContext()
327                 .getSystemService(Context.TELECOM_SERVICE);
328         PhoneAccountHandle defaultAccount = telecomManager
329                 .getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
330         mTelephonyManager.getVoicemailRingtoneUri(defaultAccount);
331         mTelephonyManager.isVoicemailVibrationEnabled(defaultAccount);
332         mTelephonyManager.getCarrierConfig();
333     }
334 
335     @Test
testCellLocationFinePermission()336     public void testCellLocationFinePermission() {
337         withRevokedPermission(() -> {
338             try {
339                 CellLocation cellLocation = (CellLocation) performLocationAccessCommand(
340                         CtsLocationAccessService.COMMAND_GET_CELL_LOCATION);
341                 assertTrue(cellLocation == null || cellLocation.isEmpty());
342             } catch (SecurityException e) {
343                 // expected
344             }
345 
346             try {
347                 List cis = (List) performLocationAccessCommand(
348                         CtsLocationAccessService.COMMAND_GET_CELL_INFO);
349                 assertTrue(cis == null || cis.isEmpty());
350             } catch (SecurityException e) {
351                 // expected
352             }
353         }, Manifest.permission.ACCESS_FINE_LOCATION);
354     }
355 
356     @Test
testServiceStateLocationSanitization()357     public void testServiceStateLocationSanitization() {
358         withRevokedPermission(() -> {
359                     ServiceState ss = (ServiceState) performLocationAccessCommand(
360                             CtsLocationAccessService.COMMAND_GET_SERVICE_STATE);
361                     assertServiceStateSanitization(ss, true);
362 
363                     withRevokedPermission(() -> {
364                                 ServiceState ss1 = (ServiceState) performLocationAccessCommand(
365                                         CtsLocationAccessService.COMMAND_GET_SERVICE_STATE);
366                                 assertServiceStateSanitization(ss1, false);
367                             },
368                             Manifest.permission.ACCESS_COARSE_LOCATION);
369                 },
370                 Manifest.permission.ACCESS_FINE_LOCATION);
371     }
372 
373     @Test
testServiceStateListeningWithoutPermissions()374     public void testServiceStateListeningWithoutPermissions() {
375             if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) return;
376 
377             withRevokedPermission(() -> {
378                     ServiceState ss = (ServiceState) performLocationAccessCommand(
379                             CtsLocationAccessService.COMMAND_GET_SERVICE_STATE_FROM_LISTENER);
380                     assertServiceStateSanitization(ss, true);
381 
382                     withRevokedPermission(() -> {
383                                 ServiceState ss1 = (ServiceState) performLocationAccessCommand(
384                                         CtsLocationAccessService
385                                                 .COMMAND_GET_SERVICE_STATE_FROM_LISTENER);
386                                 assertServiceStateSanitization(ss1, false);
387                             },
388                             Manifest.permission.ACCESS_COARSE_LOCATION);
389                 },
390                 Manifest.permission.ACCESS_FINE_LOCATION);
391     }
392 
393     @Test
testRegistryPermissionsForCellLocation()394     public void testRegistryPermissionsForCellLocation() {
395         withRevokedPermission(() -> {
396                     CellLocation cellLocation = (CellLocation) performLocationAccessCommand(
397                             CtsLocationAccessService.COMMAND_LISTEN_CELL_LOCATION);
398                     assertNull(cellLocation);
399                 },
400                 Manifest.permission.ACCESS_FINE_LOCATION);
401     }
402 
403     @Test
testRegistryPermissionsForCellInfo()404     public void testRegistryPermissionsForCellInfo() {
405         withRevokedPermission(() -> {
406                     CellLocation cellLocation = (CellLocation) performLocationAccessCommand(
407                             CtsLocationAccessService.COMMAND_LISTEN_CELL_INFO);
408                     assertNull(cellLocation);
409                 },
410                 Manifest.permission.ACCESS_FINE_LOCATION);
411     }
412 
getLocationAccessAppControl()413     private ICtsLocationAccessControl getLocationAccessAppControl() {
414         Intent bindIntent = new Intent(CtsLocationAccessService.CONTROL_ACTION);
415         bindIntent.setComponent(new ComponentName(CtsLocationAccessService.class.getPackageName$(),
416                 CtsLocationAccessService.class.getName()));
417 
418         LinkedBlockingQueue<ICtsLocationAccessControl> pipe =
419                 new LinkedBlockingQueue<>();
420         getContext().bindService(bindIntent, new ServiceConnection() {
421             @Override
422             public void onServiceConnected(ComponentName name, IBinder service) {
423                 pipe.offer(ICtsLocationAccessControl.Stub.asInterface(service));
424             }
425 
426             @Override
427             public void onServiceDisconnected(ComponentName name) {
428 
429             }
430         }, Context.BIND_AUTO_CREATE);
431 
432         try {
433             return pipe.poll(TOLERANCE, TimeUnit.MILLISECONDS);
434         } catch (InterruptedException e) {
435             fail("interrupted");
436         }
437         fail("Unable to connect to location access test app");
438         return null;
439     }
440 
performLocationAccessCommand(String command)441     private Object performLocationAccessCommand(String command) {
442         ICtsLocationAccessControl control = getLocationAccessAppControl();
443         try {
444             List ret = control.performCommand(command);
445             if (!ret.isEmpty()) return ret.get(0);
446         } catch (RemoteException e) {
447             fail("Remote exception");
448         }
449         return null;
450     }
451 
withRevokedPermission(Runnable r, String permission)452     private void withRevokedPermission(Runnable r, String permission) {
453         InstrumentationRegistry.getInstrumentation()
454                 .getUiAutomation().revokeRuntimePermission(
455                 CtsLocationAccessService.class.getPackageName$(), permission);
456         try {
457             r.run();
458         } finally {
459             InstrumentationRegistry.getInstrumentation()
460                     .getUiAutomation().grantRuntimePermission(
461                     CtsLocationAccessService.class.getPackageName$(), permission);
462         }
463     }
464 
assertServiceStateSanitization(ServiceState state, boolean sanitizedForFineOnly)465     private void assertServiceStateSanitization(ServiceState state, boolean sanitizedForFineOnly) {
466         if (state == null) return;
467 
468         if (state.getNetworkRegistrationInfoList() != null) {
469             for (NetworkRegistrationInfo nrs : state.getNetworkRegistrationInfoList()) {
470                 assertNull(nrs.getCellIdentity());
471             }
472         }
473 
474         if (sanitizedForFineOnly) return;
475 
476         assertTrue(TextUtils.isEmpty(state.getDataOperatorAlphaLong()));
477         assertTrue(TextUtils.isEmpty(state.getDataOperatorAlphaShort()));
478         assertTrue(TextUtils.isEmpty(state.getDataOperatorNumeric()));
479         assertTrue(TextUtils.isEmpty(state.getVoiceOperatorAlphaLong()));
480         assertTrue(TextUtils.isEmpty(state.getVoiceOperatorAlphaShort()));
481         assertTrue(TextUtils.isEmpty(state.getVoiceOperatorNumeric()));
482     }
483 
484     @Test
testGetRadioHalVersion()485     public void testGetRadioHalVersion() {
486         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
487             Log.d(TAG,"skipping test on device without FEATURE_TELEPHONY present");
488             return;
489         }
490 
491         Pair<Integer, Integer> version = mTelephonyManager.getRadioHalVersion();
492 
493         // The version must be valid, and the versions start with 1.0
494         assertFalse("Invalid Radio HAL Version: " + version,
495                 version.first < 1 || version.second < 0);
496     }
497 
498     @Test
testCreateForPhoneAccountHandle()499     public void testCreateForPhoneAccountHandle() {
500         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
501             Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
502             return;
503         }
504         TelecomManager telecomManager = getContext().getSystemService(TelecomManager.class);
505         PhoneAccountHandle handle =
506                 telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
507         TelephonyManager telephonyManager = mTelephonyManager.createForPhoneAccountHandle(handle);
508         String globalSubscriberId = ShellIdentityUtils.invokeMethodWithShellPermissions(
509                 mTelephonyManager, (tm) -> tm.getSubscriberId());
510         String localSubscriberId = ShellIdentityUtils.invokeMethodWithShellPermissions(
511                 telephonyManager, (tm) -> tm.getSubscriberId());
512         assertEquals(globalSubscriberId, localSubscriberId);
513     }
514 
515     @Test
testCreateForPhoneAccountHandle_InvalidHandle()516     public void testCreateForPhoneAccountHandle_InvalidHandle(){
517         PhoneAccountHandle handle =
518                 new PhoneAccountHandle(new ComponentName("com.example.foo", "bar"), "baz");
519         assertNull(mTelephonyManager.createForPhoneAccountHandle(handle));
520     }
521 
522     /**
523      * Tests that the phone count returned is valid.
524      */
525     @Test
testGetPhoneCount()526     public void testGetPhoneCount() {
527         int phoneCount = mTelephonyManager.getPhoneCount();
528         int phoneType = mTelephonyManager.getPhoneType();
529         switch (phoneType) {
530             case TelephonyManager.PHONE_TYPE_GSM:
531             case TelephonyManager.PHONE_TYPE_CDMA:
532                 assertTrue("Phone count should be > 0", phoneCount > 0);
533                 break;
534             case TelephonyManager.PHONE_TYPE_NONE:
535                 assertTrue("Phone count should be 0", phoneCount == 0 || phoneCount == 1);
536                 break;
537             default:
538                 throw new IllegalArgumentException("Did you add a new phone type? " + phoneType);
539         }
540     }
541 
542     /**
543      * Tests that the device properly reports either a valid IMEI, MEID/ESN, or a valid MAC address
544      * if only a WiFi device. At least one of them must be valid.
545      */
546     @Test
testGetDeviceId()547     public void testGetDeviceId() {
548         String deviceId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
549                 (tm) -> tm.getDeviceId());
550         verifyDeviceId(deviceId);
551     }
552 
553     /**
554      * Tests that the device properly reports either a valid IMEI, MEID/ESN, or a valid MAC address
555      * if only a WiFi device. At least one of them must be valid.
556      */
557     @Test
testGetDeviceIdForSlot()558     public void testGetDeviceIdForSlot() {
559         String deviceId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
560                 (tm) -> tm.getDeviceId(mTelephonyManager.getSlotIndex()));
561         verifyDeviceId(deviceId);
562         // Also verify that no exception is thrown for any slot index (including invalid ones)
563         for (int i = -1; i <= mTelephonyManager.getPhoneCount(); i++) {
564             // The compiler error 'local variables referenced from a lambda expression must be final
565             // or effectively final' is reported when using i, so assign it to a final variable.
566             final int currI = i;
567             ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
568                     (tm) -> tm.getDeviceId(currI));
569         }
570     }
571 
verifyDeviceId(String deviceId)572     private void verifyDeviceId(String deviceId) {
573         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
574             // Either IMEI or MEID need to be valid.
575             try {
576                 assertImei(deviceId);
577             } catch (AssertionError e) {
578                 assertMeidEsn(deviceId);
579             }
580         } else if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
581             assertSerialNumber();
582             assertMacAddress(getWifiMacAddress());
583         } else if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
584             assertSerialNumber();
585             assertMacAddress(getBluetoothMacAddress());
586         } else if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET)) {
587             assertTrue(mCm.getNetworkInfo(ConnectivityManager.TYPE_ETHERNET) != null);
588         }
589     }
590 
assertImei(String id)591     private static void assertImei(String id) {
592         assertFalse("Imei should not be empty or null", TextUtils.isEmpty(id));
593         // IMEI may include the check digit
594         String imeiPattern = "[0-9]{14,15}";
595         String invalidPattern = "[0]{14,15}";
596         assertTrue("IMEI " + id + " does not match pattern " + imeiPattern,
597                 Pattern.matches(imeiPattern, id));
598         assertFalse("IMEI " + id + " must not be a zero sequence" + invalidPattern,
599                 Pattern.matches(invalidPattern, id));
600         if (id.length() == 15) {
601             // if the ID is 15 digits, the 15th must be a check digit.
602             assertImeiCheckDigit(id);
603         }
604     }
605 
assertImeiCheckDigit(String deviceId)606     private static void assertImeiCheckDigit(String deviceId) {
607         int expectedCheckDigit = getLuhnCheckDigit(deviceId.substring(0, 14));
608         int actualCheckDigit = Character.digit(deviceId.charAt(14), 10);
609         assertEquals("Incorrect check digit for " + deviceId, expectedCheckDigit, actualCheckDigit);
610     }
611 
612     /**
613      * Use decimal value (0-9) to index into array to get sum of its digits
614      * needed by Lunh check.
615      *
616      * Example: DOUBLE_DIGIT_SUM[6] = 3 because 6 * 2 = 12 => 1 + 2 = 3
617      */
618     private static final int[] DOUBLE_DIGIT_SUM = {0, 2, 4, 6, 8, 1, 3, 5, 7, 9};
619 
620     /**
621      * Calculate the check digit by starting from the right, doubling every
622      * each digit, summing all the digits including the doubled ones, and
623      * finding a number to make the sum divisible by 10.
624      *
625      * @param deviceId not including the check digit
626      * @return the check digit
627      */
getLuhnCheckDigit(String deviceId)628     private static int getLuhnCheckDigit(String deviceId) {
629         int sum = 0;
630         int dontDoubleModulus = deviceId.length() % 2;
631         for (int i = deviceId.length() - 1; i >= 0; --i) {
632             int digit = Character.digit(deviceId.charAt(i), 10);
633             if (i % 2 == dontDoubleModulus) {
634                 sum += digit;
635             } else {
636                 sum += DOUBLE_DIGIT_SUM[digit];
637             }
638         }
639         sum %= 10;
640         return sum == 0 ? 0 : 10 - sum;
641     }
642 
assertMeidEsn(String id)643     private static void assertMeidEsn(String id) {
644         // CDMA device IDs may either be a 14-hex-digit MEID or an
645         // 8-hex-digit ESN.  If it's an ESN, it may not be a
646         // pseudo-ESN.
647         assertFalse("Meid ESN should not be empty or null", TextUtils.isEmpty(id));
648         if (id.length() == 14) {
649             assertMeidFormat(id);
650         } else if (id.length() == 8) {
651             assertHexadecimalEsnFormat(id);
652         } else {
653             fail("device id on CDMA must be 14-digit hex MEID or 8-digit hex ESN.");
654         }
655     }
656 
assertHexadecimalEsnFormat(String deviceId)657     private static void assertHexadecimalEsnFormat(String deviceId) {
658         String esnPattern = "[0-9a-fA-F]{8}";
659         String invalidPattern = "[0]{8}";
660         assertTrue("ESN hex device id " + deviceId + " does not match pattern " + esnPattern,
661                    Pattern.matches(esnPattern, deviceId));
662         assertFalse("ESN hex device id " + deviceId + " must not be a pseudo-ESN",
663                     "80".equals(deviceId.substring(0, 2)));
664         assertFalse("ESN hex device id " + deviceId + "must not be a zero sequence",
665                 Pattern.matches(invalidPattern, deviceId));
666     }
667 
assertMeidFormat(String deviceId)668     private static void assertMeidFormat(String deviceId) {
669         // MEID must NOT include the check digit.
670         String meidPattern = "[0-9a-fA-F]{14}";
671         String invalidPattern = "[0]{14}";
672         assertTrue("MEID device id " + deviceId + " does not match pattern "
673                 + meidPattern, Pattern.matches(meidPattern, deviceId));
674         assertFalse("MEID device id " + deviceId + "must not be a zero sequence",
675                 Pattern.matches(invalidPattern, deviceId));
676     }
677 
assertSerialNumber()678     private void assertSerialNumber() {
679         String serial = ShellIdentityUtils.invokeStaticMethodWithShellPermissions(
680                Build::getSerial);
681         assertNotNull("Non-telephony devices must have a Build.getSerial() number.",
682                 serial);
683         assertTrue("Hardware id must be no longer than 20 characters.",
684                 serial.length() <= 20);
685         assertTrue("Hardware id must be alphanumeric.",
686                 Pattern.matches("[0-9A-Za-z]+", serial));
687     }
688 
assertMacAddress(String macAddress)689     private void assertMacAddress(String macAddress) {
690         String macPattern = "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}";
691         assertTrue("MAC Address " + macAddress + " does not match pattern " + macPattern,
692                 Pattern.matches(macPattern, macAddress));
693     }
694 
695     /** @return mac address which requires the WiFi system to be enabled */
getWifiMacAddress()696     private String getWifiMacAddress() {
697         WifiManager wifiManager = (WifiManager) getContext()
698                 .getSystemService(Context.WIFI_SERVICE);
699 
700         boolean enabled = wifiManager.isWifiEnabled();
701 
702         try {
703             if (!enabled) {
704                 wifiManager.setWifiEnabled(true);
705             }
706 
707             WifiInfo wifiInfo = wifiManager.getConnectionInfo();
708             return wifiInfo.getMacAddress();
709 
710         } finally {
711             if (!enabled) {
712                 wifiManager.setWifiEnabled(false);
713             }
714         }
715     }
716 
getBluetoothMacAddress()717     private String getBluetoothMacAddress() {
718         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
719         if (adapter == null) {
720             return "";
721         }
722 
723         return adapter.getAddress();
724     }
725 
726     private static final String ISO_COUNTRY_CODE_PATTERN = "[a-z]{2}";
727 
728     @Test
testGetNetworkCountryIso()729     public void testGetNetworkCountryIso() {
730         String countryCode = mTelephonyManager.getNetworkCountryIso();
731         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
732             assertTrue("Country code '" + countryCode + "' did not match "
733                     + ISO_COUNTRY_CODE_PATTERN,
734                     Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
735         } else {
736             // Non-telephony may still have the property defined if it has a SIM.
737         }
738     }
739 
740     @Test
testGetSimCountryIso()741     public void testGetSimCountryIso() {
742         String countryCode = mTelephonyManager.getSimCountryIso();
743         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
744             assertTrue("Country code '" + countryCode + "' did not match "
745                     + ISO_COUNTRY_CODE_PATTERN,
746                     Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
747         } else {
748             // Non-telephony may still have the property defined if it has a SIM.
749         }
750     }
751 
752     @Test
testGetServiceState()753     public void testGetServiceState() throws InterruptedException {
754         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
755             Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
756             return;
757         }
758 
759         TestThread t = new TestThread(new Runnable() {
760             public void run() {
761                 Looper.prepare();
762 
763                 mListener = new PhoneStateListener() {
764                     @Override
765                     public void onServiceStateChanged(ServiceState serviceState) {
766                         synchronized (mLock) {
767                             mServiceState = serviceState;
768                             mLock.notify();
769                         }
770                     }
771                 };
772                 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_SERVICE_STATE);
773                 Looper.loop();
774             }
775         });
776 
777         synchronized (mLock) {
778             t.start();
779             mLock.wait(TOLERANCE);
780         }
781 
782         assertEquals(mServiceState, mTelephonyManager.getServiceState());
783     }
784 
785     @Test
testGetSimLocale()786     public void testGetSimLocale() throws InterruptedException {
787         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
788             Log.d(TAG,"skipping test that requires Telephony");
789             return;
790         }
791         if (SubscriptionManager.getDefaultSubscriptionId()
792                 == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
793             fail("Expected SIM inserted");
794         }
795         Locale locale = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
796                 (tm) -> tm.getSimLocale());
797         Log.d(TAG, "testGetSimLocale: " + locale);
798         assertNotNull(locale);
799     }
800 
801     /**
802      * Tests that a GSM device properly reports either the correct TAC (type allocation code) or
803      * null.
804      * The TAC should match the first 8 digits of the IMEI.
805      */
806     @Test
testGetTac()807     public void testGetTac() {
808         String tac = mTelephonyManager.getTypeAllocationCode();
809         String imei = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
810                 (tm) -> tm.getImei());
811 
812         if (tac == null || imei == null) {
813             return;
814         }
815 
816         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
817             if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
818                 assertEquals(imei.substring(0, 8), tac);
819             }
820         }
821     }
822 
823     /**
824      * Tests that a CDMA device properly reports either the correct MC (manufacturer code) or null.
825      * The MC should match the first 8 digits of the MEID.
826      */
827     @Test
testGetMc()828     public void testGetMc() {
829         String mc = mTelephonyManager.getManufacturerCode();
830         String meid = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
831                 (tm) -> tm.getMeid());
832 
833         if (mc == null || meid == null) {
834             return;
835         }
836 
837         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
838             if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
839                 assertEquals(meid.substring(0, 8), mc);
840             }
841         }
842     }
843 
844     /**
845      * Tests that the device properly reports either a valid IMEI or null.
846      */
847     @Test
testGetImei()848     public void testGetImei() {
849         String imei = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
850                 (tm) -> tm.getImei());
851 
852         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
853             if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
854                 assertImei(imei);
855             }
856         }
857     }
858 
859     /**
860      * Tests that the device properly reports either a valid IMEI or null.
861      */
862     @Test
testGetImeiForSlot()863     public void testGetImeiForSlot() {
864         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
865             return;
866         }
867 
868         for (int i = 0; i < mTelephonyManager.getPhoneCount(); i++) {
869             // The compiler error 'local variables referenced from a lambda expression must be final
870             // or effectively final' is reported when using i, so assign it to a final variable.
871             final int currI = i;
872             String imei = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
873                     (tm) -> tm.getImei(currI));
874             if (!TextUtils.isEmpty(imei)) {
875                 assertImei(imei);
876             }
877         }
878 
879         // Also verify that no exception is thrown for any slot index (including invalid ones)
880         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
881                 (tm) -> tm.getImei(-1));
882         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
883                 (tm) -> tm.getImei(mTelephonyManager.getPhoneCount()));
884     }
885 
886     /**
887      * Verifies that {@link TelephonyManager#getRadioPowerState()} does not throw any exception
888      * and returns radio on.
889      */
890     @Test
testGetRadioPowerState()891     public void testGetRadioPowerState() {
892         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
893             return;
894         }
895 
896         // Also verify that no exception is thrown.
897         assertThat(mTelephonyManager.getRadioPowerState()).isEqualTo(
898                 TelephonyManager.RADIO_POWER_ON);
899     }
900 
901     /**
902      * Verifies that {@link TelephonyManager#setCarrierDataEnabled(boolean)} does not throw any
903      * exception. TODO enhance later if we have an API to get data enabled state.
904      */
905     @Test
testSetCarrierDataEnabled()906     public void testSetCarrierDataEnabled() {
907         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
908             return;
909         }
910         // Also verify that no exception is thrown.
911         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
912                 (tm) -> tm.setCarrierDataEnabled(false));
913         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
914                 (tm) -> tm.setCarrierDataEnabled(true));
915     }
916 
917     /**
918      * Verifies that {@link TelephonyManager#rebootRadio()} does not throw any exception
919      * and final radio state is radio power on.
920      */
921     @Test
testRebootRadio()922     public void testRebootRadio() throws Throwable {
923         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
924             return;
925         }
926         assertEquals(mTelephonyManager.getServiceState().getState(), ServiceState.STATE_IN_SERVICE);
927 
928         TestThread t = new TestThread(new Runnable() {
929             public void run() {
930                 Looper.prepare();
931 
932                 mListener = new PhoneStateListener() {
933                     @Override
934                     public void onRadioPowerStateChanged(
935                             @TelephonyManager.RadioPowerState int state) {
936                         synchronized (mLock) {
937                             if (state == TelephonyManager.RADIO_POWER_ON && mHasRadioPowerOff) {
938                                 mRadioRebootTriggered = true;
939                                 mLock.notify();
940                             } else if (state == TelephonyManager.RADIO_POWER_OFF) {
941                                 // reboot must go to power off
942                                 mHasRadioPowerOff = true;
943                             }
944                         }
945                     }
946                 };
947                 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
948                         (tm) -> tm.listen(mListener,
949                                 PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED));
950                 Looper.loop();
951             }
952         });
953 
954         assertThat(mTelephonyManager.getRadioPowerState()).isEqualTo(
955                 TelephonyManager.RADIO_POWER_ON);
956         assertThat(mRadioRebootTriggered).isFalse();
957         assertThat(mHasRadioPowerOff).isFalse();
958         boolean success = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
959                 (tm) -> tm.rebootRadio());
960         //skip this test if not supported or unsuccessful (success=false)
961         if(!success) {
962             return;
963         }
964 
965         t.start();
966         synchronized (mLock) {
967             // reboot takes longer time
968             if (!mRadioRebootTriggered) {
969                 mLock.wait(10000);
970             }
971         }
972         assertThat(mTelephonyManager.getRadioPowerState()).isEqualTo(
973                 TelephonyManager.RADIO_POWER_ON);
974         assertThat(mRadioRebootTriggered).isTrue();
975 
976         // note, other telephony states might not resumes properly at this point. e.g, service state
977         // might still in the transition from OOS to In service. Thus we need to wait for in
978         // service state before running next tests.
979         t = new TestThread(new Runnable() {
980             public void run() {
981                 Looper.prepare();
982 
983                 mListener = new PhoneStateListener() {
984                     @Override
985                     public void onServiceStateChanged(ServiceState serviceState) {
986                         synchronized (mLock) {
987                             if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
988                                 mServiceStateChangedCalled = true;
989                                 mLock.notify();
990                             }
991                         }
992                     }
993                 };
994                 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
995                         (tm) -> tm.listen(mListener, PhoneStateListener.LISTEN_SERVICE_STATE));
996                 Looper.loop();
997             }
998         });
999 
1000         synchronized (mLock) {
1001             t.start();
1002             if (!mServiceStateChangedCalled) {
1003                 mLock.wait(10000);
1004             }
1005         }
1006         assertThat(mTelephonyManager.getServiceState().getState()).isEqualTo(
1007                 ServiceState.STATE_IN_SERVICE);
1008     }
1009 
1010     /**
1011      * Verifies that {@link TelephonyManager#getAidForAppType(int)} does not throw any exception
1012      * for all supported subscription app type.
1013      */
1014     @Test
testGetAidForAppType()1015     public void testGetAidForAppType() {
1016         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1017             return;
1018         }
1019         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1020                 (tm) -> tm.getAidForAppType(TelephonyManager.APPTYPE_SIM));
1021         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1022                 (tm) -> tm.getAidForAppType(TelephonyManager.APPTYPE_CSIM));
1023         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1024                 (tm) -> tm.getAidForAppType(TelephonyManager.APPTYPE_RUIM));
1025         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1026                 (tm) -> tm.getAidForAppType(TelephonyManager.APPTYPE_ISIM));
1027         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1028                 (tm) -> tm.getAidForAppType(TelephonyManager.APPTYPE_USIM));
1029     }
1030 
1031     /**
1032      * Verifies that {@link TelephonyManager#getIsimDomain()} does not throw any exception
1033      */
1034     @Test
testGetIsimDomain()1035     public void testGetIsimDomain() {
1036         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1037             return;
1038         }
1039         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1040                 (tm) -> tm.getIsimDomain());
1041     }
1042 
1043     /**
1044      * Basic test to ensure {@link NetworkRegistrationInfo#isRoaming()} does not throw any
1045      * exception.
1046      */
1047     @Test
testNetworkRegistrationInfoIsRoaming()1048     public void testNetworkRegistrationInfoIsRoaming() {
1049         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1050             return;
1051         }
1052         // get NetworkRegistration object
1053         NetworkRegistrationInfo nwReg = mTelephonyManager.getServiceState()
1054                 .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS,
1055                         AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1056         assertThat(nwReg).isNotNull();
1057         nwReg.isRoaming();
1058     }
1059 
1060     /**
1061      * Basic test to ensure {@link NetworkRegistrationInfo#getRoamingType()} ()} does not throw any
1062      * exception and returns valid result
1063      * @see ServiceState.RoamingType
1064      */
1065     @Test
testNetworkRegistrationInfoGetRoamingType()1066     public void testNetworkRegistrationInfoGetRoamingType() {
1067         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1068             return;
1069         }
1070         // get NetworkRegistration object for voice
1071         NetworkRegistrationInfo nwReg = mTelephonyManager.getServiceState()
1072                 .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS,
1073                         AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1074         assertNotNull(nwReg);
1075         assertThat(nwReg.getRoamingType()).isIn(ROAMING_TYPES);
1076 
1077         // getNetworkRegistration object for data
1078         // get NetworkRegistration object for voice
1079         nwReg = mTelephonyManager.getServiceState()
1080                 .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
1081                         AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1082         assertThat(nwReg).isNotNull();
1083         assertThat(nwReg.getRoamingType()).isIn(ROAMING_TYPES);
1084     }
1085 
1086     /**
1087      * Basic test to ensure {@link NetworkRegistrationInfo#getAccessNetworkTechnology()} not
1088      * throw any exception and returns valid result
1089      * @see TelephonyManager.NetworkType
1090      */
1091     @Test
testNetworkRegistationStateGetAccessNetworkTechnology()1092     public void testNetworkRegistationStateGetAccessNetworkTechnology() {
1093         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1094             return;
1095         }
1096         // get NetworkRegistration object for voice
1097         NetworkRegistrationInfo nwReg = mTelephonyManager.getServiceState()
1098                 .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS,
1099                         AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1100         assertThat(nwReg).isNotNull();
1101         assertThat(nwReg.getAccessNetworkTechnology()).isIn(NETWORK_TYPES);
1102 
1103         // get NetworkRegistation object for data
1104         nwReg = mTelephonyManager.getServiceState()
1105                 .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
1106                         AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1107         assertThat(nwReg).isNotNull();
1108         assertThat(nwReg.getAccessNetworkTechnology()).isIn(NETWORK_TYPES);
1109     }
1110 
1111 
1112     /**
1113      * Tests that the device properly reports either a valid MEID or null.
1114      */
1115     @Test
testGetMeid()1116     public void testGetMeid() {
1117         String meid = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1118                 (tm) -> tm.getMeid());
1119 
1120         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1121             if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
1122                 assertMeidEsn(meid);
1123             }
1124         }
1125     }
1126 
1127     /**
1128      * Tests that the device properly reports either a valid MEID or null.
1129      */
1130     @Test
testGetMeidForSlot()1131     public void testGetMeidForSlot() {
1132         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1133             return;
1134         }
1135 
1136         SubscriptionManager sm = (SubscriptionManager) getContext()
1137                 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
1138         List<SubscriptionInfo> subInfos = sm.getActiveSubscriptionInfoList();
1139 
1140         if (subInfos != null) {
1141             for (SubscriptionInfo subInfo : subInfos) {
1142                 int slotIndex = subInfo.getSimSlotIndex();
1143                 int subId = subInfo.getSubscriptionId();
1144                 TelephonyManager tm = mTelephonyManager.createForSubscriptionId(subId);
1145                 if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
1146                     String meid = ShellIdentityUtils.invokeMethodWithShellPermissions(
1147                             mTelephonyManager,
1148                             (telephonyManager) -> telephonyManager.getMeid(slotIndex));
1149 
1150                     if (!TextUtils.isEmpty(meid)) {
1151                         assertMeidEsn(meid);
1152                     }
1153                 }
1154             }
1155         }
1156 
1157         // Also verify that no exception is thrown for any slot index (including invalid ones)
1158         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1159                 (tm) -> tm.getMeid(-1));
1160         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1161                 (tm) -> tm.getMeid(mTelephonyManager.getPhoneCount()));
1162     }
1163 
1164     /**
1165      * Tests sendDialerSpecialCode API.
1166      * Expects a security exception since the caller does not have carrier privileges or is not the
1167      * current default dialer app.
1168      */
1169     @Test
testSendDialerSpecialCode()1170     public void testSendDialerSpecialCode() {
1171         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1172             Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
1173             return;
1174         }
1175         try {
1176             mTelephonyManager.sendDialerSpecialCode("4636");
1177             fail("Expected SecurityException. App does not have carrier privileges or is not the "
1178                     + "default dialer app");
1179         } catch (SecurityException expected) {
1180         }
1181     }
1182 
1183     /**
1184      * Tests that the device properly reports the contents of EF_FPLMN or null
1185      */
1186     @Test
testGetForbiddenPlmns()1187     public void testGetForbiddenPlmns() {
1188         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1189             return;
1190         }
1191         String[] plmns = mTelephonyManager.getForbiddenPlmns();
1192 
1193         int phoneType = mTelephonyManager.getPhoneType();
1194         switch (phoneType) {
1195             case TelephonyManager.PHONE_TYPE_GSM:
1196                 assertNotNull("Forbidden PLMNs must be valid or an empty list!", plmns);
1197             case TelephonyManager.PHONE_TYPE_CDMA:
1198             case TelephonyManager.PHONE_TYPE_NONE:
1199                 if (plmns == null) {
1200                     return;
1201                 }
1202         }
1203 
1204         for(String plmn : plmns) {
1205             assertTrue(
1206                     "Invalid Length for PLMN-ID, must be 5 or 6! plmn=" + plmn,
1207                     plmn.length() >= 5 && plmn.length() <= 6);
1208             assertTrue(
1209                     "PLMNs must be strings of digits 0-9! plmn=" + plmn,
1210                     android.text.TextUtils.isDigitsOnly(plmn));
1211         }
1212     }
1213 
1214     /**
1215      * Verify that TelephonyManager.getCardIdForDefaultEuicc returns a positive value or either
1216      * UNINITIALIZED_CARD_ID or UNSUPPORTED_CARD_ID.
1217      */
1218     @Test
testGetCardIdForDefaultEuicc()1219     public void testGetCardIdForDefaultEuicc() {
1220         int cardId = mTelephonyManager.getCardIdForDefaultEuicc();
1221         assertTrue("Card ID for default EUICC is not a valid value",
1222                 cardId == TelephonyManager.UNSUPPORTED_CARD_ID
1223                 || cardId == TelephonyManager.UNINITIALIZED_CARD_ID
1224                 || cardId >= 0);
1225     }
1226 
1227     /**
1228      * Tests that a SecurityException is thrown when trying to access UiccCardsInfo.
1229      */
1230     @Test
testGetUiccCardsInfo()1231     public void testGetUiccCardsInfo() {
1232         try {
1233             // Requires READ_PRIVILEGED_PHONE_STATE or carrier privileges
1234             List<UiccCardInfo> infos = mTelephonyManager.getUiccCardsInfo();
1235             fail("Expected SecurityException. App does not have carrier privileges");
1236         } catch (SecurityException e) {
1237         }
1238     }
1239 
getContext()1240     private static Context getContext() {
1241         return InstrumentationRegistry.getContext();
1242     }
1243 
1244     /**
1245      * Tests that the device properly sets the network selection mode to automatic.
1246      * Expects a security exception since the caller does not have carrier privileges.
1247      */
1248     @Test
testSetNetworkSelectionModeAutomatic()1249     public void testSetNetworkSelectionModeAutomatic() {
1250         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1251             Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
1252             return;
1253         }
1254         try {
1255             mTelephonyManager.setNetworkSelectionModeAutomatic();
1256             fail("Expected SecurityException. App does not have carrier privileges.");
1257         } catch (SecurityException expected) {
1258         }
1259     }
1260 
1261     /**
1262      * Tests that the device properly asks the radio to connect to the input network and change
1263      * selection mode to manual.
1264      * Expects a security exception since the caller does not have carrier privileges.
1265      */
1266     @Test
testSetNetworkSelectionModeManual()1267     public void testSetNetworkSelectionModeManual() {
1268         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1269             Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
1270             return;
1271         }
1272         try {
1273             mTelephonyManager.setNetworkSelectionModeManual(
1274                     "" /* operatorNumeric */, false /* persistSelection */);
1275             fail("Expected SecurityException. App does not have carrier privileges.");
1276         } catch (SecurityException expected) {
1277         }
1278     }
1279 
1280     /**
1281      * Tests TelephonyManager.getEmergencyNumberList.
1282      */
1283     @Test
testGetEmergencyNumberList()1284     public void testGetEmergencyNumberList() {
1285         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1286             return;
1287         }
1288         Map<Integer, List<EmergencyNumber>> emergencyNumberList
1289           = mTelephonyManager.getEmergencyNumberList();
1290 
1291         assertFalse(emergencyNumberList == null);
1292 
1293         checkEmergencyNumberFormat(emergencyNumberList);
1294 
1295         int defaultSubId = mSubscriptionManager.getDefaultSubscriptionId();
1296 
1297         // 112 and 911 should always be available
1298         // Reference: 3gpp 22.101, Section 10 - Emergency Calls
1299         assertTrue(checkIfEmergencyNumberListHasSpecificAddress(
1300             emergencyNumberList.get(defaultSubId), "911"));
1301         assertTrue(checkIfEmergencyNumberListHasSpecificAddress(
1302             emergencyNumberList.get(defaultSubId), "112"));
1303 
1304         // 000, 08, 110, 118, 119, and 999 should be always available when sim is absent
1305         // Reference: 3gpp 22.101, Section 10 - Emergency Calls
1306         if (mTelephonyManager.getPhoneCount() > 0
1307                 && mSubscriptionManager.getSimStateForSlotIndex(0)
1308                     == TelephonyManager.SIM_STATE_ABSENT) {
1309             assertTrue(checkIfEmergencyNumberListHasSpecificAddress(
1310                 emergencyNumberList.get(defaultSubId), "000"));
1311             assertTrue(checkIfEmergencyNumberListHasSpecificAddress(
1312                 emergencyNumberList.get(defaultSubId), "08"));
1313             assertTrue(checkIfEmergencyNumberListHasSpecificAddress(
1314                 emergencyNumberList.get(defaultSubId), "110"));
1315             assertTrue(checkIfEmergencyNumberListHasSpecificAddress(
1316                 emergencyNumberList.get(defaultSubId), "118"));
1317             assertTrue(checkIfEmergencyNumberListHasSpecificAddress(
1318                 emergencyNumberList.get(defaultSubId), "119"));
1319             assertTrue(checkIfEmergencyNumberListHasSpecificAddress(
1320                 emergencyNumberList.get(defaultSubId), "999"));
1321         }
1322     }
1323 
1324     /**
1325      * Tests TelephonyManager.isEmergencyNumber.
1326      */
1327     @Test
testIsEmergencyNumber()1328     public void testIsEmergencyNumber() {
1329         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1330             return;
1331         }
1332         // 112 and 911 should always be available
1333         // Reference: 3gpp 22.101, Section 10 - Emergency Calls
1334         assertTrue(mTelephonyManager.isEmergencyNumber("911"));
1335         assertTrue(mTelephonyManager.isEmergencyNumber("112"));
1336 
1337         // 000, 08, 110, 118, 119, and 999 should be always available when sim is absent
1338         // Reference: 3gpp 22.101, Section 10 - Emergency Calls
1339         if (mTelephonyManager.getPhoneCount() > 0
1340                 && mSubscriptionManager.getSimStateForSlotIndex(0)
1341                     == TelephonyManager.SIM_STATE_ABSENT) {
1342             assertTrue(mTelephonyManager.isEmergencyNumber("000"));
1343             assertTrue(mTelephonyManager.isEmergencyNumber("08"));
1344             assertTrue(mTelephonyManager.isEmergencyNumber("110"));
1345             assertTrue(mTelephonyManager.isEmergencyNumber("118"));
1346             assertTrue(mTelephonyManager.isEmergencyNumber("119"));
1347             assertTrue(mTelephonyManager.isEmergencyNumber("999"));
1348         }
1349     }
1350 
1351     /**
1352      * Tests TelephonyManager.isPotentialEmergencyNumber.
1353      */
1354     @Test
testIsPotentialEmergencyNumber()1355     public void testIsPotentialEmergencyNumber() {
1356         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1357             return;
1358         }
1359 
1360         String countryIso = mTelephonyManager.getNetworkCountryIso();
1361         String potentialEmergencyAddress = "91112345";
1362         // According to com.android.i18n.phonenumbers.ShortNumberInfo, in
1363         // these countries, if extra digits are added to an emergency number,
1364         // it no longer connects to the emergency service.
1365         if (countryIso.equals("br") || countryIso.equals("cl") || countryIso.equals("ni")) {
1366             assertFalse(ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1367                     (tm) -> tm.isPotentialEmergencyNumber(potentialEmergencyAddress)));
1368         } else {
1369             assertTrue(ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1370                     (tm) -> tm.isPotentialEmergencyNumber(potentialEmergencyAddress)));
1371         }
1372     }
1373 
1374     /**
1375      * Tests {@link TelephonyManager#getSupportedRadioAccessFamily()}
1376      */
1377     @Test
testGetRadioAccessFamily()1378     public void testGetRadioAccessFamily() {
1379         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1380             return;
1381         }
1382         long raf = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1383                 (tm) -> tm.getSupportedRadioAccessFamily());
1384         assertThat(raf).isNotEqualTo(TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN);
1385     }
1386 
assertSetOpportunisticSubSuccess(int value)1387     private static void assertSetOpportunisticSubSuccess(int value) {
1388         assertThat(value).isEqualTo(TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS);
1389     }
1390 
assertSetOpportunisticInvalidParameter(int value)1391     private static void assertSetOpportunisticInvalidParameter(int value) {
1392         assertThat(value).isEqualTo(TelephonyManager.SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
1393     }
1394 
1395     /**
1396      * Tests {@link TelephonyManager#setPreferredOpportunisticDataSubscription} and
1397      * {@link TelephonyManager#getPreferredOpportunisticDataSubscription}
1398      */
1399     @Test
testPreferredOpportunisticDataSubscription()1400     public void testPreferredOpportunisticDataSubscription() {
1401         int randomSubId = 1;
1402         int activeSubscriptionInfoCount = ShellIdentityUtils.invokeMethodWithShellPermissions(
1403                 mSubscriptionManager, (tm) -> tm.getActiveSubscriptionInfoCount());
1404         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1405             return;
1406         }
1407         if (mTelephonyManager.getPhoneCount() == 1) {
1408             return;
1409         }
1410         if (mTelephonyManager.getPhoneCount() == 2 && activeSubscriptionInfoCount != 2) {
1411             fail("This test requires two SIM cards.");
1412         }
1413         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
1414             (tm) -> tm.setPreferredOpportunisticDataSubscription(
1415                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false,
1416                 null, null));
1417         // wait for the data change to take effect
1418         waitForMs(500);
1419         int subId =
1420             ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1421                 (tm) -> tm.getPreferredOpportunisticDataSubscription());
1422         assertThat(subId).isEqualTo(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
1423         List<SubscriptionInfo> subscriptionInfoList =
1424                     ShellIdentityUtils.invokeMethodWithShellPermissions(mSubscriptionManager,
1425                             (tm) -> tm.getOpportunisticSubscriptions());
1426         Consumer<Integer> callbackSuccess = TelephonyManagerTest::assertSetOpportunisticSubSuccess;
1427         Consumer<Integer> callbackFailure =
1428                 TelephonyManagerTest::assertSetOpportunisticInvalidParameter;
1429         if (subscriptionInfoList == null || subscriptionInfoList.size() == 0) {
1430             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
1431                     (tm) -> tm.setPreferredOpportunisticDataSubscription(randomSubId, false,
1432                             AsyncTask.SERIAL_EXECUTOR, callbackFailure));
1433             // wait for the data change to take effect
1434             waitForMs(500);
1435             subId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1436                     (tm) -> tm.getPreferredOpportunisticDataSubscription());
1437             assertThat(subId).isEqualTo(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
1438 
1439         } else {
1440             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
1441                     (tm) -> tm.setPreferredOpportunisticDataSubscription(
1442                             subscriptionInfoList.get(0).getSubscriptionId(), false,
1443                             AsyncTask.SERIAL_EXECUTOR, callbackSuccess));
1444             // wait for the data change to take effect
1445             waitForMs(500);
1446             subId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1447                 (tm) -> tm.getPreferredOpportunisticDataSubscription());
1448             assertThat(subId).isEqualTo(subscriptionInfoList.get(0).getSubscriptionId());
1449         }
1450 
1451         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
1452                 (tm) -> tm.setPreferredOpportunisticDataSubscription(
1453                         SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false,
1454                         AsyncTask.SERIAL_EXECUTOR, callbackSuccess));
1455         // wait for the data change to take effect
1456         waitForMs(500);
1457         subId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
1458             (tm) -> tm.getPreferredOpportunisticDataSubscription());
1459         assertThat(subId).isEqualTo(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
1460     }
1461 
assertUpdateAvailableNetworkSuccess(int value)1462     private static void assertUpdateAvailableNetworkSuccess(int value) {
1463         assertThat(value).isEqualTo(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS);
1464     }
1465 
assertUpdateAvailableNetworkInvalidArguments(int value)1466     private static void assertUpdateAvailableNetworkInvalidArguments(int value) {
1467         assertThat(value).isEqualTo(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
1468     }
1469 
checkIfEmergencyNumberListHasSpecificAddress( List<EmergencyNumber> emergencyNumberList, String address)1470     private static boolean checkIfEmergencyNumberListHasSpecificAddress(
1471             List<EmergencyNumber> emergencyNumberList, String address) {
1472         for (EmergencyNumber emergencyNumber : emergencyNumberList) {
1473             if (address.equals(emergencyNumber.getNumber())) {
1474                 return true;
1475             }
1476         }
1477         return false;
1478     }
1479 
checkEmergencyNumberFormat( Map<Integer, List<EmergencyNumber>> emergencyNumberLists)1480     private static void checkEmergencyNumberFormat(
1481             Map<Integer, List<EmergencyNumber>> emergencyNumberLists) {
1482         for (List<EmergencyNumber> emergencyNumberList : emergencyNumberLists.values()) {
1483             for (EmergencyNumber emergencyNumber : emergencyNumberList) {
1484 
1485                 // Validate Emergency number address
1486                 assertTrue(validateEmergencyNumberAddress(emergencyNumber.getNumber()));
1487 
1488                 // Validate Emergency number country Iso
1489                 assertTrue(validateEmergencyNumberCountryIso(emergencyNumber.getCountryIso()));
1490 
1491                 // Validate Emergency number mnc
1492                 assertTrue(validateEmergencyNumberMnc(emergencyNumber.getMnc()));
1493 
1494                 // Validate Emergency service category list
1495                 assertTrue(validateEmergencyServiceCategoryList(
1496                         emergencyNumber.getEmergencyServiceCategories()));
1497 
1498                 // Validate Emergency number source list
1499                 assertTrue(validateEmergencyNumberSourceList(
1500                         emergencyNumber.getEmergencyNumberSources()));
1501 
1502                 // Validate Emergency URN list
1503                 // (just verify it is not null, because the support of this field is optional)
1504                 assertTrue(emergencyNumber.getEmergencyUrns() != null);
1505 
1506                 // Validat Emergency call routing
1507                 assertTrue(validateEmergencyCallRouting(
1508                         emergencyNumber.getEmergencyCallRouting()));
1509 
1510                 // Valid the emergency number should be at least in a valid source.
1511                 assertTrue(validateEmergencyNumberFromAnySource(emergencyNumber));
1512 
1513                 // Valid the emergency number should be at least in a valid category.
1514                 assertTrue(validateEmergencyNumberInAnyCategory(emergencyNumber));
1515             }
1516 
1517             // Validate compareTo
1518             assertTrue(validateEmergencyNumberCompareTo(emergencyNumberList));
1519         }
1520     }
1521 
1522     /**
1523      * Tests {@link TelephonyManager#updateAvailableNetworks}
1524      */
1525     @Test
testUpdateAvailableNetworks()1526     public void testUpdateAvailableNetworks() {
1527         int randomSubId = 1;
1528         int activeSubscriptionInfoCount = ShellIdentityUtils.invokeMethodWithShellPermissions(
1529                 mSubscriptionManager, (tm) -> tm.getActiveSubscriptionInfoCount());
1530         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1531             return;
1532         }
1533         if (mTelephonyManager.getPhoneCount() == 1) {
1534             return;
1535         }
1536         if (mTelephonyManager.getPhoneCount() == 2 && activeSubscriptionInfoCount != 2) {
1537             fail("This test requires two SIM cards.");
1538         }
1539 
1540         List<SubscriptionInfo> subscriptionInfoList =
1541             ShellIdentityUtils.invokeMethodWithShellPermissions(mSubscriptionManager,
1542                 (tm) -> tm.getOpportunisticSubscriptions());
1543         List<String> mccMncs = new ArrayList<String>();
1544         List<Integer> bands = new ArrayList<Integer>();
1545         List<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<AvailableNetworkInfo>();
1546         Consumer<Integer> callbackSuccess =
1547                 TelephonyManagerTest::assertUpdateAvailableNetworkSuccess;
1548         Consumer<Integer> callbackFailure =
1549                 TelephonyManagerTest::assertUpdateAvailableNetworkInvalidArguments;
1550         if (subscriptionInfoList == null || subscriptionInfoList.size() == 0
1551                 || !mSubscriptionManager.isActiveSubscriptionId(
1552                         subscriptionInfoList.get(0).getSubscriptionId())) {
1553             AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(randomSubId,
1554                     AvailableNetworkInfo.PRIORITY_HIGH, mccMncs, bands);
1555             availableNetworkInfos.add(availableNetworkInfo);
1556             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
1557                     (tm) -> tm.updateAvailableNetworks(availableNetworkInfos,
1558                             AsyncTask.SERIAL_EXECUTOR, callbackFailure));
1559             // wait for the data change to take effect
1560             waitForMs(500);
1561             // clear all the operations at the end of test.
1562             availableNetworkInfos.clear();
1563             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
1564                     (tm) -> tm.updateAvailableNetworks(availableNetworkInfos,
1565                             AsyncTask.SERIAL_EXECUTOR, callbackFailure));
1566         } else {
1567             AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(
1568                     subscriptionInfoList.get(0).getSubscriptionId(),
1569                     AvailableNetworkInfo.PRIORITY_HIGH, mccMncs, bands);
1570             availableNetworkInfos.add(availableNetworkInfo);
1571             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
1572                 (tm) -> tm.updateAvailableNetworks(availableNetworkInfos,
1573                         AsyncTask.SERIAL_EXECUTOR, callbackSuccess));
1574             // wait for the data change to take effect
1575             waitForMs(500);
1576             // clear all the operations at the end of test.
1577             availableNetworkInfos.clear();
1578             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
1579                 (tm) -> tm.updateAvailableNetworks(availableNetworkInfos,
1580                         AsyncTask.SERIAL_EXECUTOR, callbackSuccess));
1581         }
1582     }
1583 
1584     @Test
testSwitchMultiSimConfig()1585     public void testSwitchMultiSimConfig() {
1586         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1587             return;
1588         }
1589 
1590         boolean rebootRequired = ShellIdentityUtils.invokeMethodWithShellPermissions(
1591                 mTelephonyManager, (tm) -> tm.doesSwitchMultiSimConfigTriggerReboot());
1592 
1593         // It's hard to test if reboot is needed.
1594         if (!rebootRequired) {
1595             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
1596                     (tm) -> tm.switchMultiSimConfig(1));
1597             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
1598                     (tm) -> tm.switchMultiSimConfig(2));
1599         } else {
1600             // This should result in no-op.
1601             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
1602                     (tm) -> tm.switchMultiSimConfig(mTelephonyManager.getPhoneCount()));
1603         }
1604     }
1605 
1606     @Test
testIccOpenLogicalChannelBySlot()1607     public void testIccOpenLogicalChannelBySlot() {
1608         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1609             return;
1610         }
1611         // just verify no crash
1612         try {
1613             ShellIdentityUtils.invokeMethodWithShellPermissions(
1614                     mTelephonyManager, (tm) -> tm.iccOpenLogicalChannelBySlot(0, null, 0));
1615         } catch (IllegalArgumentException e) {
1616             // IllegalArgumentException is okay, just not SecurityException
1617         }
1618     }
1619 
1620     @Test
testIccCloseLogicalChannelBySlot()1621     public void testIccCloseLogicalChannelBySlot() {
1622         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1623             return;
1624         }
1625         // just verify no crash
1626         try {
1627             ShellIdentityUtils.invokeMethodWithShellPermissions(
1628                     mTelephonyManager, (tm) -> tm.iccCloseLogicalChannelBySlot(0, 0));
1629         } catch (IllegalArgumentException e) {
1630             // IllegalArgumentException is okay, just not SecurityException
1631         }
1632     }
1633 
1634     @Test
testIccTransmitApduLogicalChannelBySlot()1635     public void testIccTransmitApduLogicalChannelBySlot() {
1636         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1637             return;
1638         }
1639         int slotIndex = getValidSlotIndex();
1640         String result = ShellIdentityUtils.invokeMethodWithShellPermissions(
1641                 mTelephonyManager, (tm) -> tm.iccTransmitApduLogicalChannelBySlot(
1642                         slotIndex,
1643                         0 /* channel */,
1644                         0 /* cla */,
1645                         0 /* instruction */,
1646                         0 /* p1 */,
1647                         0 /* p2 */,
1648                         0 /* p3 */,
1649                         null /* data */));
1650         assertTrue(TextUtils.isEmpty(result));
1651     }
1652 
1653     @Test
testIccTransmitApduBasicChannelBySlot()1654     public void testIccTransmitApduBasicChannelBySlot() {
1655         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
1656             return;
1657         }
1658         // just verify no crash
1659         int slotIndex = getValidSlotIndex();
1660         try {
1661             ShellIdentityUtils.invokeMethodWithShellPermissions(
1662                     mTelephonyManager, (tm) -> tm.iccTransmitApduBasicChannelBySlot(
1663                             slotIndex,
1664                             0 /* cla */,
1665                             0 /* instruction */,
1666                             0 /* p1 */,
1667                             0 /* p2 */,
1668                             0 /* p3 */,
1669                             null /* data */));
1670         } catch (IllegalArgumentException e ) {
1671             // IllegalArgumentException is okay, just not SecurityException
1672         }
1673     }
1674 
1675     /**
1676      * Validate Emergency Number address that only contains the dialable character.
1677      *
1678      * @param address Emergency number address to validate
1679      * @return {@code true} if the address is valid; {@code false} otherwise.
1680      */
validateEmergencyNumberAddress(String address)1681     private static boolean validateEmergencyNumberAddress(String address) {
1682         if (address == null) {
1683             return false;
1684         }
1685         for (char c : address.toCharArray()) {
1686             if (!isDialable(c)) {
1687                 return false;
1688             }
1689         }
1690         return true;
1691     }
1692 
1693     /**
1694      * Validate Emergency Number country Iso
1695      *
1696      * @param countryIso Emergency number country iso to validate
1697      * @return {@code true} if the country iso is valid; {@code false} otherwise.
1698      */
validateEmergencyNumberCountryIso(String countryIso)1699     private static boolean validateEmergencyNumberCountryIso(String countryIso) {
1700         if (countryIso == null) {
1701             return false;
1702         }
1703         int length = countryIso.length();
1704         return length >= 0 && length <= 2;
1705     }
1706 
1707     /**
1708      * Validate Emergency Number MNC
1709      *
1710      * @param mnc Emergency number MNC to validate
1711      * @return {@code true} if the MNC is valid; {@code false} otherwise.
1712      */
validateEmergencyNumberMnc(String mnc)1713     private static boolean validateEmergencyNumberMnc(String mnc) {
1714         if (mnc == null) {
1715             return false;
1716         }
1717         int length = mnc.length();
1718         return length >= 0 && length <= 3;
1719     }
1720 
1721     /**
1722      * Validate Emergency service category list
1723      *
1724      * @param categories Emergency service category list to validate
1725      * @return {@code true} if the category list is valid; {@code false} otherwise.
1726      */
validateEmergencyServiceCategoryList(List<Integer> categories)1727     private static boolean validateEmergencyServiceCategoryList(List<Integer> categories) {
1728         if (categories == null) {
1729             return false;
1730         }
1731         if (categories.contains(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED)) {
1732             return categories.size() == 1;
1733         }
1734         for (int category : categories) {
1735             if (!EMERGENCY_SERVICE_CATEGORY_SET.contains(category)) {
1736                 return false;
1737             }
1738         }
1739         return true;
1740     }
1741 
1742     /**
1743      * Validate Emergency number source list
1744      *
1745      * @param categories Emergency number source list to validate
1746      * @return {@code true} if the source list is valid; {@code false} otherwise.
1747      */
validateEmergencyNumberSourceList(List<Integer> sources)1748     private static boolean validateEmergencyNumberSourceList(List<Integer> sources) {
1749         if (sources == null) {
1750             return false;
1751         }
1752         for (int source : sources) {
1753             if (!EMERGENCY_NUMBER_SOURCE_SET.contains(source)) {
1754                 return false;
1755             }
1756         }
1757         return true;
1758     }
1759 
1760     /**
1761      * Validate Emergency call routing.
1762      *
1763      * @param routing Emergency call routing to validate
1764      * @return {@code true} if the emergency call routing is valid; {@code false} otherwise.
1765      */
validateEmergencyCallRouting(int routing)1766     private static boolean validateEmergencyCallRouting(int routing) {
1767         return routing >= EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN
1768                 && routing <= (EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY
1769                 | EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
1770     }
1771 
1772     /**
1773      * Valid the emergency number should be at least from a valid source.
1774      *
1775      * @param emergencyNumber Emergency number to verify
1776      * @return {@code true} if the emergency number is from any source; {@code false} otherwise.
1777      */
validateEmergencyNumberFromAnySource(EmergencyNumber emergencyNumber)1778     private static boolean validateEmergencyNumberFromAnySource(EmergencyNumber emergencyNumber) {
1779         boolean isFromAnySource = false;
1780         for (int possibleSourceValue = EMERGENCY_NUMBER_SOURCE_RIL_ECCLIST;
1781                 possibleSourceValue <= (EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING
1782                         | EmergencyNumber.EMERGENCY_NUMBER_SOURCE_SIM
1783                         | EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE
1784                         | EmergencyNumber.EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG
1785                         | EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DEFAULT);
1786                 possibleSourceValue++) {
1787             if (emergencyNumber.isFromSources(possibleSourceValue)) {
1788                 isFromAnySource = true;
1789                 break;
1790             }
1791         }
1792         return isFromAnySource;
1793     }
1794 
1795     /**
1796      * Valid the emergency number should be at least in a valid category.
1797      *
1798      * @param emergencyNumber Emergency number to verify
1799      * @return {@code true} if it is in any category; {@code false} otherwise.
1800      */
validateEmergencyNumberInAnyCategory(EmergencyNumber emergencyNumber)1801     private static boolean validateEmergencyNumberInAnyCategory(EmergencyNumber emergencyNumber) {
1802         boolean isInAnyCategory = false;
1803         for (int possibleCategoryValue = EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
1804                 possibleCategoryValue <= (EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE
1805                          | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_AMBULANCE
1806                          | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE
1807                         | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD
1808                         | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE
1809                         | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MIEC
1810                         | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_AIEC);
1811                 possibleCategoryValue++) {
1812             if (emergencyNumber.isInEmergencyServiceCategories(possibleCategoryValue)) {
1813                 isInAnyCategory = true;
1814                 break;
1815             }
1816         }
1817         return isInAnyCategory;
1818     }
1819 
validateEmergencyNumberCompareTo( List<EmergencyNumber> emergencyNumberList)1820     private static boolean validateEmergencyNumberCompareTo(
1821             List<EmergencyNumber> emergencyNumberList) {
1822         if (emergencyNumberList == null) {
1823             return false;
1824         }
1825         if (emergencyNumberList.size() > 0) {
1826             EmergencyNumber emergencyNumber = emergencyNumberList.get(0);
1827             if (emergencyNumber.compareTo(emergencyNumber) != 0) {
1828                 return false;
1829             }
1830         }
1831         return true;
1832     }
1833 
isDialable(char c)1834     private static boolean isDialable(char c) {
1835         return (c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+' || c == 'N';
1836     }
1837 
getValidSlotIndex()1838     private int getValidSlotIndex() {
1839         return ShellIdentityUtils.invokeMethodWithShellPermissions(
1840                 mTelephonyManager, (tm) -> {
1841                     List<UiccCardInfo> cardInfos = mTelephonyManager.getUiccCardsInfo();
1842                     Set<String> presentCards = Arrays.stream(mTelephonyManager.getUiccSlotsInfo())
1843                             .filter(UiccSlotInfo::getIsActive)
1844                             .map(UiccSlotInfo::getCardId)
1845                             .filter(Objects::nonNull)
1846                             // hack around getUiccSlotsInfo not stripping trailing F
1847                             .map(s -> s.endsWith("F") ? s.substring(0, s.length() - 1) : s)
1848                             .collect(Collectors.toSet());
1849                     int slotIndex = -1;
1850                     for (UiccCardInfo cardInfo : cardInfos) {
1851                         if (presentCards.contains(cardInfo.getIccId())
1852                                 || presentCards.contains(cardInfo.getEid())) {
1853                             slotIndex = cardInfo.getSlotIndex();
1854                             break;
1855                         }
1856                     }
1857                     if (slotIndex < 0) {
1858                         fail("Test must be run with SIM card inserted, presentCards = "
1859                                 + presentCards + "cardinfos = " + cardInfos);
1860                     }
1861                     return slotIndex;
1862                 });
1863     }
1864 
waitForMs(long ms)1865     public static void waitForMs(long ms) {
1866         try {
1867             Thread.sleep(ms);
1868         } catch (InterruptedException e) {
1869             Log.d(TAG, "InterruptedException while waiting: " + e);
1870         }
1871     }
1872 }
1873