Home | History | Annotate | Download | only in cts
      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
    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
    171     public void tearDown() throws Exception {
    172         if (mListener != null) {
    173             // unregister the listener
    174             mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
    175         }
    176     }
    177 
    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
    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
    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
    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
    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
    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
    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
    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 
    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 
    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 
    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 
    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
    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
    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
    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
    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
    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
    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 
    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 
    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 
    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      */
    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 
    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 
    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 
    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 
    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 
    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 */
    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 
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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 
   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
   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
   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
   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
   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
   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
   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 
   1387     private static void assertSetOpportunisticSubSuccess(int value) {
   1388         assertThat(value).isEqualTo(TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS);
   1389     }
   1390 
   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
   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 
   1462     private static void assertUpdateAvailableNetworkSuccess(int value) {
   1463         assertThat(value).isEqualTo(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS);
   1464     }
   1465 
   1466     private static void assertUpdateAvailableNetworkInvalidArguments(int value) {
   1467         assertThat(value).isEqualTo(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
   1468     }
   1469 
   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 
   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
   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
   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
   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
   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
   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
   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      */
   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      */
   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      */
   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      */
   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      */
   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      */
   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      */
   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      */
   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 
   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 
   1834     private static boolean isDialable(char c) {
   1835         return (c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+' || c == 'N';
   1836     }
   1837 
   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 
   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