/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.telephony.cts;

import static android.app.AppOpsManager.OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER;
import static android.telephony.DataSpecificRegistrationInfo.LTE_ATTACH_EXTRA_INFO_CSFB_NOT_PREFERRED;
import static android.telephony.DataSpecificRegistrationInfo.LTE_ATTACH_EXTRA_INFO_NONE;
import static android.telephony.DataSpecificRegistrationInfo.LTE_ATTACH_EXTRA_INFO_SMS_ONLY;
import static android.telephony.DataSpecificRegistrationInfo.LTE_ATTACH_TYPE_COMBINED;
import static android.telephony.DataSpecificRegistrationInfo.LTE_ATTACH_TYPE_EPS_ONLY;
import static android.telephony.DataSpecificRegistrationInfo.LTE_ATTACH_TYPE_UNKNOWN;
import static android.telephony.PhoneCapability.DEVICE_NR_CAPABILITY_NSA;
import static android.telephony.PhoneCapability.DEVICE_NR_CAPABILITY_SA;

import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeNoException;
import static org.junit.Assume.assumeTrue;

import android.Manifest;
import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.UiAutomation;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.os.Parcel;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserManager;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.AvailableNetworkInfo;
import android.telephony.CallAttributes;
import android.telephony.CallForwardingInfo;
import android.telephony.CallQuality;
import android.telephony.CarrierConfigManager;
import android.telephony.CellBroadcastIdRange;
import android.telephony.CellIdentity;
import android.telephony.CellIdentityCdma;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
import android.telephony.CellIdentityNr;
import android.telephony.CellIdentityTdscdma;
import android.telephony.CellIdentityWcdma;
import android.telephony.CellInfo;
import android.telephony.CellLocation;
import android.telephony.DataSpecificRegistrationInfo;
import android.telephony.DataThrottlingRequest;
import android.telephony.ImsiEncryptionInfo;
import android.telephony.ModemActivityInfo;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
import android.telephony.PinResult;
import android.telephony.PreciseCallState;
import android.telephony.RadioAccessFamily;
import android.telephony.RadioAccessSpecifier;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SignalStrengthUpdateRequest;
import android.telephony.SignalThresholdInfo;
import android.telephony.SmsCbMessage;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.ThermalMitigationRequest;
import android.telephony.UiccCardInfo;
import android.telephony.UiccPortInfo;
import android.telephony.UiccSlotInfo;
import android.telephony.UiccSlotMapping;
import android.telephony.cts.util.TelephonyUtils;
import android.telephony.data.ApnSetting;
import android.telephony.data.NetworkSlicingConfig;
import android.telephony.emergency.EmergencyNumber;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;

import androidx.test.InstrumentationRegistry;

import com.android.compatibility.common.util.AmUtils;
import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.CarrierPrivilegeUtils;
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.TestThread;
import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.uicc.IccUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.IntSupplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * Build, install and run the tests by running the commands below:
 *  make cts -j64
 *  cts-tradefed run cts -m CtsTelephonyTestCases --test android.telephony.cts.TelephonyManagerTest
 */
public class TelephonyManagerTest {

    @Rule
    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
    private TelephonyManager mTelephonyManager;
    private SubscriptionManager mSubscriptionManager;
    private PackageManager mPackageManager;
    private boolean mOnCellLocationChangedCalled = false;
    private boolean mOnCellInfoChanged = false;
    private boolean mOnSignalStrengthsChanged = false;
    private boolean mServiceStateChangedCalled = false;
    private boolean mRadioRebootTriggered = false;
    private boolean mHasRadioPowerOff = false;
    private ServiceState mServiceState;
    private PhoneCapability mPhoneCapability;
    private boolean mOnPhoneCapabilityChanged = false;
    private final Object mLock = new Object();

    private CarrierConfigManager mCarrierConfigManager;
    private String mSelfPackageName;
    private String mSelfCertHash;

    private static final int WAIT_FOR_CONDITION = 3000;
    private static final int TOLERANCE = 1000;
    private static final int TIMEOUT_FOR_NETWORK_OPS = TOLERANCE * 180;

    private static final int TIMEOUT_FOR_CARRIER_STATUS_FILE_CHECK = TOLERANCE * 180;
    private PhoneStateListener mListener;
    private static ConnectivityManager mCm;
    private static final String TAG = "TelephonyManagerTest";
    private static final List<Integer> ROAMING_TYPES = Arrays.asList(
            ServiceState.ROAMING_TYPE_DOMESTIC,
            ServiceState.ROAMING_TYPE_INTERNATIONAL,
            ServiceState.ROAMING_TYPE_NOT_ROAMING,
            ServiceState.ROAMING_TYPE_UNKNOWN);
    private static final List<Integer> NETWORK_TYPES = Arrays.asList(
            TelephonyManager.NETWORK_TYPE_UNKNOWN,
            TelephonyManager.NETWORK_TYPE_GPRS,
            TelephonyManager.NETWORK_TYPE_EDGE,
            TelephonyManager.NETWORK_TYPE_UMTS,
            TelephonyManager.NETWORK_TYPE_CDMA,
            TelephonyManager.NETWORK_TYPE_EVDO_0,
            TelephonyManager.NETWORK_TYPE_EVDO_A,
            TelephonyManager.NETWORK_TYPE_1xRTT,
            TelephonyManager.NETWORK_TYPE_HSDPA,
            TelephonyManager.NETWORK_TYPE_HSUPA,
            TelephonyManager.NETWORK_TYPE_HSPA,
            TelephonyManager.NETWORK_TYPE_IDEN,
            TelephonyManager.NETWORK_TYPE_EVDO_B,
            TelephonyManager.NETWORK_TYPE_LTE,
            TelephonyManager.NETWORK_TYPE_EHRPD,
            TelephonyManager.NETWORK_TYPE_HSPAP,
            TelephonyManager.NETWORK_TYPE_GSM,
            TelephonyManager.NETWORK_TYPE_TD_SCDMA,
            TelephonyManager.NETWORK_TYPE_IWLAN,
            TelephonyManager.NETWORK_TYPE_LTE_CA,
            TelephonyManager.NETWORK_TYPE_NR);

    private static final int EMERGENCY_NUMBER_SOURCE_RIL_ECCLIST = 0;
    private static final Set<Integer> EMERGENCY_NUMBER_SOURCE_SET;

    private static final String PLMN_A = "123456";
    private static final String PLMN_B = "78901";
    private static final List<String> FPLMN_TEST = Arrays.asList(PLMN_A, PLMN_B);
    private static final int MAX_FPLMN_NUM = 1000;
    private static final int MIN_FPLMN_NUM = 3;

    private static final String THERMAL_MITIGATION_COMMAND_BASE = "cmd phone thermal-mitigation ";
    private static final String ALLOW_PACKAGE_SUBCOMMAND = "allow-package ";
    private static final String DISALLOW_PACKAGE_SUBCOMMAND = "disallow-package ";
    private static final String TELEPHONY_CTS_PACKAGE = "android.telephony.cts";

    private static final String TEST_FORWARD_NUMBER = "54321";
    private static final String TESTING_PLMN = "12345";

    private static final String BAD_IMSI_CERT_URL = "https:badurl.badurl:8080";
    private static final String IMSI_CERT_STRING_EPDG = "-----BEGIN CERTIFICATE-----"
            + "\nMIIDkzCCAnugAwIBAgIEJ4MVZDANBgkqhkiG9w0BAQsFADB6MQswCQYDVQQGEwJV"
            + "\nUzEOMAwGA1UECBMFVGV4YXMxDzANBgNVBAcTBklydmluZzEiMCAGA1UEChMZVmVy"
            + "\naXpvbiBEYXRhIFNlcnZpY2VzIExMQzEMMAoGA1UECxMDTk5PMRgwFgYDVQQDEw9F"
            + "\nQVAtSURFLlZaVy5DT00wHhcNMTcxMTEzMTkxMTA1WhcNMjcxMTExMTkxMTA1WjB6"
            + "\nMQswCQYDVQQGEwJVUzEOMAwGA1UECBMFVGV4YXMxDzANBgNVBAcTBklydmluZzEi"
            + "\nMCAGA1UEChMZVmVyaXpvbiBEYXRhIFNlcnZpY2VzIExMQzEMMAoGA1UECxMDTk5P"
            + "\nMRgwFgYDVQQDEw9FQVAtSURFLlZaVy5DT00wggEiMA0GCSqGSIb3DQEBAQUAA4IB"
            + "\nDwAwggEKAoIBAQCrQ28TvN0uUV/vK4YUS7+zcYMKAe5IYtDa3Wa0r64iyBSz6Eau"
            + "\nT+YHNNzCV4xMqURM5mIY6796LnmWR5jViUgrHyw0d06mLE54uUET/drn2pwhaobK"
            + "\nNVvbYzpm5W3dvext+klEgIhpRW4fR/uNUmD0O9n/5ofpg++wbvMNWEIjeTVUGPRT"
            + "\nCeVblH3tK8bKdCKjp48HtuciY7gE8LMoHhMHA1cob9VktSYTy2ABa+rKAPAaqVz4"
            + "\nL0Arlbi9INHSDNFlLvy1xE5dyYIqhRMicM2i4LCMwJnwf0tz8m7DmDxfdmC4HY2Q"
            + "\nz4VpbQOu10oRhXXrhZFkZEmqp6RYQmDRDDDtAgMBAAGjITAfMB0GA1UdDgQWBBSg"
            + "\nFA6liox07smzfITrvjSlgWkMMTANBgkqhkiG9w0BAQsFAAOCAQEAIoFKLgLfS9f1"
            + "\n0UG85rb+noaeXY0YofSY0dxFIW3rA5zjRD0kus9iyw9CfADDD305hefJ4Kq/NLAF"
            + "\n0odR4MOTan5KhXTlD9/8mZjSSeEktgCX3BbmMqKoKcaV6Oo9C0RfwGccDms6D+Dw"
            + "\n3GkgsvKJEB8LjApzQSmDwCV9BVJsC60041cndqBxMr3RMxCkO6/sQRKyAuzx5f91"
            + "\nWn5cpYxvl4//TatSc9oeU+ootlxfXszdRPM5xqCodm6gWmxRkK6DePlhpaZ1sKdw"
            + "\nCQg/mA35Eh5ZgOpZT2YG+a8BbDRCF5gj/pu1tPt8VfApPHq6lAoitlrx1cEdJWx6"
            + "\n5JXaFrs0UA=="
            + "\n-----END CERTIFICATE-----";
    private static final String IMSI_CERT_STRING_WLAN = "-----BEGIN CERTIFICATE-----"
            + "\nMIIFbzCCBFegAwIBAgIUAz8I/cK3fILeJ9PSbi7MkN8yZBkwDQYJKoZIhvcNAQEL"
            + "\nBQAwgY0xCzAJBgNVBAYTAk5MMRIwEAYDVQQHEwlBbXN0ZXJkYW0xJTAjBgNVBAoT"
            + "\nHFZlcml6b24gRW50ZXJwcmlzZSBTb2x1dGlvbnMxEzARBgNVBAsTCkN5YmVydHJ1"
            + "\nc3QxLjAsBgNVBAMTJVZlcml6b24gUHVibGljIFN1cmVTZXJ2ZXIgQ0EgRzE0LVNI"
            + "\nQTIwHhcNMTcxMTE2MTU1NjMzWhcNMTkxMTE2MTU1NjMzWjB6MQswCQYDVQQGEwJV"
            + "\nUzEOMAwGA1UECBMFVGV4YXMxDzANBgNVBAcTBklydmluZzEiMCAGA1UEChMZVmVy"
            + "\naXpvbiBEYXRhIFNlcnZpY2VzIExMQzEMMAoGA1UECxMDTk5PMRgwFgYDVQQDEw9F"
            + "\nQVAtSURFLlZaVy5DT00wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCr"
            + "\nQ28TvN0uUV/vK4YUS7+zcYMKAe5IYtDa3Wa0r64iyBSz6EauT+YHNNzCV4xMqURM"
            + "\n5mIY6796LnmWR5jViUgrHyw0d06mLE54uUET/drn2pwhaobKNVvbYzpm5W3dvext"
            + "\n+klEgIhpRW4fR/uNUmD0O9n/5ofpg++wbvMNWEIjeTVUGPRTCeVblH3tK8bKdCKj"
            + "\np48HtuciY7gE8LMoHhMHA1cob9VktSYTy2ABa+rKAPAaqVz4L0Arlbi9INHSDNFl"
            + "\nLvy1xE5dyYIqhRMicM2i4LCMwJnwf0tz8m7DmDxfdmC4HY2Qz4VpbQOu10oRhXXr"
            + "\nhZFkZEmqp6RYQmDRDDDtAgMBAAGjggHXMIIB0zAMBgNVHRMBAf8EAjAAMEwGA1Ud"
            + "\nIARFMEMwQQYJKwYBBAGxPgEyMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vc2VjdXJl"
            + "\nLm9tbmlyb290LmNvbS9yZXBvc2l0b3J5MIGpBggrBgEFBQcBAQSBnDCBmTAtBggr"
            + "\nBgEFBQcwAYYhaHR0cDovL3Zwc3NnMTQyLm9jc3Aub21uaXJvb3QuY29tMDMGCCsG"
            + "\nAQUFBzAChidodHRwOi8vY2FjZXJ0Lm9tbmlyb290LmNvbS92cHNzZzE0Mi5jcnQw"
            + "\nMwYIKwYBBQUHMAKGJ2h0dHA6Ly9jYWNlcnQub21uaXJvb3QuY29tL3Zwc3NnMTQy"
            + "\nLmRlcjAaBgNVHREEEzARgg9FQVAtSURFLlZaVy5DT00wDgYDVR0PAQH/BAQDAgWg"
            + "\nMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBTkLbuR"
            + "\nAWUmH7R6P6MVJaTOjEQzOzA+BgNVHR8ENzA1MDOgMaAvhi1odHRwOi8vdnBzc2cx"
            + "\nNDIuY3JsLm9tbmlyb290LmNvbS92cHNzZzE0Mi5jcmwwHQYDVR0OBBYEFKAUDqWK"
            + "\njHTuybN8hOu+NKWBaQwxMA0GCSqGSIb3DQEBCwUAA4IBAQAbSrvVrdxRPLnVu6vc"
            + "\n4BiFT2gWDhZ63EyV4f877sC1iMJRFlfwWQQfHVyhGTFa8JnhbEhhTxCP+L00Q8rX"
            + "\nKbOw9ei5g2yp7OjStwhHz5T20UejjKkl7hKtMduZXxFToqhVwIpqG58Tzl/35FX4"
            + "\nu+YDPgwTX5gbpbJxpbncn9voxWGWu3AbHVvzaskfBgZfWAuJnbgq0WTEt7bGOfiI"
            + "\nelIIQe7XL6beFcdAM9C7DlgOLqpR/31LncrMC46cPA5HmfV4mnpeK/9uq0mMbUJK"
            + "\nx2vNRWONSm2UGwdb00tLsTloxeqCOMpbkBiqi/RhOlIKIOWMPojukA5+xryh2FVs"
            + "\n7bdw"
            + "\n-----END CERTIFICATE-----";

    private static final int RADIO_HAL_VERSION_1_5 = makeRadioVersion(1, 5);
    private static final int RADIO_HAL_VERSION_1_6 = makeRadioVersion(1, 6);
    private static final int RADIO_HAL_VERSION_2_0 = makeRadioVersion(2, 0);
    private static final int RADIO_HAL_VERSION_2_1 = makeRadioVersion(2, 1);
    private static final int RADIO_HAL_VERSION_2_2 = makeRadioVersion(2, 2);

    static {
        EMERGENCY_NUMBER_SOURCE_SET = new HashSet<Integer>();
        EMERGENCY_NUMBER_SOURCE_SET.add(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING);
        EMERGENCY_NUMBER_SOURCE_SET.add(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_SIM);
        EMERGENCY_NUMBER_SOURCE_SET.add(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE);
        EMERGENCY_NUMBER_SOURCE_SET.add(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG);
        EMERGENCY_NUMBER_SOURCE_SET.add(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DEFAULT);
    }

    private static final Set<Integer> EMERGENCY_SERVICE_CATEGORY_SET;
    static {
        EMERGENCY_SERVICE_CATEGORY_SET = new HashSet<Integer>();
        EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE);
        EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_AMBULANCE);
        EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE);
        EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD);
        EMERGENCY_SERVICE_CATEGORY_SET.add(
                EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE);
        EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MIEC);
        EMERGENCY_SERVICE_CATEGORY_SET.add(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_AIEC);
    }

    private static final Map<Class<? extends CellIdentity>, List<Integer>> sNetworkTypes;
    static {
        sNetworkTypes = new ArrayMap<>();
        sNetworkTypes.put(CellIdentityGsm.class,
                Arrays.asList(new Integer[]{
                    TelephonyManager.NETWORK_TYPE_GSM,
                    TelephonyManager.NETWORK_TYPE_GPRS,
                    TelephonyManager.NETWORK_TYPE_EDGE}));
        sNetworkTypes.put(CellIdentityWcdma.class,
                Arrays.asList(TelephonyManager.NETWORK_TYPE_UMTS,
                        TelephonyManager.NETWORK_TYPE_HSDPA,
                        TelephonyManager.NETWORK_TYPE_HSUPA,
                        TelephonyManager.NETWORK_TYPE_HSPA,
                        TelephonyManager.NETWORK_TYPE_HSPAP));
        sNetworkTypes.put(CellIdentityCdma.class,
                Arrays.asList(TelephonyManager.NETWORK_TYPE_CDMA,
                        TelephonyManager.NETWORK_TYPE_1xRTT,
                        TelephonyManager.NETWORK_TYPE_EVDO_0,
                        TelephonyManager.NETWORK_TYPE_EVDO_A,
                        TelephonyManager.NETWORK_TYPE_EVDO_B,
                        TelephonyManager.NETWORK_TYPE_EHRPD));
        sNetworkTypes.put(CellIdentityLte.class,
                Arrays.asList(TelephonyManager.NETWORK_TYPE_LTE));
        sNetworkTypes.put(CellIdentityNr.class,
                Arrays.asList(TelephonyManager.NETWORK_TYPE_NR));
        sNetworkTypes.put(CellIdentityTdscdma.class,
                Arrays.asList(TelephonyManager.NETWORK_TYPE_TD_SCDMA));
    }

    private int mTestSub;
    private int mNetworkHalVersion;
    private int mModemHalVersion;
    private int mConfigHalVersion;
    private boolean mIsAllowedNetworkTypeChanged;
    private Map<Integer, Long> mAllowedNetworkTypesList = new HashMap<>();

    private static final String CARRIER_RESTRICTION_OPERATOR_DETAILS = "{\"com.vzw.hss"
            + ".myverizon\":{\"carrierId\":1839,"
    + "\"callerSHA1Id\":[\"C58EE7871896786F8BF70EBDB137DE10074043E9\","
    + "\"AE23A03436DF07B0CD70FE881CDA2EC1D21215D7B7B0CC68E67B67F5DF89526A\"]}}";

    private class CarrierPrivilegeChangeMonitor implements AutoCloseable {
        // CarrierPrivilegesCallback will be triggered upon registration. Filter the first callback
        // here since we really care of the *change* of carrier privileges instead of the content
        private boolean mHasSentPrivilegeChangeCallback = false;
        private CountDownLatch mLatch = new CountDownLatch(1);
        private final TelephonyManager.CarrierPrivilegesCallback mCarrierPrivilegesCallback;

        CarrierPrivilegeChangeMonitor() {
            mCarrierPrivilegesCallback = (privilegedPackageNames, privilegedUids) -> {
                // Ignore the first callback which is triggered upon registration
                if (!mHasSentPrivilegeChangeCallback) {
                    mHasSentPrivilegeChangeCallback = true;
                    return;
                }
                mLatch.countDown();
            };

            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.registerCarrierPrivilegesCallback(
                            SubscriptionManager.getSlotIndex(mTestSub),
                            getContext().getMainExecutor(),
                            mCarrierPrivilegesCallback));
        }

        public void waitForCarrierPrivilegeChanged() throws Exception {
            if (!mLatch.await(5, TimeUnit.SECONDS)) {
                throw new IllegalStateException("Failed to update carrier privileges");
            }
        }

        @Override
        public void close() throws Exception {
            if(mTelephonyManager != null) {
                ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                        (tm) -> tm.unregisterCarrierPrivilegesCallback(
                                mCarrierPrivilegesCallback));
            }
        }
    }

    private static class CountryChangedReceiver extends BroadcastReceiver {
        private CountDownLatch mLatch = new CountDownLatch(1);

        @Nullable
        private Bundle mBundle;

        @Nullable
        public Bundle getExtras() {
            return mBundle;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED.equals(intent.getAction())) {
                Log.d(TAG, "testLastKnownCountryIso received ACTION_NETWORK_COUNTRY_CHANGED");
                mBundle = intent.getExtras();
                mLatch.countDown();
            }
        }

        void clearQueue() {
            mLatch = new CountDownLatch(1);
        }

        void waitForIntent() throws Exception {
            // Extend to wait up to 10 seconds to receive CountryChanged Intent.
            mLatch.await(10000, TimeUnit.MILLISECONDS);
        }
    }

    @Before
    public void setUp() throws Exception {
        mCm = getContext().getSystemService(ConnectivityManager.class);
        mPackageManager = getContext().getPackageManager();
        assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY));

        mSubscriptionManager = getContext().getSystemService(SubscriptionManager.class);
        mCarrierConfigManager = getContext().getSystemService(CarrierConfigManager.class);
        mSelfPackageName = getContext().getPackageName();
        mSelfCertHash = getCertHash(mSelfPackageName);
        mTestSub = SubscriptionManager.getDefaultSubscriptionId();
        // If the test subscription is invalid, TelephonyManager APIs may return null
        assumeTrue("Skipping tests because default subscription ID is invalid",
                mTestSub != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
        mTelephonyManager = getContext().getSystemService(TelephonyManager.class)
                .createForSubscriptionId(mTestSub);
        try {
            mTelephonyManager.getHalVersion(TelephonyManager.HAL_SERVICE_RADIO);
        } catch (IllegalStateException e) {
            assumeNoException("Skipping tests because Telephony service is null", e);
        }
        Pair<Integer, Integer> networkHalVersion =
                mTelephonyManager.getHalVersion(TelephonyManager.HAL_SERVICE_NETWORK);
        mNetworkHalVersion = makeRadioVersion(networkHalVersion.first, networkHalVersion.second);
        Pair<Integer, Integer> modemHalVersion =
                mTelephonyManager.getHalVersion(TelephonyManager.HAL_SERVICE_MODEM);
        mModemHalVersion = makeRadioVersion(modemHalVersion.first, modemHalVersion.second);
        Pair<Integer, Integer> simHalVersion =
                mTelephonyManager.getHalVersion(TelephonyManager.HAL_SERVICE_RADIO);
        mConfigHalVersion = makeRadioVersion(simHalVersion.first, simHalVersion.second);
        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .adoptShellPermissionIdentity(android.Manifest.permission.READ_PHONE_STATE);
        saveAllowedNetworkTypesForAllReasons();

        // Wait previously queued broadcasts to complete before starting the test
        AmUtils.waitForBroadcastBarrier();
    }

    @After
    public void tearDown() throws Exception {
        if (mListener != null) {
            // unregister the listener
            mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
        }
        if (mIsAllowedNetworkTypeChanged) {
            recoverAllowedNetworkType();
        }

        StringBuilder cmdBuilder = new StringBuilder();
        cmdBuilder.append(THERMAL_MITIGATION_COMMAND_BASE).append(DISALLOW_PACKAGE_SUBCOMMAND)
                .append(TELEPHONY_CTS_PACKAGE);
        TelephonyUtils.executeShellCommand(InstrumentationRegistry.getInstrumentation(),
                cmdBuilder.toString());
    }

    private void saveAllowedNetworkTypesForAllReasons() {
        mIsAllowedNetworkTypeChanged = false;
        if (mAllowedNetworkTypesList == null) {
            mAllowedNetworkTypesList = new HashMap<>();
        }
        long allowedNetworkTypesUser = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.getAllowedNetworkTypesForReason(
                        TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)
        );
        long allowedNetworkTypesPower = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.getAllowedNetworkTypesForReason(
                        TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER)
        );
        long allowedNetworkTypesCarrier = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.getAllowedNetworkTypesForReason(
                        TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER)
        );
        long allowedNetworkTypesEnable2g = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.getAllowedNetworkTypesForReason(
                        TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G)
        );
        mAllowedNetworkTypesList.put(TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
                allowedNetworkTypesUser);
        mAllowedNetworkTypesList.put(TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER,
                allowedNetworkTypesPower);
        mAllowedNetworkTypesList.put(TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER,
                allowedNetworkTypesCarrier);
        mAllowedNetworkTypesList.put(TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G,
                allowedNetworkTypesEnable2g);
    }

    private void recoverAllowedNetworkType() {
        if (mAllowedNetworkTypesList == null) {
            return;
        }
        for (Integer key : mAllowedNetworkTypesList.keySet()) {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setAllowedNetworkTypesForReason(
                            key,
                            mAllowedNetworkTypesList.get(key)));
        }
    }

    private String getCertHash(String pkgName) throws Exception {
        try {
            PackageInfo pInfo = mPackageManager.getPackageInfo(pkgName,
                    PackageManager.GET_SIGNATURES
                            | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            return IccUtils.bytesToHexString(md.digest(pInfo.signatures[0].toByteArray()));
        } catch (PackageManager.NameNotFoundException ex) {
            Log.e(TAG, pkgName + " not found", ex);
            throw ex;
        } catch (NoSuchAlgorithmException ex) {
            Log.e(TAG, "Algorithm SHA1 is not found.");
            throw ex;
        }
    }

    /** Checks whether the telephony feature is supported. */
    private boolean hasFeature(String feature) {
        return mPackageManager.hasSystemFeature(feature);
    }

    @Test
    public void testHasCarrierPrivilegesViaCarrierConfigs() throws Exception {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
        PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mTestSub);

        try {
            assertNotNull("CarrierConfigManager#getConfigForSubId() returned null",
                    carrierConfig);
            assertFalse("CarrierConfigManager#getConfigForSubId() returned empty bundle",
                    carrierConfig.isEmpty());

            // purge the certs in carrierConfigs first
            carrierConfig.putStringArray(
                    CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY, new String[]{});
            changeCarrierPrivileges(false, carrierConfig);
            // verify we don't have privilege through carrierConfigs or Uicc
            assertFalse(mTelephonyManager.hasCarrierPrivileges());

            carrierConfig.putStringArray(
                    CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY,
                    new String[]{mSelfCertHash});

            // verify we now have privilege after adding certificate to carrierConfigs
            changeCarrierPrivileges(true, carrierConfig);
            assertTrue(mTelephonyManager.hasCarrierPrivileges());
        } finally {
            // purge the newly added certificate
            carrierConfig.putStringArray(
                    CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY, new String[]{});
            changeCarrierPrivileges(false, carrierConfig);
            // verify we no longer have privilege after removing certificate
            assertFalse(mTelephonyManager.hasCarrierPrivileges());
        }
    }

    private void changeCarrierPrivileges(boolean gain, PersistableBundle carrierConfig)
            throws Exception {
        if (mTelephonyManager.hasCarrierPrivileges() == gain) {
            Log.w(TAG, "Carrier privileges already " + (gain ? "granted" : "revoked"));
            return;
        }

        try(CarrierPrivilegeChangeMonitor monitor = new CarrierPrivilegeChangeMonitor()) {
            overrideCarrierConfig(carrierConfig);
            monitor.waitForCarrierPrivilegeChanged();
        }
    }

    private void overrideCarrierConfig(PersistableBundle bundle) throws Exception {
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mCarrierConfigManager,
                (cm) -> cm.overrideConfig(mTestSub, bundle));
    }

    public static void grantLocationPermissions() {
        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
        String packageName = getContext().getPackageName();
        uiAutomation.grantRuntimePermission(packageName, permission.ACCESS_COARSE_LOCATION);
        uiAutomation.grantRuntimePermission(packageName, permission.ACCESS_FINE_LOCATION);
        uiAutomation.grantRuntimePermission(packageName, permission.ACCESS_BACKGROUND_LOCATION);
    }

    @Test
    public void testDevicePolicyApn() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        // These methods aren't accessible to anything except system and phone by design, so we just
        // look for security exceptions here.
        try {
            List<ApnSetting> apns = mTelephonyManager.getDevicePolicyOverrideApns(getContext());
            fail("SecurityException expected");
        } catch (SecurityException e) {
            // expected
        }

        try {
            ApnSetting.Builder builder = new ApnSetting.Builder();

            ApnSetting setting = builder
                    .setEntryName("asdf")
                    .setApnName("asdf")
                    .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT)
                    .build();
            int id = mTelephonyManager.addDevicePolicyOverrideApn(getContext(), setting);
            fail("SecurityException expected");
        } catch (SecurityException e) {
            // expected
        }

        try {
            ApnSetting.Builder builder = new ApnSetting.Builder();

            ApnSetting setting = builder
                    .setEntryName("asdf")
                    .setApnName("asdf")
                    .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT)
                    .build();
            boolean success = mTelephonyManager.modifyDevicePolicyOverrideApn(
                    getContext(), 0, setting);
            fail("SecurityException expected");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testListen() throws Throwable {
        if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
            // TODO: temp workaround, need to adjust test to for CDMA
            return;
        }

        grantLocationPermissions();

        TestThread t = new TestThread(() -> {
            Looper.prepare();
            mListener = new PhoneStateListener() {
                @Override
                public void onCellLocationChanged(CellLocation location) {
                    if (!mOnCellLocationChangedCalled) {
                        synchronized (mLock) {
                            mOnCellLocationChangedCalled = true;
                            mLock.notify();
                        }
                    }
                }
            };

            synchronized (mLock) {
                mLock.notify(); // mListener is ready
            }

            Looper.loop();
        });

        synchronized (mLock) {
            t.start();
            mLock.wait(TOLERANCE); // wait for mListener
        }

        // Test register
        synchronized (mLock) {
            // .listen generates an onCellLocationChanged event
            mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_CELL_LOCATION);
            mLock.wait(TOLERANCE);

            assertTrue("Test register, mOnCellLocationChangedCalled should be true.",
                    mOnCellLocationChangedCalled);
        }

        synchronized (mLock) {
            mOnCellLocationChangedCalled = false;
            CellLocation.requestLocationUpdate();
            mLock.wait(TOLERANCE);

            // Starting with Android S, this API will silently drop all requests from apps
            // targeting Android S due to unfixable limitations with the API.
            assertFalse("Test register, mOnCellLocationChangedCalled should be false.",
                    mOnCellLocationChangedCalled);
        }

        // unregister the listener
        mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
        Thread.sleep(TOLERANCE);

        // Test unregister
        synchronized (mLock) {
            mOnCellLocationChangedCalled = false;
            // unregister again, to make sure doing so does not call the listener
            mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
            CellLocation.requestLocationUpdate();
            mLock.wait(TOLERANCE);

            assertFalse("Test unregister, mOnCellLocationChangedCalled should be false.",
                    mOnCellLocationChangedCalled);
        }
    }

    /**
     * The getter methods here are all related to the information about the telephony.
     * These getters are related to concrete location, phone, service provider company, so
     * it's no need to get details of these information, just make sure they are in right
     * condition(>0 or not null).
     */
    @Test
    public void testTelephonyManager() {
        assertTrue(mTelephonyManager.getNetworkType() >= TelephonyManager.NETWORK_TYPE_UNKNOWN);
        assertTrue(mTelephonyManager.getPhoneType() >= TelephonyManager.PHONE_TYPE_NONE);
        assertTrue(mTelephonyManager.getSimState() >= TelephonyManager.SIM_STATE_UNKNOWN);
        assertTrue(mTelephonyManager.getDataActivity() >= TelephonyManager.DATA_ACTIVITY_NONE);
        assertTrue(mTelephonyManager.getDataState() >= TelephonyManager.DATA_DISCONNECTED);
        assertTrue(mTelephonyManager.getCallState() >= TelephonyManager.CALL_STATE_IDLE);

        for (int i = 0; i < mTelephonyManager.getPhoneCount(); ++i) {
            assertTrue(mTelephonyManager.getSimState(i) >= TelephonyManager.SIM_STATE_UNKNOWN);
        }

        // Make sure devices without MMS service won't fail on this
        if (InstrumentationRegistry.getContext().getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
                && (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE)) {
            assertFalse(mTelephonyManager.getMmsUserAgent().isEmpty());
            assertFalse(mTelephonyManager.getMmsUAProfUrl().isEmpty());
        }

        // The following methods may return any value depending on the state of the device. Simply
        // call them to make sure they do not throw any exceptions.
        mTelephonyManager.getVoiceMailNumber();
        mTelephonyManager.getSimOperatorName();
        mTelephonyManager.getNetworkCountryIso();
        mTelephonyManager.getCellLocation();
        mTelephonyManager.getSimCarrierId();
        mTelephonyManager.getSimCarrierIdName();
        mTelephonyManager.getSimSpecificCarrierId();
        mTelephonyManager.getSimSpecificCarrierIdName();
        mTelephonyManager.getCarrierIdFromSimMccMnc();
        mTelephonyManager.isDataRoamingEnabled();
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getSimSerialNumber());
        mTelephonyManager.getSimOperator();
        mTelephonyManager.getSignalStrength();
        mTelephonyManager.getNetworkOperatorName();
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getSubscriberId());
        mTelephonyManager.getLine1Number();
        mTelephonyManager.getNetworkOperator();

        try {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .adoptShellPermissionIdentity(
                        android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
            mTelephonyManager.getPhoneAccountHandle();
        } catch (SecurityException e) {
            fail("TelephonyManager#getPhoneAccountHandle requires READ_PRIVILEGED_PHONE_STATE");
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .dropShellPermissionIdentity();
        }
        mTelephonyManager.getSimCountryIso();
        mTelephonyManager.getVoiceMailAlphaTag();
        mTelephonyManager.isNetworkRoaming();
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getDeviceId());
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getDeviceId(mTelephonyManager.getSlotIndex()));
        mTelephonyManager.getDeviceSoftwareVersion();
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getDeviceSoftwareVersion(mTelephonyManager.getSlotIndex()));
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getImei());
        if (mModemHalVersion >= RADIO_HAL_VERSION_2_1) {
            ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    (tm) -> tm.getPrimaryImei());
        }
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getImei(mTelephonyManager.getSlotIndex()));
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.isManualNetworkSelectionAllowed());
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getManualNetworkSelectionPlmn());

        mTelephonyManager.getPhoneCount();
        mTelephonyManager.getDataEnabled();
        mTelephonyManager.getNetworkSpecifier();
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager, (tm) -> tm.getNai());
        TelecomManager telecomManager = getContext().getSystemService(TelecomManager.class);
        PhoneAccountHandle defaultAccount = telecomManager
                .getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
        mTelephonyManager.getVoicemailRingtoneUri(defaultAccount);
        mTelephonyManager.isVoicemailVibrationEnabled(defaultAccount);
        mTelephonyManager.getSubscriptionId(defaultAccount);
        mTelephonyManager.getCarrierConfig();
        mTelephonyManager.isVoiceCapable();
        mTelephonyManager.isSmsCapable();
        mTelephonyManager.isLteCdmaEvdoGsmWcdmaEnabled();
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.isDataConnectionAllowed());
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.isAnyRadioPoweredOn());
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                (tm) -> tm.resetIms(tm.getSlotIndex()));

        // Verify TelephonyManager.getCarrierPrivilegeStatus
        List<Integer> validCarrierPrivilegeStatus = new ArrayList<>();
        validCarrierPrivilegeStatus.add(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
        validCarrierPrivilegeStatus.add(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
        validCarrierPrivilegeStatus.add(
                TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED);
        validCarrierPrivilegeStatus.add(
                TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES);
        int carrierPrivilegeStatusResult = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.getCarrierPrivilegeStatus(Process.myUid()));
        assertTrue(validCarrierPrivilegeStatus.contains(carrierPrivilegeStatusResult));

        // Verify TelephonyManager.getCarrierPrivilegedPackagesForAllActiveSubscriptions
        List<String> resultForGetCarrierPrivilegedApis =
                ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                        (tm) -> tm.getCarrierPrivilegedPackagesForAllActiveSubscriptions());
        assertNotNull(resultForGetCarrierPrivilegedApis);
        for (String result : resultForGetCarrierPrivilegedApis) {
            assertFalse(TextUtils.isEmpty(result));
        }

        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                TelephonyManager::getDefaultRespondViaMessageApplication);
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                TelephonyManager::getAndUpdateDefaultRespondViaMessageApplication);

        // Verify getImei/getSubscriberId/getIccAuthentication:
        // With app ops permision USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, should not throw
        // SecurityException.
        try {
            setAppOpsPermissionAllowed(true, OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER);

            mTelephonyManager.getImei();
            if (mModemHalVersion >= RADIO_HAL_VERSION_2_1) {
                mTelephonyManager.getPrimaryImei();
            }
            mTelephonyManager.getSubscriberId();
            mTelephonyManager.getIccAuthentication(
                    TelephonyManager.APPTYPE_USIM, TelephonyManager.AUTHTYPE_EAP_AKA, "");
        } finally {
            setAppOpsPermissionAllowed(false, OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER);
        }

        // Verify getIccAuthentication:
        // With app ops permission USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, should not throw
        // SecurityException.
        try {
            setAppOpsPermissionAllowed(true, OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER);

            mTelephonyManager.getIccAuthentication(
                    TelephonyManager.APPTYPE_USIM, TelephonyManager.AUTHTYPE_GBA_BOOTSTRAP, "");
        } finally {
            setAppOpsPermissionAllowed(false, OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER);
        }

        // Verify getIccAuthentication:
        // With app ops permission USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, should not throw
        // SecurityException.
        try {
            setAppOpsPermissionAllowed(true, OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER);

            mTelephonyManager.getIccAuthentication(
                    TelephonyManager.APPTYPE_USIM, TelephonyManager.AUTHTYPE_GBA_NAF_KEY_EXTERNAL,
                    "");
        } finally {
            setAppOpsPermissionAllowed(false, OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER);
        }
    }

    @Test
    public void testGetCallForwarding() throws Exception {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CALLING));

        List<Integer> callForwardingReasons = new ArrayList<>();
        callForwardingReasons.add(CallForwardingInfo.REASON_UNCONDITIONAL);
        callForwardingReasons.add(CallForwardingInfo.REASON_BUSY);
        callForwardingReasons.add(CallForwardingInfo.REASON_NO_REPLY);
        callForwardingReasons.add(CallForwardingInfo.REASON_NOT_REACHABLE);
        callForwardingReasons.add(CallForwardingInfo.REASON_ALL);
        callForwardingReasons.add(CallForwardingInfo.REASON_ALL_CONDITIONAL);

        Set<Integer> callForwardingErrors = new HashSet<Integer>();
        callForwardingErrors.add(TelephonyManager.CallForwardingInfoCallback
                .RESULT_ERROR_FDN_CHECK_FAILURE);
        callForwardingErrors.add(TelephonyManager.CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN);
        callForwardingErrors.add(TelephonyManager.CallForwardingInfoCallback
                .RESULT_ERROR_NOT_SUPPORTED);

        for (int callForwardingReasonToGet : callForwardingReasons) {
            Log.d(TAG, "[testGetCallForwarding] callForwardingReasonToGet: "
                    + callForwardingReasonToGet);
            AtomicReference<CallForwardingInfo> receivedForwardingInfo = new AtomicReference<>();
            AtomicReference<Integer> receivedErrorCode = new AtomicReference<>();
            CountDownLatch latch = new CountDownLatch(1);
            TelephonyManager.CallForwardingInfoCallback callback =
                    new TelephonyManager.CallForwardingInfoCallback() {
                        @Override
                        public void onCallForwardingInfoAvailable(CallForwardingInfo info) {
                            receivedForwardingInfo.set(info);
                            latch.countDown();
                        }

                        @Override
                        public void onError(int error) {
                            receivedErrorCode.set(error);
                            latch.countDown();
                        }
            };
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.getCallForwarding(callForwardingReasonToGet,
                            getContext().getMainExecutor(), callback));

            assertTrue(latch.await(TIMEOUT_FOR_NETWORK_OPS, TimeUnit.MILLISECONDS));
            // Make sure only one of the callbacks gets invoked
            assertTrue((receivedForwardingInfo.get() != null) ^ (receivedErrorCode.get() != null));
            if (receivedForwardingInfo.get() != null) {
                CallForwardingInfo info = receivedForwardingInfo.get();
                assertTrue("Got reason not in expected set:" + info.getReason(),
                        callForwardingReasons.contains(info.getReason()));
                if (info.isEnabled()) {
                    assertNotNull(info.getNumber());
                    assertTrue("Got negative timeoutSeconds=" + info.getTimeoutSeconds(),
                            info.getTimeoutSeconds() >= 0);
                }
            }

            if (receivedErrorCode.get() != null) {
                assertTrue("Got code not in expected set:" + receivedErrorCode.get(),
                        callForwardingErrors.contains(receivedErrorCode.get()));
            }
        }
    }

    @Test
    public void testSetCallForwarding() throws Exception {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CALLING));

        List<Integer> callForwardingReasons = new ArrayList<>();
        callForwardingReasons.add(CallForwardingInfo.REASON_UNCONDITIONAL);
        callForwardingReasons.add(CallForwardingInfo.REASON_BUSY);
        callForwardingReasons.add(CallForwardingInfo.REASON_NO_REPLY);
        callForwardingReasons.add(CallForwardingInfo.REASON_NOT_REACHABLE);
        callForwardingReasons.add(CallForwardingInfo.REASON_ALL);
        callForwardingReasons.add(CallForwardingInfo.REASON_ALL_CONDITIONAL);

        // Enable Call Forwarding
        for (int callForwardingReasonToEnable : callForwardingReasons) {
            CountDownLatch latch = new CountDownLatch(1);
            // Disregard success or failure; just make sure it reports back.
            Consumer<Integer> ignoringResultListener = (x) -> latch.countDown();

            final CallForwardingInfo callForwardingInfoToEnable = new CallForwardingInfo(
                    true,
                    callForwardingReasonToEnable,
                    TEST_FORWARD_NUMBER,
                    // time seconds
                    1);
            Log.d(TAG, "[testSetCallForwarding] Enable Call Forwarding. Reason: "
                    + callForwardingReasonToEnable + " Number: " + TEST_FORWARD_NUMBER
                    + " Time Seconds: 1");
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setCallForwarding(callForwardingInfoToEnable,
                            getContext().getMainExecutor(), ignoringResultListener));
            // TODO: this takes way too long on a real network (upwards of 40s).
            // assertTrue("No response for forwarding for reason " + callForwardingReasonToEnable,
            //        latch.await(TIMEOUT_FOR_NETWORK_OPS * 3, TimeUnit.MILLISECONDS));
        }

        // Disable Call Forwarding
        for (int callForwardingReasonToDisable : callForwardingReasons) {
            CountDownLatch latch = new CountDownLatch(1);
            // Disregard success or failure; just make sure it reports back.
            Consumer<Integer> ignoringResultListener = (x) -> latch.countDown();

            final CallForwardingInfo callForwardingInfoToDisable = new CallForwardingInfo(
                    false,
                    callForwardingReasonToDisable,
                    TEST_FORWARD_NUMBER,
                    // time seconds
                    1);
            Log.d(TAG, "[testSetCallForwarding] Disable Call Forwarding. Reason: "
                    + callForwardingReasonToDisable + " Number: " + TEST_FORWARD_NUMBER
                    + " Time Seconds: 1");
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setCallForwarding(callForwardingInfoToDisable,
                            getContext().getMainExecutor(), ignoringResultListener));
            // TODO: this takes way too long on a real network (upwards of 40s).
            //assertTrue("No response for forwarding for reason " + callForwardingReasonToDisable,
            //        latch.await(TIMEOUT_FOR_NETWORK_OPS * 3, TimeUnit.MILLISECONDS));
        }
    }

    @Test
    public void testGetCallWaitingStatus() throws Exception {
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            Log.d(TAG, "skipping test on device without FEATURE_TELEPHONY present");
            return;
        }
        Set<Integer> validCallWaitingStatuses = new HashSet<Integer>();
        validCallWaitingStatuses.add(TelephonyManager.CALL_WAITING_STATUS_ENABLED);
        validCallWaitingStatuses.add(TelephonyManager.CALL_WAITING_STATUS_DISABLED);
        validCallWaitingStatuses.add(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
        validCallWaitingStatuses.add(TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED);
        validCallWaitingStatuses.add(TelephonyManager.CALL_WAITING_STATUS_FDN_CHECK_FAILURE);

        LinkedBlockingQueue<Integer> callWaitingStatusResult = new LinkedBlockingQueue<>(1);
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager, (tm) -> tm.getCallWaitingStatus(getContext().getMainExecutor(),
                        callWaitingStatusResult::offer));
        assertTrue(validCallWaitingStatuses.contains(
                callWaitingStatusResult.poll(TIMEOUT_FOR_NETWORK_OPS, TimeUnit.MILLISECONDS)));
    }

    @Test
    public void testSetCallWaitingStatus() throws Exception {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CALLING));

        Set<Integer> validCallWaitingErrors = new HashSet<Integer>();
        validCallWaitingErrors.add(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
        validCallWaitingErrors.add(TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED);
        validCallWaitingErrors.add(TelephonyManager.CALL_WAITING_STATUS_FDN_CHECK_FAILURE);
        Executor executor = getContext().getMainExecutor();
        {
            LinkedBlockingQueue<Integer> callWaitingResult = new LinkedBlockingQueue<>(1);

            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setCallWaitingEnabled(true, executor, callWaitingResult::offer));
            Integer result = callWaitingResult.poll(TIMEOUT_FOR_NETWORK_OPS, TimeUnit.MILLISECONDS);
            assertNotNull("Never got callback from set call waiting", result);
            if (result != TelephonyManager.CALL_WAITING_STATUS_ENABLED) {
                assertTrue("Call waiting callback got an invalid value: " + result,
                        validCallWaitingErrors.contains(result));
            }
        }

        {
            LinkedBlockingQueue<Integer> callWaitingResult = new LinkedBlockingQueue<>(1);

            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setCallWaitingEnabled(false, executor, callWaitingResult::offer));
            Integer result = callWaitingResult.poll(TIMEOUT_FOR_NETWORK_OPS, TimeUnit.MILLISECONDS);
            assertNotNull("Never got callback from set call waiting", result);
            if (result != TelephonyManager.CALL_WAITING_STATUS_DISABLED) {
                assertTrue("Call waiting callback got an invalid value: " + result,
                        validCallWaitingErrors.contains(result));
            }
        }
    }

    @Test
    public void testGetHalVersion() {
        Pair<Integer, Integer> halversion;
        for (int i = TelephonyManager.HAL_SERVICE_DATA;
                i <= TelephonyManager.HAL_SERVICE_VOICE; i++) {
            halversion = mTelephonyManager.getHalVersion(i);

            // The version must be valid, and the versions start with 1.0
            assertFalse("Invalid HAL Version (" + halversion + ") of service (" + i + ")",
                    halversion.first < 1 || halversion.second < 0);
        }
    }

    @Test
    public void testCreateForPhoneAccountHandle() {
        if (!mTelephonyManager.isVoiceCapable()) {
            Log.d(TAG, "Skipping test that requires config_voice_capable is true");
            return;
        }
        int subId = SubscriptionManager.getDefaultDataSubscriptionId();
        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            Log.d(TAG, "Skipping test that requires DefaultDataSubscriptionId setting");
            return;
        }

        TelecomManager telecomManager = getContext().getSystemService(TelecomManager.class);
        PhoneAccountHandle handle =
                telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
        TelephonyManager telephonyManager = mTelephonyManager.createForPhoneAccountHandle(handle);
        String globalSubscriberId = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.getSubscriberId());
        String localSubscriberId = ShellIdentityUtils.invokeMethodWithShellPermissions(
                telephonyManager, (tm) -> tm.getSubscriberId());
        assertEquals(globalSubscriberId, localSubscriberId);
    }

    @Test
    public void testCreateForPhoneAccountHandle_InvalidHandle(){
        PhoneAccountHandle handle =
                new PhoneAccountHandle(new ComponentName("com.example.foo", "bar"), "baz");
        assertNull(mTelephonyManager.createForPhoneAccountHandle(handle));
    }

    @Test
    @ApiTest(apis = {"android.telephony.TelephonyManager#getPhoneAccountHandle"})
    public void testGetPhoneAccountHandle() {
        TelecomManager telecomManager = getContext().getSystemService(TelecomManager.class);
        List<PhoneAccountHandle> callCapableAccounts = telecomManager
                .getCallCapablePhoneAccounts();
        try {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .adoptShellPermissionIdentity(
                        android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
            PhoneAccountHandle phoneAccountHandle = mTelephonyManager.getPhoneAccountHandle();
            assertTrue(callCapableAccounts.contains(phoneAccountHandle));
        } catch (SecurityException e) {
            fail("TelephonyManager#getPhoneAccountHandle requires READ_PRIVILEGED_PHONE_STATE");
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .dropShellPermissionIdentity();
        }
    }

    /**
     * Tests that the phone count returned is valid.
     */
    @Test
    public void testGetPhoneCount() {
        int phoneCount = mTelephonyManager.getPhoneCount();
        int phoneType = mTelephonyManager.getPhoneType();
        switch (phoneType) {
            case TelephonyManager.PHONE_TYPE_GSM:
            case TelephonyManager.PHONE_TYPE_CDMA:
                assertTrue("Phone count should be > 0", phoneCount > 0);
                break;
            case TelephonyManager.PHONE_TYPE_NONE:
                assertTrue("Phone count should be >= 0", phoneCount >= 0);
                break;
            default:
                throw new IllegalArgumentException("Did you add a new phone type? " + phoneType);
        }
    }

    /**
     * Tests that the device properly reports either a valid IMEI, MEID/ESN, or a valid MAC address
     * if only a WiFi device. At least one of them must be valid.
     */
    @Test
    public void testGetDeviceId() {
        String deviceId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getDeviceId());
        verifyDeviceId(deviceId);
    }

    /**
     * Tests the max number of active SIMs method
     */
    @Test
    public void testGetMaxNumberOfSimultaneouslyActiveSims() {
        int maxNum = mTelephonyManager.getMaxNumberOfSimultaneouslyActiveSims();
        assertTrue(maxNum >= 1);
    }

    /**
     * Tests that the device properly reports either a valid IMEI, MEID/ESN, or a valid MAC address
     * if only a WiFi device. At least one of them must be valid.
     */
    @Test
    public void testGetDeviceIdForSlot() {
        String deviceId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getDeviceId(mTelephonyManager.getSlotIndex()));
        verifyDeviceId(deviceId);
        // Also verify that no exception is thrown for any slot index (including invalid ones)
        for (int i = -1; i <= mTelephonyManager.getPhoneCount(); i++) {
            // The compiler error 'local variables referenced from a lambda expression must be final
            // or effectively final' is reported when using i, so assign it to a final variable.
            final int currI = i;
            ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    (tm) -> tm.getDeviceId(currI));
        }
    }

    private void verifyDeviceId(String deviceId) {
        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            // Either IMEI or MEID need to be valid.
            try {
                assertImei(deviceId);
            } catch (AssertionError e) {
                assertMeidEsn(deviceId);
            }
        } else if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
            assertSerialNumber();
            assertMacAddress(getWifiMacAddress());
        } else if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
            assertSerialNumber();
            assertMacAddress(getBluetoothMacAddress());
        } else if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET)) {
            assertTrue(mCm.getNetworkInfo(ConnectivityManager.TYPE_ETHERNET) != null);
        }
    }

    private static void assertImei(String id) {
        assertFalse("Imei should not be empty or null", TextUtils.isEmpty(id));
        // IMEI must have 15 digits.
        String imeiPattern = "[0-9]{15}";
        String invalidPattern = "[0]{15}";
        assertTrue("IMEI " + id + " does not match pattern " + imeiPattern,
                Pattern.matches(imeiPattern, id));
        assertFalse("IMEI " + id + " must not be a zero sequence" + invalidPattern,
                Pattern.matches(invalidPattern, id));
        // 15th digit must be a check digit.
        assertImeiCheckDigit(id);
    }

    private static void assertImeiCheckDigit(String deviceId) {
        int expectedCheckDigit = getLuhnCheckDigit(deviceId.substring(0, 14));
        int actualCheckDigit = Character.digit(deviceId.charAt(14), 10);
        assertEquals("Incorrect check digit for " + deviceId, expectedCheckDigit, actualCheckDigit);
    }

    /**
     * Use decimal value (0-9) to index into array to get sum of its digits
     * needed by Lunh check.
     *
     * Example: DOUBLE_DIGIT_SUM[6] = 3 because 6 * 2 = 12 => 1 + 2 = 3
     */
    private static final int[] DOUBLE_DIGIT_SUM = {0, 2, 4, 6, 8, 1, 3, 5, 7, 9};

    /**
     * Calculate the check digit by starting from the right, doubling every
     * each digit, summing all the digits including the doubled ones, and
     * finding a number to make the sum divisible by 10.
     *
     * @param deviceId not including the check digit
     * @return the check digit
     */
    private static int getLuhnCheckDigit(String deviceId) {
        int sum = 0;
        int dontDoubleModulus = deviceId.length() % 2;
        for (int i = deviceId.length() - 1; i >= 0; --i) {
            int digit = Character.digit(deviceId.charAt(i), 10);
            if (i % 2 == dontDoubleModulus) {
                sum += digit;
            } else {
                sum += DOUBLE_DIGIT_SUM[digit];
            }
        }
        sum %= 10;
        return sum == 0 ? 0 : 10 - sum;
    }

    private static void assertMeidEsn(String id) {
        // CDMA device IDs may either be a 14-hex-digit MEID or an
        // 8-hex-digit ESN.  If it's an ESN, it may not be a
        // pseudo-ESN.
        assertFalse("Meid ESN should not be empty or null", TextUtils.isEmpty(id));
        if (id.length() == 14) {
            assertMeidFormat(id);
        } else if (id.length() == 8) {
            assertHexadecimalEsnFormat(id);
        } else {
            fail("device id on CDMA must be 14-digit hex MEID or 8-digit hex ESN.");
        }
    }

    private static void assertHexadecimalEsnFormat(String deviceId) {
        String esnPattern = "[0-9a-fA-F]{8}";
        String invalidPattern = "[0]{8}";
        assertTrue("ESN hex device id " + deviceId + " does not match pattern " + esnPattern,
                Pattern.matches(esnPattern, deviceId));
        assertFalse("ESN hex device id " + deviceId + " must not be a pseudo-ESN",
                "80".equals(deviceId.substring(0, 2)));
        assertFalse("ESN hex device id " + deviceId + "must not be a zero sequence",
                Pattern.matches(invalidPattern, deviceId));
    }

    private static void assertMeidFormat(String deviceId) {
        // MEID must NOT include the check digit.
        String meidPattern = "[0-9a-fA-F]{14}";
        String invalidPattern = "[0]{14}";
        assertTrue("MEID device id " + deviceId + " does not match pattern "
                + meidPattern, Pattern.matches(meidPattern, deviceId));
        assertFalse("MEID device id " + deviceId + "must not be a zero sequence",
                Pattern.matches(invalidPattern, deviceId));
    }

    private void assertSerialNumber() {
        String serial = ShellIdentityUtils.invokeStaticMethodWithShellPermissions(
                Build::getSerial);
        assertNotNull("Non-telephony devices must have a Build.getSerial() number.",
                serial);
        assertTrue("Hardware id must be alphanumeric.",
                Pattern.matches("[0-9A-Za-z.,_-]+", serial));
    }

    private void assertMacAddress(String macAddress) {
        String macPattern = "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}";
        assertTrue("MAC Address " + macAddress + " does not match pattern " + macPattern,
                Pattern.matches(macPattern, macAddress));
    }

    /** @return mac address which requires the WiFi system to be enabled */
    private String getWifiMacAddress() {
        WifiManager wifiManager = getContext().getSystemService(WifiManager.class);

        if (wifiManager.isWifiEnabled()) {
            return wifiManager.getConnectionInfo().getMacAddress();
        } else {
            try {
                runWithShellPermissionIdentity(() -> wifiManager.setWifiEnabled(true));

                return wifiManager.getConnectionInfo().getMacAddress();

            } finally {
                runWithShellPermissionIdentity(() -> wifiManager.setWifiEnabled(false));
            }
        }
    }

    private String getBluetoothMacAddress() {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (adapter == null) {
            return "";
        }

        return adapter.getAddress();
    }

    private static final String ISO_COUNTRY_CODE_PATTERN = "[a-z]{2}";

    @Test
    @ApiTest(apis = "android.telephony.TelephonyManager#getNetworkCountryIso")
    public void testGetNetworkCountryIso() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        String countryCode = mTelephonyManager.getNetworkCountryIso();
        ServiceState serviceState = mTelephonyManager.getServiceState();
        if (serviceState != null && (serviceState.getState()
                == ServiceState.STATE_IN_SERVICE || serviceState.getState()
                == ServiceState.STATE_EMERGENCY_ONLY)) {
            assertTrue("Country code '" + countryCode + "' did not match "
                    + ISO_COUNTRY_CODE_PATTERN,
                    Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
        } else {
            assertTrue("Country code could be empty when out of service",
                    Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode)
                    || TextUtils.isEmpty(countryCode));
        }

        int[] allSubs = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mSubscriptionManager, (sm) -> sm.getActiveSubscriptionIdList());
        for (int i : allSubs) {
            countryCode = mTelephonyManager.getNetworkCountryIso(
                    SubscriptionManager.getSlotIndex(i));
            serviceState = mTelephonyManager.createForSubscriptionId(i).getServiceState();

            if (serviceState != null && (serviceState.getState()
                    == ServiceState.STATE_IN_SERVICE || serviceState.getState()
                    == ServiceState.STATE_EMERGENCY_ONLY)) {
                assertTrue("Country code '" + countryCode + "' did not match "
                        + ISO_COUNTRY_CODE_PATTERN + " for slot " + i,
                        Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
            } else {
                assertTrue("Country code could be empty when out of service",
                        Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode)
                        || TextUtils.isEmpty(countryCode));
            }
        }

        for (int i = 0; i < mTelephonyManager.getPhoneCount(); i++) {
            countryCode = mTelephonyManager.getNetworkCountryIso(i);
            assertTrue("Country code must match " + ISO_COUNTRY_CODE_PATTERN + "or empty",
                    Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode)
                    || TextUtils.isEmpty(countryCode));
        }
    }

    @Test
    public void testSetSystemSelectionChannels() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // Get initial list of system selection channels if the API is available
        List<RadioAccessSpecifier> initialSpecifiers = tryGetSystemSelectionChannels();
        // TODO (b/189255895): Don't allow empty or null channels once API is enforced in U.
        boolean getAvailable = initialSpecifiers != null && !initialSpecifiers.isEmpty();
        Log.d(TAG, "getSystemSelectionChannels is " + (getAvailable ? "" : "not ") + "available.");

        List<RadioAccessSpecifier> validSpecifiers = new ArrayList<>();
        List<RadioAccessSpecifier> specifiers;
        for (int accessNetworkType : TelephonyUtils.ALL_BANDS.keySet()) {
            List<Integer> validBands = new ArrayList<>();
            for (int band : TelephonyUtils.ALL_BANDS.get(accessNetworkType)) {
                // Set each band to see which ones are supported by the modem
                RadioAccessSpecifier specifier = new RadioAccessSpecifier(
                        accessNetworkType, new int[]{band}, new int[]{});
                boolean success = trySetSystemSelectionChannels(
                        Collections.singletonList(specifier), true);
                if (success) {
                    validBands.add(band);

                    // Try calling the API that doesn't provide feedback.
                    // We have no way of knowing if it succeeds, so just make sure nothing crashes.
                    trySetSystemSelectionChannels(Collections.singletonList(specifier), false);

                    if (getAvailable) {
                        // Assert that we get back the value we set.
                        specifiers = tryGetSystemSelectionChannels();
                        assertNotNull(specifiers);
                        assertEquals(1, specifiers.size());
                        assertEquals(specifier, specifiers.get(0));
                    }
                }
            }
            if (!validBands.isEmpty()) {
                validSpecifiers.add(new RadioAccessSpecifier(accessNetworkType,
                        validBands.stream().mapToInt(i -> i).toArray(), new int[]{}));
            }
        }

        // Call setSystemSelectionChannels with an empty list and verify no error
        if (!trySetSystemSelectionChannels(Collections.emptyList(), true)) {
            // TODO (b/189255895): Reset initial system selection channels on failure
            fail("Failed to call setSystemSelectionChannels with an empty list.");
        }

        // Verify that getSystemSelectionChannels returns all valid specifiers
        specifiers = tryGetSystemSelectionChannels();
        // TODO (b/189255895): Uncomment in U after getSystemSelectionChannels is enforced
        //assertNotNull(specifiers);
        //assertEquals(specifiers.size(), validSpecifiers.size());
        //assertTrue(specifiers.containsAll(validSpecifiers));

        // Call setSystemSelectionChannels with all valid specifiers to test batch operations
        if (!trySetSystemSelectionChannels(validSpecifiers, true)) {
            // TODO (b/189255895): Reset initial system selection channels on failure
            // TODO (b/189255895): Fail once setSystemSelectionChannels is enforced properly
            Log.e(TAG, "Failed to call setSystemSelectionChannels with all valid specifiers.");
        }

        // Reset the values back to the original.
        if (getAvailable) {
            trySetSystemSelectionChannels(initialSpecifiers, true);
        }
    }

    private List<RadioAccessSpecifier> tryGetSystemSelectionChannels() {
        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
        uiAutomation.adoptShellPermissionIdentity();
        List<RadioAccessSpecifier> channels = null;
        try {
            channels = mTelephonyManager.getSystemSelectionChannels();
        } catch (IllegalStateException ignored) {
            // TODO (b/189255895): Reset and fail in U after getSystemSelectionChannels is enforced
        } finally {
            uiAutomation.dropShellPermissionIdentity();
        }
        return channels;
    }

    private boolean trySetSystemSelectionChannels(List<RadioAccessSpecifier> specifiers,
            boolean useCallback) {
        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
        uiAutomation.adoptShellPermissionIdentity();
        boolean success = false;
        try {
            if (useCallback) {
                LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>(1);
                // This is a oneway binder call, meaning we may return before the permission check
                // happens. Hold shell permissions until we get a response.
                mTelephonyManager.setSystemSelectionChannels(
                        specifiers, getContext().getMainExecutor(), queue::offer);
                Boolean result = queue.poll(2000, TimeUnit.MILLISECONDS);

                // Ensure we get a result
                assertNotNull(result);
                success = result;
            } else {
                mTelephonyManager.setSystemSelectionChannels(specifiers);
                success = true;
            }
        } catch (InterruptedException e) {
            // TODO (b/189255895): Reset initial system selection channels on failure
            fail("setSystemSelectionChannels interrupted.");
        } finally {
            uiAutomation.dropShellPermissionIdentity();
        }
        return success;
    }

    @Test
    public void testGetSimCountryIso() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        String countryCode = mTelephonyManager.getSimCountryIso();
        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) &&
                !countryCode.isEmpty()) {
            assertTrue("Country code '" + countryCode + "' did not match "
                            + ISO_COUNTRY_CODE_PATTERN,
                    Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
        } else {
            // Non-telephony may still have the property defined if it has a SIM.
        }
    }

    @Test
    public void testResetSettings() throws Exception {
        UserManager userManager = getContext().getSystemService(UserManager.class);

        boolean canChangeMobileNetworkSettings = userManager != null
                && !userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
        assertTrue("Primary user must be able to configure mobile networks to pass this test",
                canChangeMobileNetworkSettings);
        boolean initialDataSetting = isDataEnabled();

        //First check permissions are correct
        try {
            mTelephonyManager.resetSettings();
            fail("TelephonyManager#resetSettings requires the"
                    + " android.Manifest.permission.NETWORK_SETTINGS permission");
        } catch (SecurityException e) {
            //expected
        }
        // and then do a reset to move data to default.
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    TelephonyManager::resetSettings,
                    android.Manifest.permission.NETWORK_SETTINGS,
                    android.Manifest.permission.MODIFY_PHONE_STATE);
        } catch (SecurityException e) {
            e.printStackTrace();
            fail(e.toString());
        }
        // This may timeout because the default is equal to the initial data setting, but there is
        // no way to definitively check what the default should be, so assume the default will be
        // set within TOLERANCE time.
        TelephonyUtils.pollUntilTrue(() -> initialDataSetting != isDataEnabled(), 5 /*times*/,
                TOLERANCE/5 /*timeout per poll*/);

        boolean defaultDataSetting = isDataEnabled();

        // set data to not the default!
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setDataEnabled(!defaultDataSetting));
        assertTrue("Data enable change didn't work",
                TelephonyUtils.pollUntilTrue(() -> defaultDataSetting != isDataEnabled(),
                        5 /*times*/, TOLERANCE/5 /*timeout per poll*/));

        // and then do a reset to move data to default again.
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    TelephonyManager::resetSettings,
                    android.Manifest.permission.NETWORK_SETTINGS,
                    android.Manifest.permission.MODIFY_PHONE_STATE);
        } catch (SecurityException e) {
            e.printStackTrace();
            fail(e.toString());
        }

        assertTrue("resetSettings did not reset default data",
                TelephonyUtils.pollUntilTrue(() -> defaultDataSetting == isDataEnabled(),
                        5 /*times*/, TOLERANCE/5 /*timeout per poll*/));
    }

    @Test
    public void testNetworkTypeMatchesDataNetworkType() throws Exception {
        assertEquals(mTelephonyManager.getDataNetworkType(),
                mTelephonyManager.getNetworkType());
    }

    @Test
    public void testNetworkTypeMatchesCellIdentity() throws Exception {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
        ServiceState ss = mTelephonyManager.getServiceState();
        assertNotNull(ss);
        for (NetworkRegistrationInfo nri : ss.getNetworkRegistrationInfoList()) {
            final int networkType = nri.getAccessNetworkTechnology();
            final CellIdentity cid = nri.getCellIdentity();
            if (nri.getTransportType() == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
                assertTrue("NetworkType for WLAN transport must be IWLAN if registered or"
                        + " UNKNOWN if unregistered",
                    networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN
                            || networkType == TelephonyManager.NETWORK_TYPE_IWLAN);
                assertNull("There is no valid cell type for WLAN", cid);
                continue;
            }
            if (!nri.isRegistered() && !nri.isEmergencyEnabled()) {
                assertEquals(
                        "Network type cannot be known unless it is providing some service",
                        TelephonyManager.NETWORK_TYPE_UNKNOWN, networkType);
                assertNull(cid);
                continue;
            }

            assertEquals(nri.getTransportType(), AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
            if (nri.isRegistered() || (nri.isEmergencyEnabled() && !nri.isSearching())) {
                assertNotEquals("Network type must be known if it is providing some service",
                        TelephonyManager.NETWORK_TYPE_UNKNOWN, networkType);
                assertNotNull("The cid must be known for a cell providing service", cid);
                // The network type must roughly match the CellIdentity type
                assertTrue("The network type must be valid for the current cell",
                        sNetworkTypes.get(cid.getClass()).contains(networkType));
            }
        }
    }

    @Test
    public void testGetServiceState() throws InterruptedException {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
            return;
        }

        TestThread t = new TestThread(() -> {
            Looper.prepare();

            mListener = new PhoneStateListener() {
                @Override
                public void onServiceStateChanged(ServiceState serviceState) {
                    synchronized (mLock) {
                        mServiceState = serviceState;
                        mLock.notify();
                    }
                }
            };
            mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_SERVICE_STATE);
            Looper.loop();
        });

        synchronized (mLock) {
            t.start();
            mLock.wait(TOLERANCE);
        }

        // Service state changes frequently and there can be a mismatch between the current service
        // state from TelephonyManager and the slightly delayed one from the listener.
        // Retry all assertions multiple times to prevent flaky test failures.
        int retries = 5;
        for (int i = 0; i < retries; i++) {
            try {
                assertEquals(mServiceState, mTelephonyManager.getServiceState());
                // Exit if the assertion passes without an exception
                break;
            } catch (AssertionError e) {
                if (i == retries - 1) {
                    throw(e);
                }
            }
            waitForMs(100);
        }
        for (int i = 0; i < retries; i++) {
            try {
                assertServiceStateSanitization(mServiceState,
                        mTelephonyManager.getServiceState(
                                TelephonyManager.INCLUDE_LOCATION_DATA_NONE));
                // Exit if the assertion passes without an exception
                break;
            } catch (AssertionError e) {
                if (i == retries - 1) {
                    throw(e);
                }
            }
            waitForMs(100);
        }
        for (int i = 0; i < retries; i++) {
            try {
                assertServiceStateFineLocationSanitization(mServiceState,
                        mTelephonyManager.getServiceState(
                                TelephonyManager.INCLUDE_LOCATION_DATA_COARSE));
                // Exit if the assertion passes without an exception
                break;
            } catch (AssertionError e) {
                if (i == retries - 1) {
                    throw(e);
                }
            }
            waitForMs(100);
        }
        for (int i = 0; i < retries; i++) {
            try {
                assertEquals(mServiceState,
                        mTelephonyManager.getServiceState(
                                TelephonyManager.INCLUDE_LOCATION_DATA_FINE));
                // Exit if the assertion passes without an exception
                break;
            } catch (AssertionError e) {
                if (i == retries - 1) {
                    throw(e);
                }
            }
            waitForMs(100);
        }

        NetworkRegistrationInfo regInfo = mServiceState.getNetworkRegistrationInfo(
                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        if (regInfo != null) {
            DataSpecificRegistrationInfo dsri = regInfo.getDataSpecificInfo();
            if (dsri != null) {
                int lteAttachType = dsri.getLteAttachResultType();
                assertTrue(lteAttachType == LTE_ATTACH_TYPE_UNKNOWN
                        || lteAttachType == LTE_ATTACH_TYPE_EPS_ONLY
                        || lteAttachType == LTE_ATTACH_TYPE_COMBINED);

                int lteAttachExtraInfo = dsri.getLteAttachExtraInfo();
                assertTrue(lteAttachExtraInfo == LTE_ATTACH_EXTRA_INFO_NONE
                        || lteAttachExtraInfo == LTE_ATTACH_EXTRA_INFO_SMS_ONLY
                        || lteAttachExtraInfo == LTE_ATTACH_EXTRA_INFO_CSFB_NOT_PREFERRED
                        || lteAttachExtraInfo == (LTE_ATTACH_EXTRA_INFO_SMS_ONLY
                                                 | LTE_ATTACH_EXTRA_INFO_CSFB_NOT_PREFERRED));
            }
        }
    }

    private void assertServiceStateSanitization(ServiceState expectedServiceState,
            ServiceState receivedServiceState) {
        assertNotEquals(null, receivedServiceState);
        assertServiceStateFineLocationSanitization(expectedServiceState, receivedServiceState);

        assertTrue(TextUtils.isEmpty(receivedServiceState.getOperatorAlphaLong()));
        assertTrue(TextUtils.isEmpty(receivedServiceState.getOperatorAlphaShort()));
        assertTrue(TextUtils.isEmpty(receivedServiceState.getOperatorNumeric()));
    }

    private void assertServiceStateFineLocationSanitization(ServiceState expectedServiceState,
            ServiceState receivedServiceState) {
        assertNotEquals(null, receivedServiceState);

        assertEquals(expectedServiceState.getVoiceRegState(),
                receivedServiceState.getVoiceRegState());
        assertEquals(expectedServiceState.getDataRegState(),
                receivedServiceState.getDataRegState());
        assertEquals(expectedServiceState.getDataNetworkType(),
                receivedServiceState.getDataNetworkType());
        assertEquals(expectedServiceState.getDataRoaming(),
                receivedServiceState.getDataRoaming());
        assertEquals(expectedServiceState.getRilVoiceRadioTechnology(),
                receivedServiceState.getRilVoiceRadioTechnology());

        if (receivedServiceState.getNetworkRegistrationInfoList() != null) {
            for (NetworkRegistrationInfo nrs : receivedServiceState
                    .getNetworkRegistrationInfoList()) {
                assertNull(nrs.getCellIdentity());
            }
        }
    }

    @Test
    public void testGetServiceStateForInactiveSub() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
            return;
        }

        int[] allSubs  = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mSubscriptionManager, (sm) ->sm.getActiveSubscriptionIdList());
        // generate a subscription that is valid (>0) but inactive (not part of active subId list)
        // A simple way to do this is sum the active subIds and add 1
        int inactiveValidSub = 1;
        for (int sub : allSubs) {
            inactiveValidSub += sub;
        }

        assertNull(mTelephonyManager.createForSubscriptionId(inactiveValidSub).getServiceState());
    }

    // This test is to ensure the RAT IWLAN is not reported on WWAN transport if the device is
    // operated in AP-assisted mode.
    @Test
    @CddTest(requirement = "7.4.1/C-4-1")
    public void testIWlanServiceState() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
            return;
        }
        String mode = SystemProperties.get("ro.telephony.iwlan_operation_mode");
        if (!mode.equals("legacy")) {
            ServiceState ss = mTelephonyManager.getServiceState();
            if (ss != null) {
                for (NetworkRegistrationInfo nri : ss.getNetworkRegistrationInfoList()) {
                    if (nri.getTransportType() == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
                        assertNotEquals(TelephonyManager.NETWORK_TYPE_IWLAN,
                                nri.getAccessNetworkTechnology());
                    }
                }
            }
        }
    }

    private MockPhoneCapabilityListener mMockPhoneCapabilityListener;

    private class MockPhoneCapabilityListener extends TelephonyCallback
            implements TelephonyCallback.PhoneCapabilityListener {
        @Override
        public void onPhoneCapabilityChanged(PhoneCapability capability) {
            synchronized (mLock) {
                mPhoneCapability = capability;
                mOnPhoneCapabilityChanged = true;
                mLock.notify();
            }
        }
    }

    @Test
    public void testGetPhoneCapabilityAndVerify() {
        boolean is5gStandalone = getContext().getResources().getBoolean(
                Resources.getSystem().getIdentifier("config_telephony5gStandalone", "bool",
                        "android"));
        boolean is5gNonStandalone = getContext().getResources().getBoolean(
                Resources.getSystem().getIdentifier("config_telephony5gNonStandalone", "bool",
                        "android"));
        int[] deviceNrCapabilities = new int[0];
        if (is5gStandalone || is5gNonStandalone) {
            List<Integer> list = new ArrayList<>();
            if (is5gNonStandalone) {
                list.add(DEVICE_NR_CAPABILITY_NSA);
            }
            if (is5gStandalone) {
                list.add(DEVICE_NR_CAPABILITY_SA);
            }
            deviceNrCapabilities = list.stream().mapToInt(Integer::valueOf).toArray();
        }

        PhoneCapability phoneCapability = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.getPhoneCapability());

        assertArrayEquals(deviceNrCapabilities, phoneCapability.getDeviceNrCapabilities());
    }

    @Test
    public void testGetSimLocale() throws InterruptedException {
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            Log.d(TAG,"skipping test that requires Telephony");
            return;
        }
        if (SubscriptionManager.getDefaultSubscriptionId()
                == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            fail("Expected SIM inserted");
        }
        Locale locale = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getSimLocale());
        Log.d(TAG, "testGetSimLocale: " + locale);
        assertNotNull(locale);
    }

    /**
     * Tests that a GSM device properly reports either the correct TAC (type allocation code) or
     * null.
     * The TAC should match the first 8 digits of the IMEI.
     */
    @Test
    public void testGetTac() {
        String tac = mTelephonyManager.getTypeAllocationCode();
        String imei = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getImei());

        if (tac == null || imei == null) {
            return;
        }

        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
                assertEquals(imei.substring(0, 8), tac);
            }
        }
    }

    /**
     * Tests that a CDMA device properly reports either the correct MC (manufacturer code) or null.
     * The MC should match the first 8 digits of the MEID.
     */
    @Test
    public void testGetMc() {
        String mc = mTelephonyManager.getManufacturerCode();
        String meid = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getMeid());

        if (mc == null || meid == null) {
            return;
        }

        // mc and meid should either be null or supported. empty string is not expected even if
        // the device does not support mc/meid.
        assertNotEquals("", mc);
        assertNotEquals("", meid);

        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
                assertEquals(meid.substring(0, 8), mc);
            }
        }
    }

    /**
     * Tests that the device properly reports either a valid IMEI or null.
     */
    @Test
    public void testGetImei() {
        String imei = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getImei());

        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
                assertImei(imei);
            }
        }
    }

    /**
     * Tests that the device properly reports either a valid Primary Imei.
     */
    @Test
    public void testGetPrimaryImei() {
        // make sure the modem supports primaryImei feature
        assumeTrue(mModemHalVersion >= RADIO_HAL_VERSION_2_1);
        String primaryImei = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getPrimaryImei());

        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
                assertImei(primaryImei);
            }
        }
    }

    /**
     * Tests that the device properly reports either a valid IMEI or null.
     */
    @Test
    public void testGetImeiForSlot() {
        for (int i = 0; i < mTelephonyManager.getPhoneCount(); i++) {
            // The compiler error 'local variables referenced from a lambda expression must be final
            // or effectively final' is reported when using i, so assign it to a final variable.
            final int currI = i;
            String imei = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    (tm) -> tm.getImei(currI));
            if (!TextUtils.isEmpty(imei)) {
                assertImei(imei);
            }
        }

        // Also verify that no exception is thrown for any slot index (including invalid ones)
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getImei(-1));
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getImei(mTelephonyManager.getPhoneCount()));
    }

    /**
     * Verifies that {@link TelephonyManager#getRadioPowerState()} does not throw any exception
     * and returns radio on.
     */
    @Test
    public void testGetRadioPowerState() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // Also verify that no exception is thrown.
        assertThat(mTelephonyManager.getRadioPowerState()).isEqualTo(
                TelephonyManager.RADIO_POWER_ON);
    }

    /**
     * Verifies that {@link TelephonyManager#setCarrierDataEnabled(boolean)} does not throw any
     * exception. TODO enhance later if we have an API to get data enabled state.
     */
    @Test
    public void testSetCarrierDataEnabled() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        // Also verify that no exception is thrown.
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                (tm) -> tm.setCarrierDataEnabled(false));
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                (tm) -> tm.setCarrierDataEnabled(true));
    }

    /**
     * Verifies that {@link TelephonyManager#rebootModem()} does not throw any exception
     * and final radio state is radio power on.
     */
    @Test
    public void testRebootRadio() throws Throwable {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
        if (mModemHalVersion <= RADIO_HAL_VERSION_2_2) {
            Log.d(TAG,
                    "Skipping test since rebootModem is not supported/enforced until IRadio 2.3.");
            return;
        }

        TestThread t = new TestThread(() -> {
            Looper.prepare();

            mListener = new PhoneStateListener() {
                @Override
                public void onRadioPowerStateChanged(@RadioPowerState int state) {
                    synchronized (mLock) {
                        if (state == TelephonyManager.RADIO_POWER_ON && mHasRadioPowerOff) {
                            mRadioRebootTriggered = true;
                            mLock.notify();
                        } else if (state == TelephonyManager.RADIO_POWER_OFF) {
                            // reboot must go to power off
                            mHasRadioPowerOff = true;
                        }
                    }
                }
            };
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.listen(mListener,
                            PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED));
            Looper.loop();
        });

        assertThat(mTelephonyManager.getRadioPowerState()).isEqualTo(
                TelephonyManager.RADIO_POWER_ON);
        assertThat(mRadioRebootTriggered).isFalse();
        assertThat(mHasRadioPowerOff).isFalse();
        t.start();
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    TelephonyManager::rebootModem);
        } catch (Exception ex) {
            //skip this test if not supported or unsuccessful (success=false)
            return;
        }

        synchronized (mLock) {
            // reboot takes longer time
            if (!mRadioRebootTriggered) {
                mLock.wait(20000);
            }
        }
        assertThat(mTelephonyManager.getRadioPowerState()).isEqualTo(
                TelephonyManager.RADIO_POWER_ON);
        assertThat(mRadioRebootTriggered).isTrue();

        if (mListener != null) {
            // unregister the listener
            mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
        }

        // note, other telephony states might not resumes properly at this point. e.g, service state
        // might still in the transition from OOS to In service. Thus we need to wait for in
        // service state before running next tests.
        t = new TestThread(() -> {
            Looper.prepare();

            mListener = new PhoneStateListener() {
                @Override
                public void onServiceStateChanged(ServiceState serviceState) {
                    synchronized (mLock) {
                        if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
                            mServiceStateChangedCalled = true;
                            mLock.notify();
                        }
                    }
                }
            };
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.listen(mListener, PhoneStateListener.LISTEN_SERVICE_STATE));
            Looper.loop();
        });

        synchronized (mLock) {
            t.start();
            if (!mServiceStateChangedCalled) {
                mLock.wait(60000);
            }
        }
        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .adoptShellPermissionIdentity(android.Manifest.permission.READ_PHONE_STATE);
        assertThat(mTelephonyManager.getServiceState().getState()).isEqualTo(
                ServiceState.STATE_IN_SERVICE);
    }

    /**
     * Verifies that {@link TelephonyManager#getAidForAppType(int)} does not throw any exception
     * for all supported subscription app type.
     */
    @Test
    public void testGetAidForAppType() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getAidForAppType(TelephonyManager.APPTYPE_SIM));
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getAidForAppType(TelephonyManager.APPTYPE_CSIM));
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getAidForAppType(TelephonyManager.APPTYPE_RUIM));
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getAidForAppType(TelephonyManager.APPTYPE_ISIM));
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getAidForAppType(TelephonyManager.APPTYPE_USIM));
    }

    /**
     * Verifies that {@link TelephonyManager#getIsimDomain()} does not throw any exception
     */
    @Test
    public void testGetIsimDomain() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getIsimDomain());
    }

    /**
     * Verifies that {@link TelephonyManager#getIsimImpu()} does not throw any exception when called
     * and has the correct permissions.
     */
    @Ignore("API moved back to @hide for Android R.")
    @Test
    public void testGetIsimImpu() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                TelephonyManager::getIsimImpu);
        // Try without the correct permissions and ensure it fails.
        try {
            mTelephonyManager.getIsimImpu();
            fail();
        } catch (SecurityException e) {
            // expected
        }
    }

    /**
     * Basic test to ensure {@link NetworkRegistrationInfo#getRegisteredPlmn()} provides valid
     * information.
     */
    @Test
    public void testNetworkRegistrationInfoRegisteredPlmn() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // get NetworkRegistration object
        ServiceState ss = mTelephonyManager.getServiceState();
        assertNotNull(ss);

        boolean hasRegistered = false;
        for (NetworkRegistrationInfo nwReg : ss.getNetworkRegistrationInfoList()) {
            if (nwReg.isRegistered()
                        && nwReg.getTransportType() == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
                hasRegistered = true;
                String plmnId = nwReg.getRegisteredPlmn();
                // CDMA doesn't have PLMN IDs. Rather than put CID|NID here, instead it will be
                // empty. It's a case that's becoming less important over time, but for now a
                // device that's only registered on CDMA needs to pass this test.
                if (nwReg.getCellIdentity() instanceof android.telephony.CellIdentityCdma) {
                    assertTrue(TextUtils.isEmpty(plmnId));
                } else {
                    assertFalse(TextUtils.isEmpty(plmnId));
                    assertTrue("PlmnId() out of range [00000 - 999999], PLMN ID=" + plmnId,
                            plmnId.matches("^[0-9]{5,6}$"));
                }
            }
        }
        assertTrue(hasRegistered);
    }

    /**
     * Basic test to ensure {@link NetworkRegistrationInfo#isRoaming()} does not throw any
     * exception.
     */
    @Test
    public void testNetworkRegistrationInfoIsRoaming() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // get NetworkRegistration object
        NetworkRegistrationInfo nwReg = mTelephonyManager.getServiceState()
                .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS,
                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        assertThat(nwReg).isNotNull();
        nwReg.isRoaming();
    }

    /**
     * Basic test to ensure {@link NetworkRegistrationInfo#getRoamingType()} does not throw any
     * exception and returns valid result
     * @see ServiceState.RoamingType
     */
    @Test
    public void testNetworkRegistrationInfoGetRoamingType() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // get NetworkRegistration object for voice
        NetworkRegistrationInfo nwReg = mTelephonyManager.getServiceState()
                .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS,
                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        assertNotNull(nwReg);
        assertThat(nwReg.getRoamingType()).isIn(ROAMING_TYPES);

        // getNetworkRegistration object for data
        // get NetworkRegistration object for voice
        nwReg = mTelephonyManager.getServiceState()
                .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        assertThat(nwReg).isNotNull();
        assertThat(nwReg.getRoamingType()).isIn(ROAMING_TYPES);
    }

    /**
     * Basic test to ensure {@link NetworkRegistrationInfo#getAccessNetworkTechnology()} not
     * throw any exception and returns valid result
     * @see android.telephony.Annotation.NetworkType
     */
    @Test
    public void testNetworkRegistationStateGetAccessNetworkTechnology() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // get NetworkRegistration object for voice
        NetworkRegistrationInfo nwReg = mTelephonyManager.getServiceState()
                .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS,
                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        assertThat(nwReg).isNotNull();
        assertThat(nwReg.getAccessNetworkTechnology()).isIn(NETWORK_TYPES);

        // get NetworkRegistation object for data
        nwReg = mTelephonyManager.getServiceState()
                .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        assertThat(nwReg).isNotNull();
        assertThat(nwReg.getAccessNetworkTechnology()).isIn(NETWORK_TYPES);
    }


    /**
     * Tests that the device properly reports either a valid MEID or null.
     */
    @Test
    public void testGetMeid() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CDMA));

        String meid = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getMeid());

        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
                assertMeidEsn(meid);
            }
        }
    }

    /**
     * Tests that the device properly reports either a valid MEID or null.
     */
    @Test
    public void testGetMeidForSlot() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CDMA));

        SubscriptionManager sm = SubscriptionManager.from(getContext());
        List<SubscriptionInfo> subInfos = sm.getActiveSubscriptionInfoList();

        if (subInfos != null) {
            for (SubscriptionInfo subInfo : subInfos) {
                int slotIndex = subInfo.getSimSlotIndex();
                int subId = subInfo.getSubscriptionId();
                TelephonyManager tm = mTelephonyManager.createForSubscriptionId(subId);
                if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
                    String meid = ShellIdentityUtils.invokeMethodWithShellPermissions(
                            mTelephonyManager,
                            (telephonyManager) -> telephonyManager.getMeid(slotIndex));

                    if (!TextUtils.isEmpty(meid)) {
                        assertMeidEsn(meid);
                    }
                }
            }
        }

        // Also verify that no exception is thrown for any slot index (including invalid ones)
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getMeid(-1));
        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getMeid(mTelephonyManager.getPhoneCount()));
    }

    /**
     * Tests sendDialerSpecialCode API.
     * Expects a security exception since the caller does not have carrier privileges or is not the
     * current default dialer app.
     */
    @Test
    public void testSendDialerSpecialCode() {
        try {
            mTelephonyManager.sendDialerSpecialCode("4636");
            fail("Expected SecurityException. App does not have carrier privileges or is not the "
                    + "default dialer app");
        } catch (SecurityException expected) {
        }
    }

    /**
     * Tests that the device properly reports the contents of EF_FPLMN or null
     */
    @Test
    public void testGetForbiddenPlmns() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        String[] plmns = mTelephonyManager.getForbiddenPlmns();

        int phoneType = mTelephonyManager.getPhoneType();
        switch (phoneType) {
            case TelephonyManager.PHONE_TYPE_GSM:
                assertNotNull("Forbidden PLMNs must be valid or an empty list!", plmns);
            case TelephonyManager.PHONE_TYPE_CDMA:
            case TelephonyManager.PHONE_TYPE_NONE:
                if (plmns == null) {
                    return;
                }
        }

        for(String plmn : plmns) {
            assertTrue(
                    "Invalid Length for PLMN-ID, must be 5 or 6! plmn=" + plmn,
                    plmn.length() >= 5 && plmn.length() <= 6);
            assertTrue(
                    "PLMNs must be strings of digits 0-9! plmn=" + plmn,
                    android.text.TextUtils.isDigitsOnly(plmn));
        }
    }

    /**
     * Tests that the device properly sets and pads the contents of EF_FPLMN
     */
    @Test
    public void testSetForbiddenPlmns() {
        assumeTrue(supportSetFplmn());

        String[] originalFplmns = mTelephonyManager.getForbiddenPlmns();
        try {
            int numFplmnsSet = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.setForbiddenPlmns(FPLMN_TEST));
            String[] writtenFplmns = mTelephonyManager.getForbiddenPlmns();
            assertEquals("Wrong return value for setFplmns with less than required fplmns: "
                    + numFplmnsSet, FPLMN_TEST.size(), numFplmnsSet);
            assertEquals("Wrong Fplmns content written", FPLMN_TEST, Arrays.asList(writtenFplmns));
        } finally {
            // Restore
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.setForbiddenPlmns(Arrays.asList(originalFplmns)));
        }
    }

    /**
     * Tests that the device properly truncates the contents of EF_FPLMN when provided size
     * is too big.
     */
    @Test
    public void testSetForbiddenPlmnsTruncate() {
        assumeTrue(supportSetFplmn());

        String[] originalFplmns = mTelephonyManager.getForbiddenPlmns();
        try {
            List<String> targetFplmns = new ArrayList<>();
            for (int i = 0; i < MIN_FPLMN_NUM; i++) {
                targetFplmns.add(PLMN_A);
            }
            for (int i = MIN_FPLMN_NUM; i < MAX_FPLMN_NUM; i++) {
                targetFplmns.add(PLMN_B);
            }
            int numFplmnsSet = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.setForbiddenPlmns(targetFplmns));
            String[] writtenFplmns = mTelephonyManager.getForbiddenPlmns();
            assertTrue("Wrong return value for setFplmns with overflowing fplmns: " + numFplmnsSet,
                    numFplmnsSet < MAX_FPLMN_NUM);
            assertEquals("Number of Fplmns set does not equal number of Fplmns available",
                    numFplmnsSet, writtenFplmns.length);
            assertEquals("Wrong Fplmns content written", targetFplmns.subList(0, numFplmnsSet),
                    Arrays.asList(writtenFplmns));
        } finally {
            // Restore
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.setForbiddenPlmns(Arrays.asList(originalFplmns)));
        }
    }

    /**
     * Tests that the device properly deletes the contents of EF_FPLMN
     */
    @Test
    public void testSetForbiddenPlmnsDelete() {
        assumeTrue(supportSetFplmn());

        String[] originalFplmns = mTelephonyManager.getForbiddenPlmns();
        try {
            // Support test for empty SIM
            List<String> targetDummyFplmns = new ArrayList<>();
            for (int i = 0; i < MIN_FPLMN_NUM; i++) {
                targetDummyFplmns.add(PLMN_A);
            }
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.setForbiddenPlmns(targetDummyFplmns));
            String[] writtenDummyFplmns = mTelephonyManager.getForbiddenPlmns();
            assertEquals(targetDummyFplmns, Arrays.asList(writtenDummyFplmns));

            List<String> targetFplmns = new ArrayList<>();
            int numFplmnsSet = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.setForbiddenPlmns(targetFplmns));
            String[] writtenFplmns = mTelephonyManager.getForbiddenPlmns();
            assertEquals("Wrong return value for setFplmns with empty list", 0, numFplmnsSet);
            assertEquals("Wrong number of Fplmns written", 0, writtenFplmns.length);
            // TODO wait for 10 minutes or so for the FPLMNS list to grow back
        } finally {
            // Restore
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.setForbiddenPlmns(Arrays.asList(originalFplmns)));
        }
    }


    /**
     * Tests that setForbiddenPlmns properly handles null input
     */
    @Test
    public void testSetForbiddenPlmnsVoid() {
        assumeTrue(supportSetFplmn());

        String[] originalFplmns = mTelephonyManager.getForbiddenPlmns();
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.setForbiddenPlmns(null));
            fail("Expected IllegalArgumentException. Null input is not allowed");
        } catch (IllegalArgumentException expected) {
        } finally {
            // Restore
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.setForbiddenPlmns(Arrays.asList(originalFplmns)));
        }
    }

    @Test
    public void testGetEquivalentHomePlmns() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        List<String> plmns = mTelephonyManager.getEquivalentHomePlmns();

        if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
            assertEquals(0, plmns.size());
        } else {
            for (String plmn : plmns) {
                assertTrue(
                        "Invalid Length for PLMN-ID, must be 5 or 6! plmn=" + plmn,
                        plmn.length() >= 5 && plmn.length() <= 6);
                assertTrue(
                        "PLMNs must be strings of digits 0-9! plmn=" + plmn,
                        android.text.TextUtils.isDigitsOnly(plmn));
            }
        }
    }

    /**
     * Tests that the device properly reports the contents of ManualNetworkSelectionPlmn
     * The setting is not persisted selection
     */
    @Test
    public void testGetManualNetworkSelectionPlmnNonPersisted() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        if (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_GSM) return;

        try {
            ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    (tm) -> tm.setNetworkSelectionModeManual(
                     TESTING_PLMN/* operatorNumeric */, false /* persistSelection */));
            String plmn = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                     (tm) -> tm.getManualNetworkSelectionPlmn());
            assertEquals(TESTING_PLMN, plmn);
        } finally {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setNetworkSelectionModeAutomatic());
        }
    }

    /**
     * Tests that the device properly reports the contents of ManualNetworkSelectionPlmn
     * The setting is persisted selection
     */
    @Test
    public void testGetManualNetworkSelectionPlmnPersisted() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        if (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_GSM) return;

        try {
            ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    (tm) -> tm.setNetworkSelectionModeManual(
                     TESTING_PLMN/* operatorNumeric */, true /* persistSelection */));
            String plmn = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                     (tm) -> tm.getManualNetworkSelectionPlmn());
            assertEquals(TESTING_PLMN, plmn);
        } finally {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setNetworkSelectionModeAutomatic());
        }
    }

    /**
     * Verify that TelephonyManager.getCardIdForDefaultEuicc returns a positive value or either
     * UNINITIALIZED_CARD_ID or UNSUPPORTED_CARD_ID.
     */
    @Test
    public void testGetCardIdForDefaultEuicc() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_EUICC));

        int cardId = mTelephonyManager.getCardIdForDefaultEuicc();
        assertTrue("Card ID for default EUICC is not a valid value",
                cardId == TelephonyManager.UNSUPPORTED_CARD_ID
                        || cardId == TelephonyManager.UNINITIALIZED_CARD_ID
                        || cardId >= 0);
    }

    /**
     * Tests that a SecurityException is thrown when trying to access UiccCardsInfo.
     */
    @Test
    public void testGetUiccCardsInfoException() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        try {
            // Requires READ_PRIVILEGED_PHONE_STATE or carrier privileges
            List<UiccCardInfo> infos = mTelephonyManager.getUiccCardsInfo();
            fail("Expected SecurityException. App does not have carrier privileges");
        } catch (SecurityException e) {
        }
    }

    /**
     * Tests that UiccCardsInfo methods don't crash.
     */
    @Test
    public void testGetUiccCardsInfo() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        // The API requires either READ_PRIVILEGED_PHONE_STATE or carrier privileges
        try {
            mTelephonyManager.getUiccCardsInfo();
            fail("Telephony#getUiccCardsInfo should throw SecurityException without "
                    + "READ_PRIVILEGED_PHONE_STATE nor carrier privileges");
        } catch (SecurityException expected) {
        }

        // With READ_PRIVILEGED_PHONE_STATE only, it should work
        List<UiccCardInfo> infos =
                ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getUiccCardsInfo());
        // test that these methods don't crash
        if (infos.size() > 0) {
            UiccCardInfo info = infos.get(0);
            info.getEid();
            info.isRemovable();
            info.isEuicc();
            info.getCardId();
            info.getPorts();
            info.getPhysicalSlotIndex();
            info.isRemovable();
        }

        // With carrier privileges only, it should also work
        try {
            CarrierPrivilegeUtils.withCarrierPrivileges(
                    getContext(),
                    SubscriptionManager.getDefaultSubscriptionId(),
                    () -> mTelephonyManager.getUiccCardsInfo());
        } catch (SecurityException se) {
            fail("TelephonyManager.getUiccCardsInfo should not throw SecurityException with "
                    + "carrier privileges");
        } catch (Exception e) {
            fail("Exception thrown when try to get carrier privileges.");
        }
    }

    private static Context getContext() {
        return InstrumentationRegistry.getContext();
    }

    /**
     * Tests that the device properly reports the contents of NetworkSelectionMode
     */
    @Test
    public void testGetNetworkSelectionMode() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setNetworkSelectionModeAutomatic());
        } catch (Exception e) {
        }

        int networkMode = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getNetworkSelectionMode());

        assertEquals(TelephonyManager.NETWORK_SELECTION_MODE_AUTO, networkMode);
    }

    /**
     * Tests that the device properly sets the network selection mode to automatic.
     * Expects a security exception since the caller does not have carrier privileges.
     */
    @Test
    public void testSetNetworkSelectionModeAutomatic() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        try {
            mTelephonyManager.setNetworkSelectionModeAutomatic();
            fail("Expected SecurityException. App does not have carrier privileges.");
        } catch (SecurityException expected) {
        }
    }

    /**
     * Tests that the device properly asks the radio to connect to the input network and change
     * selection mode to manual.
     * Expects a security exception since the caller does not have carrier privileges.
     */
    @Test
    public void testSetNetworkSelectionModeManual() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        try {
            mTelephonyManager.setNetworkSelectionModeManual(
                    "" /* operatorNumeric */, false /* persistSelection */);
            fail("Expected SecurityException. App does not have carrier privileges.");
        } catch (SecurityException expected) {
        }
    }

    /**
     * Tests that the device properly check whether selection mode was manual.
     */
    @Test
    public void testIsManualNetworkSelectionAllowed() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        if (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_GSM) return;

        assertTrue(ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.isManualNetworkSelectionAllowed()));
    }

    /**
     * Tests that the device properly sets the VoNr
     */
    @Test
    public void testIsVoNrEnabled() {
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            return;
        }

        try {
            int result = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    (tm) -> tm.setVoNrEnabled(true));
            if (result ==  TelephonyManager.ENABLE_VONR_REQUEST_NOT_SUPPORTED) {
                return;
            }
        } catch (Exception e) {
        }

        assertTrue(ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.isVoNrEnabled()));
    }

    /**
     * Tests that a SecurityException is thrown when trying to set VoNR
     */
    @Test
    public void testSetVoNrEnabledException() {
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
            return;
        }
        try {
            mTelephonyManager.setVoNrEnabled(true);
            fail("Expected SecurityException. App does not have carrier privileges.");
        } catch (SecurityException expected) {
        }
    }

    /**
     * Construct a CallAttributes object and test getters.
     */
    @Test
    public void testCallAttributes() {
        CallQuality cq = new CallQuality();
        PreciseCallState pcs = new PreciseCallState();
        CallAttributes ca = new CallAttributes(pcs, TelephonyManager.NETWORK_TYPE_UNKNOWN, cq);
        assertEquals(pcs, ca.getPreciseCallState());
        assertEquals(TelephonyManager.NETWORK_TYPE_UNKNOWN, ca.getNetworkType());
        assertEquals(cq, ca.getCallQuality());
    }

    /**
     * Checks that a zeroed-out default CallQuality object can be created
     */
    @Test
    public void testCallQuality() {
        CallQuality cq = new CallQuality();
        assertEquals(0, cq.getDownlinkCallQualityLevel());
        assertEquals(0, cq.getUplinkCallQualityLevel());
        assertEquals(0, cq.getCallDuration());
        assertEquals(0, cq.getNumRtpPacketsTransmitted());
        assertEquals(0, cq.getNumRtpPacketsReceived());
        assertEquals(0, cq.getNumRtpPacketsTransmittedLost());
        assertEquals(0, cq.getNumRtpPacketsNotReceived());
        assertEquals(0, cq.getAverageRelativeJitter());
        assertEquals(0, cq.getMaxRelativeJitter());
        assertEquals(0, cq.getAverageRoundTripTime());
        assertEquals(0, cq.getCodecType());
        assertEquals(false, cq.isRtpInactivityDetected());
        assertEquals(false, cq.isIncomingSilenceDetectedAtCallSetup());
        assertEquals(false, cq.isOutgoingSilenceDetectedAtCallSetup());
        assertEquals(0, cq.getNumVoiceFrames());
        assertEquals(0, cq.getNumNoDataFrames());
        assertEquals(0, cq.getNumDroppedRtpPackets());
        assertEquals(0, cq.getMinPlayoutDelayMillis());
        assertEquals(0, cq.getMaxPlayoutDelayMillis());
        assertEquals(0, cq.getNumRtpSidPacketsReceived());
        assertEquals(0, cq.getNumRtpDuplicatePackets());
    }

    /**
     * Validate CallQuality Parcel
     */
    @Test
    public void testCallQualityParcel() {
        CallQuality cq = new CallQuality.Builder()
                .setDownlinkCallQualityLevel(CallQuality.CALL_QUALITY_NOT_AVAILABLE)
                .setUplinkCallQualityLevel(CallQuality.CALL_QUALITY_NOT_AVAILABLE)
                .setCallDurationMillis(20000)
                .setNumRtpPacketsTransmitted(550)
                .setNumRtpPacketsReceived(450)
                .setNumRtpPacketsTransmittedLost(4)
                .setNumRtpPacketsNotReceived(6)
                .setAverageRelativeJitter(20)
                .setMaxRelativeJitter(30)
                .setAverageRoundTripTimeMillis(150)
                .setCodecType(0)
                .setRtpInactivityDetected(false)
                .setIncomingSilenceDetectedAtCallSetup(false)
                .setOutgoingSilenceDetectedAtCallSetup(false)
                .setNumVoiceFrames(300)
                .setNumNoDataFrames(300)
                .setNumDroppedRtpPackets(5)
                .setMinPlayoutDelayMillis(500)
                .setMaxPlayoutDelayMillis(1000)
                .setNumRtpSidPacketsReceived(300)
                .setNumRtpDuplicatePackets(0)
                .build();

        Parcel stateParcel = Parcel.obtain();
        cq.writeToParcel(stateParcel, 0);
        stateParcel.setDataPosition(0);

        CallQuality parcelCq = CallQuality.CREATOR.createFromParcel(stateParcel);
        assertThat(cq).isEqualTo(parcelCq);

    }

    // Reference: packages/services/Telephony/ecc/input/eccdata.txt
    private static final Map<String, String> EMERGENCY_NUMBERS_FOR_COUNTRIES = Map.of(
            "au", "000",
            "ca", "911",
            "de", "112",
            "gb", "999",
            "in", "112",
            "jp", "110",
            "sg", "999",
            "tw", "110",
            "us", "911");

    /**
     * Tests TelephonyManager.getEmergencyNumberList.
     *
     * Also enforce country-specific emergency number in CTS.
     */
    @Test
    public void testGetEmergencyNumberList() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CALLING));

        Map<Integer, List<EmergencyNumber>> emergencyNumberList =
                mTelephonyManager.getEmergencyNumberList();

        assertFalse(emergencyNumberList == null);

        checkEmergencyNumberFormat(emergencyNumberList);

        int defaultSubId = mSubscriptionManager.getDefaultSubscriptionId();
        for (Map.Entry<String, String> entry : EMERGENCY_NUMBERS_FOR_COUNTRIES.entrySet()) {
            if (mTelephonyManager.getNetworkCountryIso().equals(entry.getKey())) {
                assertTrue(checkIfEmergencyNumberListHasSpecificAddress(
                        emergencyNumberList.get(defaultSubId), entry.getValue()));
            }
        }
    }

    /**
     * Tests TelephonyManager.getEmergencyNumberList(@EmergencyServiceCategories int categories).
     *
     */
    @Test
    public void testGetEmergencyNumberListForCategories() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CALLING));

        Map<Integer, List<EmergencyNumber>> emergencyNumberList =
                mTelephonyManager.getEmergencyNumberList(
                        EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE);

        assertFalse(emergencyNumberList == null);

        checkEmergencyNumberFormat(emergencyNumberList);

        int defaultSubId = mSubscriptionManager.getDefaultSubscriptionId();
        final String country_us = "us";
        final String country_us_police_number = "911";
        if (mTelephonyManager.getNetworkCountryIso().equals(country_us)) {
            assertTrue(checkIfEmergencyNumberListHasSpecificAddress(
                    emergencyNumberList.get(defaultSubId), country_us_police_number));
        }
        for (EmergencyNumber num : emergencyNumberList.get(defaultSubId)) {
            assertTrue(num.isInEmergencyServiceCategories(
                    EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE));
        }
    }

    /**
     * Tests TelephonyManager.isEmergencyNumber.
     *
     * Also enforce country-specific emergency number in CTS.
     */
    @Test
    public void testIsEmergencyNumber() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CALLING));

        for (Map.Entry<String, String> entry : EMERGENCY_NUMBERS_FOR_COUNTRIES.entrySet()) {
            if (mTelephonyManager.getNetworkCountryIso().equals(entry.getKey())) {
                assertTrue(mTelephonyManager.isEmergencyNumber(entry.getValue()));
            }
        }
    }

    /**
     * Tests TelephonyManager.isPotentialEmergencyNumber.
     */
    @Test
    public void testIsPotentialEmergencyNumber() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CALLING));
        //NOTE: TelephonyManager#isPotentialEmergencyNumber is a hidden
        //and now deprecated API (from Android-U). This test is updated to make sure we never
        //do a "potential" match, but always use "exact" matching since it can cause issues
        //in countries where regular numbers can end up being treated as emergency numbers.
        String countryIso = mTelephonyManager.getNetworkCountryIso();
        String potentialEmergencyAddress = "91112345";
        assertFalse(ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.isPotentialEmergencyNumber(potentialEmergencyAddress)));
    }

    /**
     * Tests TelephonyManager.setCallComposerStatus and TelephonyManager.getCallComposerStatus.
     */
    @Test
    public void testSetGetCallComposerStatus() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CALLING));

        if (hasFeature(PackageManager.FEATURE_TELEPHONY_IMS)) {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    tm -> tm.setCallComposerStatus(TelephonyManager.CALL_COMPOSER_STATUS_OFF));
            int status = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    tm -> tm.getCallComposerStatus());
            assertThat(status).isEqualTo(TelephonyManager.CALL_COMPOSER_STATUS_OFF);

            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    tm -> tm.setCallComposerStatus(TelephonyManager.CALL_COMPOSER_STATUS_ON));
            status = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    tm -> tm.getCallComposerStatus());
            assertThat(status).isEqualTo(TelephonyManager.CALL_COMPOSER_STATUS_ON);
        } else {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    tm -> tm.setCallComposerStatus(TelephonyManager.CALL_COMPOSER_STATUS_OFF));
            int status = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    tm -> tm.getCallComposerStatus());
            assertThat(status).isEqualTo(TelephonyManager.CALL_COMPOSER_STATUS_OFF);

            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    tm -> tm.setCallComposerStatus(TelephonyManager.CALL_COMPOSER_STATUS_ON));
            status = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    tm -> tm.getCallComposerStatus());
            assertThat(status).isEqualTo(TelephonyManager.CALL_COMPOSER_STATUS_OFF);
        }
    }

    /**
     * Tests {@link TelephonyManager#getSupportedRadioAccessFamily()}
     */
    @Test
    public void testGetRadioAccessFamily() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        long raf = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getSupportedRadioAccessFamily());
        assertThat(raf).isNotEqualTo(TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN);
    }

    private static void assertSetOpportunisticSubSuccess(int value) {
        assertThat(value).isEqualTo(TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS);
    }

    private static void assertSetOpportunisticNoOpportunisticSub(int value) {
        assertThat(value).isEqualTo(
                TelephonyManager.SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE);
    }

    /**
     * Tests {@link TelephonyManager#setPreferredOpportunisticDataSubscription} and
     * {@link TelephonyManager#getPreferredOpportunisticDataSubscription}
     */
    @Test
    public void testPreferredOpportunisticDataSubscription() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        int randomSubId = 1;
        int activeSubscriptionInfoCount = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mSubscriptionManager, (tm) -> tm.getActiveSubscriptionInfoCount());
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            return;
        }
        if (mTelephonyManager.getPhoneCount() == 1) {
            return;
        }
        if (mTelephonyManager.getPhoneCount() == 2 && activeSubscriptionInfoCount != 2) {
            return;
        }
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                (tm) -> tm.setPreferredOpportunisticDataSubscription(
                        SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false,
                        null, null));
        // wait for the data change to take effect
        waitForMs(500);
        int subId =
                ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                        (tm) -> tm.getPreferredOpportunisticDataSubscription());
        assertThat(subId).isEqualTo(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
        List<SubscriptionInfo> subscriptionInfoList =
                ShellIdentityUtils.invokeMethodWithShellPermissions(mSubscriptionManager,
                        (tm) -> tm.getOpportunisticSubscriptions());
        Consumer<Integer> callbackSuccess = TelephonyManagerTest::assertSetOpportunisticSubSuccess;
        Consumer<Integer> callbackNoOpSub =
                TelephonyManagerTest::assertSetOpportunisticNoOpportunisticSub;
        if (subscriptionInfoList == null || subscriptionInfoList.size() == 0) {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setPreferredOpportunisticDataSubscription(randomSubId, false,
                            AsyncTask.SERIAL_EXECUTOR, callbackNoOpSub));
            // wait for the data change to take effect
            waitForMs(500);
            subId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    (tm) -> tm.getPreferredOpportunisticDataSubscription());
            assertThat(subId).isEqualTo(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
        } else {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setPreferredOpportunisticDataSubscription(
                            subscriptionInfoList.get(0).getSubscriptionId(), false,
                            AsyncTask.SERIAL_EXECUTOR, callbackSuccess));
            // wait for the data change to take effect
            waitForMs(500);
            subId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                    (tm) -> tm.getPreferredOpportunisticDataSubscription());
            assertThat(subId).isEqualTo(subscriptionInfoList.get(0).getSubscriptionId());
        }

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                (tm) -> tm.setPreferredOpportunisticDataSubscription(
                        SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false,
                        AsyncTask.SERIAL_EXECUTOR, callbackSuccess));
        // wait for the data change to take effect
        waitForMs(500);
        subId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.getPreferredOpportunisticDataSubscription());
        assertThat(subId).isEqualTo(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
    }

    private static void assertUpdateAvailableNetworkSuccess(int value) {
        assertThat(value).isEqualTo(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS);
    }

    private static void assertUpdateAvailableNetworkNoOpportunisticSub(int value) {
        assertThat(value).isEqualTo(
                TelephonyManager.UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE);
    }

    private static boolean checkIfEmergencyNumberListHasSpecificAddress(
            List<EmergencyNumber> emergencyNumberList, String address) {
        for (EmergencyNumber emergencyNumber : emergencyNumberList) {
            if (address.equals(emergencyNumber.getNumber())) {
                return true;
            }
        }
        return false;
    }

    private static void checkEmergencyNumberFormat(
            Map<Integer, List<EmergencyNumber>> emergencyNumberLists) {
        for (List<EmergencyNumber> emergencyNumberList : emergencyNumberLists.values()) {
            for (EmergencyNumber emergencyNumber : emergencyNumberList) {

                // Validate Emergency number address
                assertTrue(validateEmergencyNumberAddress(emergencyNumber.getNumber()));

                // Validate Emergency number country Iso
                assertTrue(validateEmergencyNumberCountryIso(emergencyNumber.getCountryIso()));

                // Validate Emergency number mnc
                assertTrue(validateEmergencyNumberMnc(emergencyNumber.getMnc()));

                // Validate Emergency service category list
                assertTrue(validateEmergencyServiceCategoryList(
                        emergencyNumber.getEmergencyServiceCategories()));

                // Validate Emergency number source list
                assertTrue(validateEmergencyNumberSourceList(
                        emergencyNumber.getEmergencyNumberSources()));

                // Validate Emergency URN list
                // (just verify it is not null, because the support of this field is optional)
                assertTrue(emergencyNumber.getEmergencyUrns() != null);

                // Validat Emergency call routing
                assertTrue(validateEmergencyCallRouting(
                        emergencyNumber.getEmergencyCallRouting()));

                // Valid the emergency number should be at least in a valid source.
                assertTrue(validateEmergencyNumberFromAnySource(emergencyNumber));

                // Valid the emergency number should be at least in a valid category.
                assertTrue(validateEmergencyNumberInAnyCategory(emergencyNumber));
            }

            // Validate compareTo
            assertTrue(validateEmergencyNumberCompareTo(emergencyNumberList));
        }
    }

    /**
     * Tests {@link TelephonyManager#updateAvailableNetworks}
     */
    @Test
    public void testUpdateAvailableNetworks() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        int randomSubId = 1;
        int activeSubscriptionInfoCount = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mSubscriptionManager, (tm) -> tm.getActiveSubscriptionInfoCount());
        boolean isOpportunisticNetworkEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isOpportunisticNetworkEnabled());

        if (!isOpportunisticNetworkEnabled) {
            return;
        }
        if (mTelephonyManager.getPhoneCount() == 1) {
            return;
        }
        if (mTelephonyManager.getPhoneCount() == 2 && activeSubscriptionInfoCount != 2) {
            return;
        }

        List<SubscriptionInfo> subscriptionInfoList =
                ShellIdentityUtils.invokeMethodWithShellPermissions(mSubscriptionManager,
                        (tm) -> tm.getOpportunisticSubscriptions());
        List<String> mccMncs = new ArrayList<String>();
        List<Integer> bands = new ArrayList<Integer>();
        List<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<AvailableNetworkInfo>();
        Consumer<Integer> callbackSuccess =
                TelephonyManagerTest::assertUpdateAvailableNetworkSuccess;
        Consumer<Integer> callbackNoOpSub =
                TelephonyManagerTest::assertUpdateAvailableNetworkNoOpportunisticSub;
        if (subscriptionInfoList == null || subscriptionInfoList.size() == 0
                || !mSubscriptionManager.isActiveSubscriptionId(
                subscriptionInfoList.get(0).getSubscriptionId())) {
            AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(randomSubId,
                    AvailableNetworkInfo.PRIORITY_HIGH, mccMncs, bands);
            availableNetworkInfos.add(availableNetworkInfo);
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.updateAvailableNetworks(availableNetworkInfos,
                            AsyncTask.SERIAL_EXECUTOR, callbackNoOpSub));
            // wait for the data change to take effect
            waitForMs(500);
            // clear all the operations at the end of test.
            availableNetworkInfos.clear();
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.updateAvailableNetworks(availableNetworkInfos,
                            AsyncTask.SERIAL_EXECUTOR, callbackNoOpSub));
        } else {
            AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(
                    subscriptionInfoList.get(0).getSubscriptionId(),
                    AvailableNetworkInfo.PRIORITY_HIGH, mccMncs, bands);
            availableNetworkInfos.add(availableNetworkInfo);
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.updateAvailableNetworks(availableNetworkInfos,
                            AsyncTask.SERIAL_EXECUTOR, callbackSuccess));
            // wait for the data change to take effect
            waitForMs(500);
            // clear all the operations at the end of test.
            availableNetworkInfos.clear();
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.updateAvailableNetworks(availableNetworkInfos,
                            AsyncTask.SERIAL_EXECUTOR, callbackSuccess));
        }
    }

    @Test
    public void testSwitchMultiSimConfig() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        try {
            mTelephonyManager.switchMultiSimConfig(mTelephonyManager.getActiveModemCount());
            fail("TelephonyManager#switchMultiSimConfig should require the MODIFY_PHONE_STATE"
                    + " permission to access.");
        } catch (SecurityException e) {
            // expected
        }
        try {
            // This should result in no-op.
            ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.switchMultiSimConfig(mTelephonyManager.getActiveModemCount()),
                    SecurityException.class, android.Manifest.permission.MODIFY_PHONE_STATE);
        } catch (SecurityException e) {
            fail("TelephonyManager#switchMultiSimConfig should require MODIFY_PHONE_STATE"
                    + "permission to access.");
        }
    }

    @Test
    public void testIccOpenLogicalChannelBySlot() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        // just verify no crash
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.iccOpenLogicalChannelBySlot(0, null, 0));
        } catch (IllegalArgumentException e) {
            // IllegalArgumentException is okay, just not SecurityException
        }
    }

    @Test
    public void testIccOpenLogicalChannelBySlotAndPort() {
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            return;
        }
        // just verify no crash
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.iccOpenLogicalChannelByPort(0, 0, null, 0));
        } catch (SecurityException e) {
            // IllegalArgumentException is okay, just not SecurityException
            fail("iccCloseLogicalChannelByPort: SecurityException not expected");
        }
    }

    @Test
    public void testIccCloseLogicalChannelBySlot() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        // just verify no crash
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.iccCloseLogicalChannelBySlot(0, 0));
        } catch (IllegalArgumentException e) {
            // IllegalArgumentException is okay, just not SecurityException
        }
    }
    @Test
    public void testIccCloseLogicalChannelBySlotAndPort() {
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            return;
        }
        int slotIndex = getValidSlotIndexAndPort().getKey();
        int portIndex = getValidSlotIndexAndPort().getValue();
        // just verify no crash
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager, (tm) -> tm.iccCloseLogicalChannelByPort(
                            slotIndex, portIndex, 0));
        } catch (IllegalArgumentException | IllegalStateException e) {
            // IllegalArgumentException and IllegalStateException is okay, just not
            // SecurityException
        } catch (SecurityException e) {
            // IllegalArgumentException is okay, just not SecurityException
            fail("iccCloseLogicalChannelByPort: SecurityException not expected");
        }
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager, (tm) -> tm.iccCloseLogicalChannelByPort(slotIndex, -1, 0));
            fail("Expected IllegalArgumentException, invalid PortIndex");
        } catch (IllegalArgumentException e) {
            // IllegalArgumentException is expected
        }
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager, (tm) -> tm.iccCloseLogicalChannelByPort(
                            slotIndex, portIndex, -1));
            fail("Expected IllegalArgumentException, invalid channel");
        } catch (IllegalArgumentException e) {
            // IllegalArgumentException is expected
        }
    }

    @Test
    public void testIccTransmitApduLogicalChannelBySlot() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        int slotIndex = getValidSlotIndexAndPort().getKey();
        String result = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.iccTransmitApduLogicalChannelBySlot(
                        slotIndex,
                        0 /* channel */,
                        0 /* cla */,
                        0 /* instruction */,
                        0 /* p1 */,
                        0 /* p2 */,
                        0 /* p3 */,
                        null /* data */));
        assertTrue(TextUtils.isEmpty(result));
    }

    @Test
    public void testIccTransmitApduLogicalChannelBySlotAndPort() {
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            return;
        }
        int slotIndex = getValidSlotIndexAndPort().getKey();
        int portIndex = getValidSlotIndexAndPort().getValue();
        try {
            String result = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.iccTransmitApduLogicalChannelByPort(
                            slotIndex,
                            portIndex /* portIndex */,
                            0 /* channel */,
                            0 /* cla */,
                            0 /* instruction */,
                            0 /* p1 */,
                            0 /* p2 */,
                            0 /* p3 */,
                            null /* data */));
            assertTrue(TextUtils.isEmpty(result));
        } catch (SecurityException e) {
            // IllegalArgumentException is okay, just not SecurityException
            fail("iccTransmitApduLogicalChannelByPort: SecurityException not expected");
        }
    }
    @Test
    public void testIccTransmitApduBasicChannelBySlot() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        // just verify no crash
        int slotIndex = getValidSlotIndexAndPort().getKey();
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.iccTransmitApduBasicChannelBySlot(
                            slotIndex,
                            0 /* cla */,
                            0 /* instruction */,
                            0 /* p1 */,
                            0 /* p2 */,
                            0 /* p3 */,
                            null /* data */));
        } catch (IllegalArgumentException e ) {
            // IllegalArgumentException is okay, just not SecurityException
        }
    }

    @Test
    public void testIccTransmitApduBasicChannelBySlotAndPort() {
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            return;
        }
        // just verify no crash
        int slotIndex = getValidSlotIndexAndPort().getKey();
        int portIndex = getValidSlotIndexAndPort().getValue();
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.iccTransmitApduBasicChannelByPort(
                            slotIndex,
                            portIndex /*portIndex */,
                            0 /* cla */,
                            0 /* instruction */,
                            0 /* p1 */,
                            0 /* p2 */,
                            0 /* p3 */,
                            null /* data */));
        } catch (SecurityException e) {
            // IllegalArgumentException is okay, just not SecurityException
            fail("iccTransmitApduBasicChannelByPort: SecurityException not expected");
        }
    }

    @Test
    public void testIsIccLockEnabled() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        // verify SecurityException
        try {
            mTelephonyManager.isIccLockEnabled();
            fail("testIsIccLockEnabled: Expected SecurityException on isIccLockEnabled");
        } catch (SecurityException se) {
            // expected
        }

        // test with permission
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.isIccLockEnabled());
        } catch (SecurityException se) {
            fail("testIsIccLockEnabled: SecurityException not expected");
        }
    }

    @Test
    public void testIsDataEnabledForApn() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        // verify SecurityException
        try {
            mTelephonyManager.isDataEnabledForApn(ApnSetting.TYPE_MMS);
            fail("testIsDataEnabledForApn: Expected SecurityException on isDataEnabledForApn");
        } catch (SecurityException se) {
            // expected
        }

        // test with permission
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.isDataEnabledForApn(ApnSetting.TYPE_MMS));
        } catch (SecurityException se) {
            fail("testIsDataEnabledForApn: SecurityException not expected");
        }
    }

    @Test
    public void testIsTetheringApnRequired() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        // verify SecurityException
        try {
            mTelephonyManager.isTetheringApnRequired();
            fail("testIsTetheringApnRequired: Expected SecurityException on "
                    + "isTetheringApnRequired");
        } catch (SecurityException se) {
            // expected
        }

        // test with permission
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.isTetheringApnRequired());
        } catch (SecurityException se) {
            fail("testIsIccLockEnabled: SecurityException not expected");
        }
    }

    @Test
    public void testGetCarrierInfoForImsiEncryption() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        // test without permission: verify SecurityException
        try {
            mTelephonyManager.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_EPDG);
            fail("testGetCarrierInfoForImsiEncryption: "
                    + "SecurityException expected on getCarrierInfoForImsiEncryption");
        } catch (SecurityException se) {
            // expected
        }
        try {
            mTelephonyManager.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN);
            fail("testGetCarrierInfoForImsiEncryption: "
                    + "SecurityException expected on getCarrierInfoForImsiEncryption");
        } catch (SecurityException se) {
            // expected
        }
        // test with permission
        PublicKey epdgKey = null;
        PublicKey wlanKey = null;
        try {
            PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mTestSub);

            assertNotNull("CarrierConfigManager#getConfigForSubId() returned null",
                    carrierConfig);
            assertFalse("CarrierConfigManager#getConfigForSubId() returned empty bundle",
                    carrierConfig.isEmpty());

            // purge the certs in carrierConfigs first
            carrierConfig.putInt(
                    CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT, 3);
            carrierConfig.putString(
                    CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING, BAD_IMSI_CERT_URL);
            carrierConfig.putString(
                    CarrierConfigManager.IMSI_CARRIER_PUBLIC_KEY_EPDG_STRING,
                    IMSI_CERT_STRING_EPDG);
            carrierConfig.putString(
                    CarrierConfigManager.IMSI_CARRIER_PUBLIC_KEY_WLAN_STRING,
                    IMSI_CERT_STRING_WLAN);
            overrideCarrierConfig(carrierConfig);
        } catch (Exception e) {
            fail("Could not override carrier config. e=" + e.toString());
        }

        try {
            // It appears that the two certs actually have the same public key. Ideally we would
            // want these to be different for testing, but it's challenging to create a valid
            // certificate string for testing and these are the only two examples available
            InputStream inStream = new ByteArrayInputStream(IMSI_CERT_STRING_WLAN.getBytes());
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
            wlanKey = cert.getPublicKey();

            inStream = new ByteArrayInputStream(IMSI_CERT_STRING_EPDG.getBytes());
            cert = (X509Certificate) cf.generateCertificate(inStream);
            epdgKey = cert.getPublicKey();
        } catch (CertificateException e) {
            fail("Could not create certs. e=" + e.toString());
        }

        try {
            ImsiEncryptionInfo info = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager,
                    (tm) -> {
                        return tm.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_EPDG);
                    });
            assertNotNull("Encryption info returned null", info);
            assertEquals(epdgKey, info.getPublicKey());
            assertEquals(TelephonyManager.KEY_TYPE_EPDG, info.getKeyType());
        } catch (SecurityException se) {
            fail("testGetCarrierInfoForImsiEncryption: SecurityException not expected");
        } catch (IllegalArgumentException iae) {
            // IllegalArgumentException is okay, just not SecurityException
        }
        try {
            ImsiEncryptionInfo info = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager,
                    (tm) -> {
                        return tm.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN);
                    });
            assertNotNull("Encryption info returned null", info);
            assertEquals(wlanKey, info.getPublicKey());
            assertEquals(TelephonyManager.KEY_TYPE_WLAN, info.getKeyType());
        } catch (SecurityException se) {
            fail("testGetCarrierInfoForImsiEncryption: SecurityException not expected");
        } catch (IllegalArgumentException iae) {
            // IllegalArgumentException is okay, just not SecurityException
        }
    }

    @Test
    public void testResetCarrierKeysForImsiEncryption() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        // test without permission: verify SecurityException
        try {
            mTelephonyManager.resetCarrierKeysForImsiEncryption();
            fail("testResetCarrierKeysForImsiEncryption: SecurityException expected");
        } catch (SecurityException se) {
            // expected
        }
        // test with permission
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.resetCarrierKeysForImsiEncryption());
        } catch (SecurityException se) {
            fail("testResetCarrierKeysForImsiEncryption: SecurityException not expected");
        }
    }

    @Test
    public void testIsInEmergencySmsMode() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING));

        // test without permission: verify SecurityException
        try {
            mTelephonyManager.isInEmergencySmsMode();
            fail("testIsInEmergencySmsMode: SecurityException expected");
        } catch (SecurityException se) {
            // expected
        }
        // test with permission
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.isInEmergencySmsMode());
        } catch (SecurityException se) {
            fail("testIsInEmergencySmsMode: SecurityException not expected");
        }
    }

    @Test
    public void testGetSubscriptionId() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        TelephonyManager tm = mTelephonyManager.createForSubscriptionId(1);
        int subId = tm.getSubscriptionId();
        assertEquals(1, subId);
    }

    @Test
    public void testSetAllowedNetworkTypes() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // test without permission: verify SecurityException
        long allowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
        try {
            mTelephonyManager.setAllowedNetworkTypes(allowedNetworkTypes);
            fail("testSetAllowedNetworkTypes: SecurityException expected");
        } catch (SecurityException se) {
            // expected
        }

        // test with permission
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setAllowedNetworkTypes(allowedNetworkTypes));

            long deviceAllowedNetworkTypes = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> {
                        return tm.getAllowedNetworkTypes();
                    }
            );
            assertEquals(allowedNetworkTypes, deviceAllowedNetworkTypes);
        } catch (SecurityException se) {
            fail("testSetAllowedNetworkTypes: SecurityException not expected");
        }
    }

    @Test
    public void testDisAllowedNetworkTypes() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        long allowedNetworkTypes = ~TelephonyManager.NETWORK_TYPE_BITMASK_NR;
        long networkTypeBitmask = TelephonyManager.NETWORK_TYPE_BITMASK_LTE
                | TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;

        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setAllowedNetworkTypesForReason(
                            TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER,
                            allowedNetworkTypes));

            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setAllowedNetworkTypesForReason(
                            TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
                            networkTypeBitmask));

            long modemNetworkTypeBitmask = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> {
                        return tm.getAllowedNetworkTypesBitmask();
                    }
            );
            long radioAccessFamily = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> {
                        return tm.getSupportedRadioAccessFamily();
                    }
            );

            // RadioAccessFamily won't include all bits of RAFs group, so transfer to preferred
            // network type instead of using bitmask directly
            int modemPreferredNetworkType = RadioAccessFamily.getNetworkTypeFromRaf(
                    (int) modemNetworkTypeBitmask);
            int preferredNetworkType = RadioAccessFamily.getNetworkTypeFromRaf(
                    (int) (networkTypeBitmask & allowedNetworkTypes & radioAccessFamily));
            assertEquals(preferredNetworkType, modemPreferredNetworkType);
        } catch (SecurityException se) {
            fail("testDisAllowedNetworkTypes: SecurityException not expected");
        }
    }

    @Test
    public void testSetAllowedNetworkTypesForReason() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // test without permission: verify SecurityException
        long allowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
        try {
            mIsAllowedNetworkTypeChanged = true;
            mTelephonyManager.setAllowedNetworkTypesForReason(
                    TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER, allowedNetworkTypes);
            fail("testSetAllowedNetworkTypesForReason: SecurityException expected");
        } catch (SecurityException se) {
            // expected
        }

        // test with permission
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setAllowedNetworkTypesForReason(
                            TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER,
                            allowedNetworkTypes));

            long deviceAllowedNetworkTypes = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> {
                        return tm.getAllowedNetworkTypesForReason(
                                TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER);
                    }
            );
            assertEquals(allowedNetworkTypes, deviceAllowedNetworkTypes);
        } catch (SecurityException se) {
            fail("testSetAllowedNetworkTypes: SecurityException not expected");
        }
    }

    @Test
    public void testSetAllowedNetworkTypesForReason_carrierPrivileges() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
        try {
            CarrierPrivilegeUtils.withCarrierPrivileges(getContext(),
                    SubscriptionManager.getDefaultSubscriptionId(),
                    () -> {
                        mTelephonyManager.setAllowedNetworkTypesForReason(
                                TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER,
                                TelephonyManager.NETWORK_TYPE_BITMASK_LTE);
                    }
            );
        } catch (SecurityException se) {
            fail("setAllowedNetworkTypesForReason: SecurityException not expected: "
                    + se.getMessage());
        } catch (Exception e) {
            // withCarrierPrivileges declares a checked Exception, so we must handle it. We don't
            // expect any exceptions so this is still a failure.
            Log.e(TAG, "Exception not expected. failing test.", e);
            fail("CarrierPrivilegeUtils.withCarrierPrivileges: Exception not expected. "
                    + "See error log.");
        }

        assertThrows(SecurityException.class, () -> {
            CarrierPrivilegeUtils.withCarrierPrivileges(getContext(),
                    SubscriptionManager.getDefaultSubscriptionId(),
                    () -> {
                        mTelephonyManager.setAllowedNetworkTypesForReason(
                                TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G,
                                TelephonyManager.NETWORK_TYPE_BITMASK_LTE);
                    }
            );
        });
    }

    @Test
    public void testSetAllowedNetworkTypesForReason_moreReason() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // test without permission: verify SecurityException
        long allowedNetworkTypes1 = TelephonyManager.NETWORK_TYPE_BITMASK_LTE
                | TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
        long allowedNetworkTypes2 = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
        long allowedNetworkTypes3 = TelephonyManager.NETWORK_TYPE_BITMASK_LTE
                | TelephonyManager.NETWORK_TYPE_BITMASK_HSPA
                | TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
        long allowedNetworkTypes4 = TelephonyManager.NETWORK_TYPE_BITMASK_LTE
                | TelephonyManager.NETWORK_TYPE_BITMASK_HSPA;

        try {
            mIsAllowedNetworkTypeChanged = true;
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setAllowedNetworkTypesForReason(
                            TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER,
                            allowedNetworkTypes1),
                    "android.permission.MODIFY_PHONE_STATE");

            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setAllowedNetworkTypesForReason(
                            TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
                            allowedNetworkTypes2),
                    "android.permission.MODIFY_PHONE_STATE");
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setAllowedNetworkTypesForReason(
                            TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER,
                            allowedNetworkTypes3),
                    "android.permission.MODIFY_PHONE_STATE");
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setAllowedNetworkTypesForReason(
                            TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G,
                            allowedNetworkTypes4),
                    "android.permission.MODIFY_PHONE_STATE");
            long deviceAllowedNetworkTypes1 = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager,
                    (tm) -> {
                        return tm.getAllowedNetworkTypesForReason(
                                TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER);
                    },
                    "android.permission.READ_PRIVILEGED_PHONE_STATE"
            );
            long deviceAllowedNetworkTypes2 = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager,
                    (tm) -> {
                        return tm.getAllowedNetworkTypesForReason(
                                TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
                    },
                    "android.permission.READ_PRIVILEGED_PHONE_STATE"
            );
            long deviceAllowedNetworkTypes3 = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> {
                        return tm.getAllowedNetworkTypesForReason(
                                TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER);
                    },
                    "android.permission.READ_PRIVILEGED_PHONE_STATE"
            );
            long deviceAllowedNetworkTypes4 = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> {
                        return tm.getAllowedNetworkTypesForReason(
                                TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
                    },
                    "android.permission.READ_PRIVILEGED_PHONE_STATE"
            );
            assertEquals(allowedNetworkTypes1, deviceAllowedNetworkTypes1);
            assertEquals(allowedNetworkTypes2, deviceAllowedNetworkTypes2);
            assertEquals(allowedNetworkTypes3, deviceAllowedNetworkTypes3);
            assertEquals(allowedNetworkTypes4, deviceAllowedNetworkTypes4);
        } catch (SecurityException se) {
            fail("testSetAllowedNetworkTypes: SecurityException not expected");
        }
    }

    @Test
    public void testIsApplicationOnUicc() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        // Expect a security exception without permission.
        try {
            mTelephonyManager.isApplicationOnUicc(TelephonyManager.APPTYPE_SIM);
            fail("Expected security exception");
        } catch (SecurityException se1) {
            // Expected
        }

        InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .adoptShellPermissionIdentity(
                        android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
        try {
            mTelephonyManager.isApplicationOnUicc(TelephonyManager.APPTYPE_SIM);
        } catch (SecurityException se) {
            fail("Caller with READ_PRIVILEGED_PHONE_STATE should be able to call API");
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .dropShellPermissionIdentity();
        }
    }

    @Test
    @ApiTest(apis = {"android.telephony.TelephonyManager#requestModemActivityInfo"})
    public void testRequestModemActivityInfo() throws Exception {
        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .adoptShellPermissionIdentity(android.Manifest.permission.MODIFY_PHONE_STATE);
        try {
            // Get one instance of activity info and make sure it's valid
            CompletableFuture<ModemActivityInfo> future1 = new CompletableFuture<>();
            mTelephonyManager.requestModemActivityInfo(getContext().getMainExecutor(),
                    future1::complete);
            ModemActivityInfo activityInfo1 = future1.get(TOLERANCE, TimeUnit.MILLISECONDS);
            assertNotNull(activityInfo1);
            assertTrue("first activity info is" + activityInfo1, activityInfo1.isValid());

            // Wait a bit, then get another instance to make sure that some info has accumulated
            waitForMs(5000);
            CompletableFuture<ModemActivityInfo> future2 = new CompletableFuture<>();
            mTelephonyManager.requestModemActivityInfo(getContext().getMainExecutor(),
                    future2::complete);
            ModemActivityInfo activityInfo2 = future2.get(TOLERANCE, TimeUnit.MILLISECONDS);
            assertNotNull(activityInfo2);
            assertTrue("second activity info is" + activityInfo2, activityInfo2.isValid());

            ModemActivityInfo diff = activityInfo1.getDelta(activityInfo2);
            assertNotNull(diff);
            assertTrue("two activityInfo are identical", !activityInfo1.equals(activityInfo2));
            assertTrue("diff is" + diff, diff.isValid() || diff.isEmpty());
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .dropShellPermissionIdentity();
        }
    }

    @Test
    public void testModemActivityInfoException() {
        TelephonyManager.ModemActivityInfoException exception =
                new TelephonyManager.ModemActivityInfoException(
                        TelephonyManager.ModemActivityInfoException.ERROR_PHONE_NOT_AVAILABLE);
        assertEquals(TelephonyManager.ModemActivityInfoException.ERROR_PHONE_NOT_AVAILABLE,
                exception.getErrorCode());
    }

    @Test
    public void testGetSupportedModemCount() {
        int supportedModemCount = mTelephonyManager.getSupportedModemCount();
        int activeModemCount = mTelephonyManager.getActiveModemCount();
        assertTrue(activeModemCount >= 0);
        assertTrue(supportedModemCount >= activeModemCount);
    }

    @Test
    public void testGetAllNetworkTypes() {
        Set<Integer> expectedNetworkTypes = new HashSet<>(Arrays.asList(
                TelephonyManager.NETWORK_TYPE_GPRS,
                TelephonyManager.NETWORK_TYPE_EDGE,
                TelephonyManager.NETWORK_TYPE_UMTS,
                TelephonyManager.NETWORK_TYPE_CDMA,
                TelephonyManager.NETWORK_TYPE_EVDO_0,
                TelephonyManager.NETWORK_TYPE_EVDO_A,
                TelephonyManager.NETWORK_TYPE_1xRTT,
                TelephonyManager.NETWORK_TYPE_HSDPA,
                TelephonyManager.NETWORK_TYPE_HSUPA,
                TelephonyManager.NETWORK_TYPE_HSPA,
                TelephonyManager.NETWORK_TYPE_IDEN,
                TelephonyManager.NETWORK_TYPE_EVDO_B,
                TelephonyManager.NETWORK_TYPE_LTE,
                TelephonyManager.NETWORK_TYPE_EHRPD,
                TelephonyManager.NETWORK_TYPE_HSPAP,
                TelephonyManager.NETWORK_TYPE_GSM,
                TelephonyManager.NETWORK_TYPE_TD_SCDMA,
                TelephonyManager.NETWORK_TYPE_IWLAN,
                TelephonyManager.NETWORK_TYPE_LTE_CA,
                TelephonyManager.NETWORK_TYPE_NR
        ));

        Set<Integer> actualNetworkTypes = IntStream.of(TelephonyManager.getAllNetworkTypes())
                .boxed().collect(Collectors.toSet());
        assertTrue(expectedNetworkTypes.containsAll(actualNetworkTypes));
        assertTrue(actualNetworkTypes.containsAll(expectedNetworkTypes));
    }

    @Test
    public void testIsModemEnabledForSlot() {
        int activeModemCount = mTelephonyManager.getActiveModemCount();
        for (int i = 0; i < activeModemCount; i++) {
            // Call isModemEnabledForSlot for each slot and verify no crash.
            mTelephonyManager.isModemEnabledForSlot(i);
        }
    }

    @Test
    public void testOpportunisticNetworkState() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
                && !mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH));

        boolean isEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                tm -> tm.isOpportunisticNetworkEnabled());
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setOpportunisticNetworkState(true));
        assertTrue(ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                tm -> tm.isOpportunisticNetworkEnabled()));
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setOpportunisticNetworkState(false));
        assertFalse(ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                tm -> tm.isOpportunisticNetworkEnabled()));
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setOpportunisticNetworkState(isEnabled));
    }

    @Test
    public void testGetSimApplicationState() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        int simApplicationState = mTelephonyManager.getSimApplicationState();
        assertTrue(Arrays.asList(TelephonyManager.SIM_STATE_UNKNOWN,
                TelephonyManager.SIM_STATE_PIN_REQUIRED,
                TelephonyManager.SIM_STATE_PUK_REQUIRED,
                TelephonyManager.SIM_STATE_NETWORK_LOCKED,
                TelephonyManager.SIM_STATE_NOT_READY,
                TelephonyManager.SIM_STATE_PERM_DISABLED,
                TelephonyManager.SIM_STATE_LOADED).contains(simApplicationState));

        for (int i = 0; i <= mTelephonyManager.getPhoneCount(); i++) {
            final int slotId = i;
            simApplicationState = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.getSimApplicationState(slotId));
            assertTrue(Arrays.asList(TelephonyManager.SIM_STATE_UNKNOWN,
                    TelephonyManager.SIM_STATE_PIN_REQUIRED,
                    TelephonyManager.SIM_STATE_PUK_REQUIRED,
                    TelephonyManager.SIM_STATE_NETWORK_LOCKED,
                    TelephonyManager.SIM_STATE_NOT_READY,
                    TelephonyManager.SIM_STATE_PERM_DISABLED,
                    TelephonyManager.SIM_STATE_LOADED).contains(simApplicationState));
        }
    }

    @Test
    public void testGetSimApplicationStateWithPhysicalSlotIndexAndPortIndex() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        try {
            List<UiccCardInfo> cardInfoList =
                    ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                            (tm) -> tm.getUiccCardsInfo());
            for (UiccCardInfo cardInfo : cardInfoList) {
                int physicalSlotIndex = cardInfo.getPhysicalSlotIndex();
                List<UiccPortInfo> portInfoList = (List<UiccPortInfo>) cardInfo.getPorts();
                for (UiccPortInfo uiccPortInfo : portInfoList) {
                    int portIndex = uiccPortInfo.getPortIndex();
                    int simApplicationState =
                            ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                                    (tm) -> tm.getSimApplicationState(physicalSlotIndex,
                                            portIndex));
                    assertTrue(Arrays.asList(TelephonyManager.SIM_STATE_UNKNOWN,
                            TelephonyManager.SIM_STATE_PIN_REQUIRED,
                            TelephonyManager.SIM_STATE_PUK_REQUIRED,
                            TelephonyManager.SIM_STATE_NETWORK_LOCKED,
                            TelephonyManager.SIM_STATE_NOT_READY,
                            TelephonyManager.SIM_STATE_PERM_DISABLED,
                            TelephonyManager.SIM_STATE_LOADED).contains(simApplicationState));
                }
            }
        } catch (SecurityException e) {
            fail("Caller with READ_PRIVILEGED_PHONE_STATE should be able to call API");
        }
    }

    @Test
    public void testGetSimCardState() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        int simCardState = mTelephonyManager.getSimCardState();
        assertTrue(Arrays.asList(TelephonyManager.SIM_STATE_UNKNOWN,
                TelephonyManager.SIM_STATE_ABSENT,
                TelephonyManager.SIM_STATE_CARD_IO_ERROR,
                TelephonyManager.SIM_STATE_CARD_RESTRICTED,
                TelephonyManager.SIM_STATE_PRESENT).contains(simCardState));
    }
    @Test
    @ApiTest(apis = {"android.telephony.TelephonyManager#getUiccCardsInfo",
            "android.telephony.TelephonyManager#getSimCardState"})
    public void getSimCardStateTest() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .adoptShellPermissionIdentity(
                        android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
        List<UiccCardInfo> cardsInfo = mTelephonyManager.getUiccCardsInfo();
        for (UiccCardInfo cardInfo : cardsInfo) {
            for (UiccPortInfo portInfo : cardInfo.getPorts()) {
                int simCardState = mTelephonyManager.getSimCardState(cardInfo
                        .getPhysicalSlotIndex(), portInfo.getPortIndex());
                assertTrue(Arrays.asList(TelephonyManager.SIM_STATE_UNKNOWN,
                        TelephonyManager.SIM_STATE_ABSENT,
                        TelephonyManager.SIM_STATE_CARD_IO_ERROR,
                        TelephonyManager.SIM_STATE_CARD_RESTRICTED,
                        TelephonyManager.SIM_STATE_PRESENT).contains(simCardState));
            }
        }
        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .dropShellPermissionIdentity();
    }

    @Test
    public void testMultipleEnabledProfiles() {
        if (hasFeature(PackageManager.FEATURE_TELEPHONY_EUICC_MEP)) {
            List<UiccCardInfo> cardInfos =
                    ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                            (tm) -> tm.getUiccCardsInfo());
            for (UiccCardInfo cardInfo : cardInfos) {
                // This test suppose there is no use case that OEMs will have multiple esim
                // chipset with different MEP capabilities.
                if (cardInfo.isEuicc()) {
                    assertTrue(cardInfo.isMultipleEnabledProfilesSupported());
                    List<UiccPortInfo> uiccPortInfos = (List<UiccPortInfo>)
                            ShellIdentityUtils.invokeMethodWithShellPermissions(cardInfo,
                                    (card) -> card.getPorts());
                    assertTrue(uiccPortInfos.size() > 1);
                }
            }
        }
    }

    private boolean isDataEnabled() {
        return ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                TelephonyManager::isDataEnabled);
    }

    @Test
    public void testThermalDataEnable() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        // Perform this test on default data subscription.
        mTelephonyManager = getContext().getSystemService(TelephonyManager.class)
                .createForSubscriptionId(SubscriptionManager.getDefaultDataSubscriptionId());
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager,
                (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_THERMAL,
                        false));

        waitForMs(1000);
        boolean isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                        TelephonyManager.DATA_ENABLED_REASON_THERMAL));
        assertFalse(isDataEnabledForReason);

        boolean isDataConnectionAvailable = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, TelephonyManager::isDataConnectionAllowed);
        assertFalse(isDataConnectionAvailable);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager,
                (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_THERMAL,
                        true));

        waitForMs(1000);
        isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                        TelephonyManager.DATA_ENABLED_REASON_THERMAL));
        assertTrue(isDataEnabledForReason);

        isDataConnectionAvailable = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, TelephonyManager::isDataConnectionAllowed);
        assertTrue(isDataConnectionAvailable);
    }

    @Test
    public void testPolicyDataEnable() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        // Perform this test on default data subscription.
        mTelephonyManager = getContext().getSystemService(TelephonyManager.class)
                .createForSubscriptionId(SubscriptionManager.getDefaultDataSubscriptionId());

        int retry = 0;
        boolean isDataEnabledForReason = true;
        boolean isDataConnectionAvailable = true;
        // NPMS will set policy data to true after tests set it to false,
        // so retry disabling policy data to prevent flaky test failures.
        // TODO: Set empty policies once we can suppress default policies.
        while ((isDataEnabledForReason || isDataConnectionAvailable) && retry < 30) {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_POLICY,
                            false));
            isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                            TelephonyManager.DATA_ENABLED_REASON_POLICY));
            isDataConnectionAvailable = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, TelephonyManager::isDataConnectionAllowed);
            retry++;
            waitForMs(500);
        }
        assertFalse(isDataEnabledForReason);
        assertFalse(isDataConnectionAvailable);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager,
                (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_POLICY,
                        true));

        waitForMs(1000);
        isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                        TelephonyManager.DATA_ENABLED_REASON_POLICY));
        assertTrue(isDataEnabledForReason);

        isDataConnectionAvailable = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, TelephonyManager::isDataConnectionAllowed);
        assertTrue(isDataConnectionAvailable);
    }

    @Test
    public void testCarrierDataEnable() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        // Perform this test on default data subscription.
        mTelephonyManager = getContext().getSystemService(TelephonyManager.class)
                .createForSubscriptionId(SubscriptionManager.getDefaultDataSubscriptionId());
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager,
                (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_CARRIER,
                        false));

        waitForMs(1000);
        boolean isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                        TelephonyManager.DATA_ENABLED_REASON_CARRIER));
        assertFalse(isDataEnabledForReason);

        boolean isDataConnectionAvailable = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, TelephonyManager::isDataConnectionAllowed);
        assertFalse(isDataConnectionAvailable);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager,
                (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_CARRIER,
                        true));

        waitForMs(1000);
        isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                        TelephonyManager.DATA_ENABLED_REASON_CARRIER));
        assertTrue(isDataEnabledForReason);
        isDataConnectionAvailable = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, TelephonyManager::isDataConnectionAllowed);
        assertTrue(isDataConnectionAvailable);
    }

    @Test
    public void testUserDataEnable() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager,
                (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER,
                        false));

        waitForMs(1000);
        boolean isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                        TelephonyManager.DATA_ENABLED_REASON_USER));
        assertFalse(isDataEnabledForReason);

        boolean isDataConnectionAvailable = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, TelephonyManager::isDataConnectionAllowed);
        assertFalse(isDataConnectionAvailable);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager,
                (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER,
                        true));

        waitForMs(1000);
        isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                        TelephonyManager.DATA_ENABLED_REASON_USER));
        assertTrue(isDataEnabledForReason);
        isDataConnectionAvailable = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, TelephonyManager::isDataConnectionAllowed);
        assertTrue(isDataConnectionAvailable);
    }

    @Test
    public void testDataDuringVoiceCallPolicy() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        ShellIdentityUtils.ShellPermissionMethodHelper<Boolean, TelephonyManager> getPolicyHelper =
                (tm) -> tm.isMobileDataPolicyEnabled(
                        TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL);

        boolean allowDataDuringVoiceCall = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, getPolicyHelper);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager, (tm) -> tm.setMobileDataPolicyEnabled(
                        TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL,
                        !allowDataDuringVoiceCall));

        waitForMs(500);
        assertNotEquals(allowDataDuringVoiceCall,
                ShellIdentityUtils.invokeMethodWithShellPermissions(
                        mTelephonyManager, getPolicyHelper));

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager, (tm) -> tm.setMobileDataPolicyEnabled(
                        TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL,
                        allowDataDuringVoiceCall));

        waitForMs(500);
        assertEquals(allowDataDuringVoiceCall,
                ShellIdentityUtils.invokeMethodWithShellPermissions(
                        mTelephonyManager, getPolicyHelper));
    }

    private interface Condition {
        Object expected();
        Object actual();
    }

    private void waitUntilConditionIsTrueOrTimeout(
            Condition condition, long timeout, String description) {
        final long start = System.currentTimeMillis();
        while (!Objects.equals(condition.expected(), condition.actual())
                && System.currentTimeMillis() - start < timeout) {
            waitForMs(50);
        }
        assertEquals(description, condition.expected(), condition.actual());
    }

    private void waitForDataPolicySetting(ShellIdentityUtils.ShellPermissionMethodHelper<Boolean,
            TelephonyManager> getPolicyHelper, boolean mmsAlwaysAllowed) {
        waitUntilConditionIsTrueOrTimeout(
                new Condition() {
                    @Override
                    public Object expected() {
                        return mmsAlwaysAllowed;
                    }

                    @Override
                    public Object actual() {
                        Log.d(TAG, "invokeMethodWithShellPermissions : " + mmsAlwaysAllowed);
                        return ShellIdentityUtils.invokeMethodWithShellPermissions(
                          mTelephonyManager, getPolicyHelper);
                    }
                }, WAIT_FOR_CONDITION, "Policy returned");
    }

    @Test
    public void testAlwaysAllowMmsDataPolicy() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        ShellIdentityUtils.ShellPermissionMethodHelper<Boolean, TelephonyManager> getPolicyHelper =
                (tm) -> tm.isMobileDataPolicyEnabled(
                        TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED);

        boolean mmsAlwaysAllowed = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, getPolicyHelper);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager, (tm) -> tm.setMobileDataPolicyEnabled(
                        TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED,
                        !mmsAlwaysAllowed));

        waitForDataPolicySetting(getPolicyHelper, !mmsAlwaysAllowed);
        assertNotEquals(mmsAlwaysAllowed,
                ShellIdentityUtils.invokeMethodWithShellPermissions(
                        mTelephonyManager, getPolicyHelper));

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager, (tm) -> tm.setMobileDataPolicyEnabled(
                        TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED,
                        mmsAlwaysAllowed));

        waitForDataPolicySetting(getPolicyHelper, mmsAlwaysAllowed);
        assertEquals(mmsAlwaysAllowed,
                ShellIdentityUtils.invokeMethodWithShellPermissions(
                        mTelephonyManager, getPolicyHelper));
    }

    @Test
    public void testAutoDataSwitchPolicy() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_DATA));

        ShellIdentityUtils.ShellPermissionMethodHelper<Boolean, TelephonyManager> getPolicyHelper =
                (tm) -> tm.isMobileDataPolicyEnabled(
                        TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH);

        boolean autoDatSwitchAllowed = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, getPolicyHelper);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager, (tm) -> tm.setMobileDataPolicyEnabled(
                        TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
                        !autoDatSwitchAllowed));

        waitForMs(1000);
        assertNotEquals(autoDatSwitchAllowed,
                ShellIdentityUtils.invokeMethodWithShellPermissions(
                        mTelephonyManager, getPolicyHelper));

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                mTelephonyManager, (tm) -> tm.setMobileDataPolicyEnabled(
                        TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
                        autoDatSwitchAllowed));

        waitForMs(1000);
        assertEquals(autoDatSwitchAllowed,
                ShellIdentityUtils.invokeMethodWithShellPermissions(
                        mTelephonyManager, getPolicyHelper));
    }

    @Test
    public void testGetCdmaEnhancedRoamingIndicatorDisplayNumber() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CDMA));

        int index = mTelephonyManager.getCdmaEnhancedRoamingIndicatorDisplayNumber();
        int phoneType = mTelephonyManager.getPhoneType();
        if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
            assertTrue(index >= 0 && index <= 255);
        } else {
            assertEquals(-1, index);
        }
    }

    private int disableNrDualConnectivity() {
        if (!ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isRadioInterfaceCapabilitySupported(
                        TelephonyManager
                                .CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE))) {
            return TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED;
        }

        int result = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager,
                (tm) -> tm.setNrDualConnectivityState(
                        TelephonyManager.NR_DUAL_CONNECTIVITY_DISABLE));

        boolean isNrDualConnectivityEnabled =
                ShellIdentityUtils.invokeMethodWithShellPermissions(
                        mTelephonyManager, (tm) -> tm.isNrDualConnectivityEnabled());
        // Only verify the result for supported devices on IRadio 1.6+
        if (mNetworkHalVersion >= RADIO_HAL_VERSION_1_6
                && result != TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED) {
            assertFalse(isNrDualConnectivityEnabled);
        }

        return result;
    }

    @Test
    public void testNrDualConnectivityEnable() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        if (!ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isRadioInterfaceCapabilitySupported(
                        TelephonyManager
                                .CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE))) {
            return;
        }

        boolean isInitiallyEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isNrDualConnectivityEnabled());
        boolean isNrDualConnectivityEnabled;
        int result;
        if (isInitiallyEnabled) {
            result = disableNrDualConnectivity();
            if (result == TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED) {
                return;
            }
        }


        result = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager,
                (tm) -> tm.setNrDualConnectivityState(
                        TelephonyManager.NR_DUAL_CONNECTIVITY_ENABLE));

        if (result == TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED) {
            return;
        }

        isNrDualConnectivityEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isNrDualConnectivityEnabled());
        // Only verify the result for supported devices on IRadio 1.6+
        if (mNetworkHalVersion >= RADIO_HAL_VERSION_1_6) {
            assertTrue(isNrDualConnectivityEnabled);
        }

        if (!isInitiallyEnabled) {
            disableNrDualConnectivity();
        }
    }

    @Test
    public void testCdmaRoamingMode() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
                && mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA);

        // Save state
        int cdmaRoamingMode = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                TelephonyManager::getCdmaRoamingMode);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setCdmaRoamingMode(TelephonyManager.CDMA_ROAMING_MODE_HOME));
        assertEquals(TelephonyManager.CDMA_ROAMING_MODE_HOME,
                (int) ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                        TelephonyManager::getCdmaRoamingMode));
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setCdmaRoamingMode(TelephonyManager.CDMA_ROAMING_MODE_AFFILIATED));
        assertEquals(TelephonyManager.CDMA_ROAMING_MODE_AFFILIATED,
                (int) ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                        TelephonyManager::getCdmaRoamingMode));

        // Reset state
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setCdmaRoamingMode(cdmaRoamingMode));
    }

    @Test
    public void testCdmaSubscriptionMode() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
                && mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA);

        // Save state
        int cdmaSubscriptionMode = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, TelephonyManager::getCdmaSubscriptionMode);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setCdmaSubscriptionMode(TelephonyManager.CDMA_SUBSCRIPTION_NV));
        assertEquals(TelephonyManager.CDMA_SUBSCRIPTION_NV,
                (int) ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                        TelephonyManager::getCdmaSubscriptionMode));
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setCdmaSubscriptionMode(TelephonyManager.CDMA_SUBSCRIPTION_RUIM_SIM));
        assertEquals(TelephonyManager.CDMA_SUBSCRIPTION_RUIM_SIM,
                (int) ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                        TelephonyManager::getCdmaSubscriptionMode));

        // Reset state
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setCdmaSubscriptionMode(cdmaSubscriptionMode));
    }

    @Test
    public void testPinResult() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        final String empty_pin = ""; // For getting current remaining pin attempt.
        final String pin = "fake_pin";
        final String puk = "fake_puk";
        final String newPin = "fake_new_pin";

        //Refer GSM 02.17 5.6 PIN Management
        //To avoid that sim may enter PUK state,
        //TC should be allowed when current Pin attempt count is reset with 3.
        boolean isEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, TelephonyManager::isIccLockEnabled);
        PinResult result = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.supplyIccLockPin(empty_pin));
        if (result.getAttemptsRemaining() < 3) {
            Log.d(TAG, "Skipping test and requires that reboot device and unlock pin successfully");
            return;
        }

        result = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.setIccLockEnabled(!isEnabled, pin));
        assertTrue(result.getResult() == PinResult.PIN_RESULT_TYPE_INCORRECT
                || result.getResult() == PinResult.PIN_RESULT_TYPE_FAILURE);
        assertTrue(result.getAttemptsRemaining() >= -1);
        assertEquals(isEnabled, ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, TelephonyManager::isIccLockEnabled));

        result = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.changeIccLockPin(pin, newPin));
        assertTrue(result.getResult() == PinResult.PIN_RESULT_TYPE_INCORRECT
                || result.getResult() == PinResult.PIN_RESULT_TYPE_FAILURE);
        assertTrue(result.getAttemptsRemaining() >= -1);

        result = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.supplyIccLockPin(pin));
        assertTrue(result.getResult() == PinResult.PIN_RESULT_TYPE_INCORRECT
                || result.getResult() == PinResult.PIN_RESULT_TYPE_FAILURE);
        assertTrue(result.getAttemptsRemaining() >= -1);

        result = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.supplyIccLockPuk(puk, pin));
        assertTrue(result.getResult() == PinResult.PIN_RESULT_TYPE_INCORRECT
                || result.getResult() == PinResult.PIN_RESULT_TYPE_FAILURE);
        assertTrue(result.getAttemptsRemaining() >= -1);
    }

    @Test
    public void testSetSignalStrengthUpdateRequest_nullRequest() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // Verify NPE throws if set request with null object
        try {
            mTelephonyManager.setSignalStrengthUpdateRequest(null);
            fail("NullPointerException expected when setSignalStrengthUpdateRequest with null");
        } catch (NullPointerException expected) {
        }
    }

    @Test
    public void testSetSignalStrengthUpdateRequest_noPermission() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        final SignalStrengthUpdateRequest normalRequest =
                new SignalStrengthUpdateRequest.Builder()
                        .setSignalThresholdInfos(List.of(
                                new SignalThresholdInfo.Builder()
                                        .setRadioAccessNetworkType(
                                                AccessNetworkConstants.AccessNetworkType.GERAN)
                                        .setSignalMeasurementType(
                                                SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
                                        .setThresholds(new int[]{-113, -103, -97, -51})
                                        .build()))
                        .setReportingRequestedWhileIdle(true)
                        .build();

        // Verify SE throws for apps without carrier privilege or MODIFY_PHONE_STATE permission
        try {
            mTelephonyManager.setSignalStrengthUpdateRequest(normalRequest);
            fail("SecurityException expected when setSignalStrengthUpdateRequest without "
                    + "carrier privilege or MODIFY_PHONE_STATE permission");
        } catch (SecurityException expected) {
        } finally {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.clearSignalStrengthUpdateRequest(normalRequest));
        }
    }

    @Test
    public void testSetSignalStrengthUpdateRequest_systemThresholdReportingRequestedWhileIdle() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // Verify system privileged app with permission LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH can
        // set systemThresholdReportingRequestedWhileIdle to true with empty thresholdInfos
        SignalStrengthUpdateRequest request = new SignalStrengthUpdateRequest.Builder()
                .setSignalThresholdInfos(Collections.EMPTY_LIST)
                .setSystemThresholdReportingRequestedWhileIdle(true)
                .build();

        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager, (tm) -> tm.setSignalStrengthUpdateRequest(request));
        } finally {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.clearSignalStrengthUpdateRequest(request));
        }
    }

    @Test
    public void testSetSignalStrengthUpdateRequest_hysteresisDbSet() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // Verify SE throws for app when set hysteresisDb in the SignalThresholdInfo
        SignalStrengthUpdateRequest requestWithHysteresisDbSet =
                new SignalStrengthUpdateRequest.Builder()
                        .setSignalThresholdInfos(List.of(
                                new SignalThresholdInfo.Builder()
                                        .setRadioAccessNetworkType(
                                                AccessNetworkConstants.AccessNetworkType.GERAN)
                                        .setSignalMeasurementType(
                                                SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
                                        .setThresholds(new int[]{-113, -103, -97, -51})
                                        .setHysteresisDb(10)
                                        .build()))
                        .setReportingRequestedWhileIdle(true)
                        .build();

        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setSignalStrengthUpdateRequest(requestWithHysteresisDbSet));
        } finally {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.clearSignalStrengthUpdateRequest(requestWithHysteresisDbSet));
        }
    }


    @Test
    public void testSetSignalStrengthUpdateRequest_hysteresisMsSet() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // Verify SE throws for app when set hysteresisMs in the SignalThresholdInfo
        SignalStrengthUpdateRequest requestWithHysteresisMsSet =
                new SignalStrengthUpdateRequest.Builder()
                        .setSignalThresholdInfos(List.of(
                                new SignalThresholdInfo.Builder()
                                        .setRadioAccessNetworkType(
                                                AccessNetworkConstants.AccessNetworkType.GERAN)
                                        .setSignalMeasurementType(
                                                SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
                                        .setThresholds(new int[]{-113, -103, -97, -51})
                                        .setHysteresisMs(1000) //allowed for system caller only
                                        .build()))
                        .setReportingRequestedWhileIdle(true)
                        .build();
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setSignalStrengthUpdateRequest(requestWithHysteresisMsSet));
            fail("IllegalArgumentException expected when set hysteresisMs in SignalThresholdInfo "
                    + "to true");
        } catch (IllegalArgumentException expected) {
        } finally {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.clearSignalStrengthUpdateRequest(requestWithHysteresisMsSet));
        }
    }

    @Test
    public void testSetSignalStrengthUpdateRequest_isEnabledSet() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // Verify SE throws for app when set isEnabled in the SignalThresholdInfo
        SignalStrengthUpdateRequest requestWithThresholdIsEnabledSet =
                new SignalStrengthUpdateRequest.Builder()
                        .setSignalThresholdInfos(List.of(
                                new SignalThresholdInfo.Builder()
                                        .setRadioAccessNetworkType(
                                                AccessNetworkConstants.AccessNetworkType.GERAN)
                                        .setSignalMeasurementType(
                                                SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
                                        .setThresholds(new int[]{-113, -103, -97})
                                        .setIsEnabled(true) //allowed for system caller only
                                        .build()))
                        .setReportingRequestedWhileIdle(true)
                        .build();
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setSignalStrengthUpdateRequest(requestWithThresholdIsEnabledSet));
            fail("IllegalArgumentException expected when set isEnabled in SignalThresholdInfo "
                    + "with true");
        } catch (IllegalArgumentException expected) {
        } finally {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.clearSignalStrengthUpdateRequest(requestWithThresholdIsEnabledSet));
        }
    }

    @Test
    public void testSetSignalStrengthUpdateRequest_tooShortThresholds() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // verify SE throws if app set too short thresholds
        SignalStrengthUpdateRequest requestWithTooShortThresholds =
                new SignalStrengthUpdateRequest.Builder()
                        .setSignalThresholdInfos(List.of(
                                new SignalThresholdInfo.Builder()
                                        .setRadioAccessNetworkType(
                                                AccessNetworkConstants.AccessNetworkType.GERAN)
                                        .setSignalMeasurementType(
                                                SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
                                        .setThresholds(new int[]{}, true /*isSystem*/)
                                        .build()))
                        .setReportingRequestedWhileIdle(true)
                        .build();
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setSignalStrengthUpdateRequest(requestWithTooShortThresholds));
            fail("IllegalArgumentException expected when set thresholds that is too short");
        } catch (IllegalArgumentException expected) {
        } finally {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.clearSignalStrengthUpdateRequest(requestWithTooShortThresholds));
        }
    }

    @Test
    public void testSetSignalStrengthUpdateRequest_tooLongThresholds() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // verify SE throws if app set too long thresholds
        SignalStrengthUpdateRequest requestWithTooLongThresholds =
                new SignalStrengthUpdateRequest.Builder()
                        .setSignalThresholdInfos(List.of(
                                new SignalThresholdInfo.Builder()
                                        .setRadioAccessNetworkType(
                                                AccessNetworkConstants.AccessNetworkType.GERAN)
                                        .setSignalMeasurementType(
                                                SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
                                        .setThresholds(new int[]{-113, -103, -97, -61, -51},
                                            true /*isSystem*/)
                                        .build()))
                        .setReportingRequestedWhileIdle(true)
                        .build();
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setSignalStrengthUpdateRequest(requestWithTooLongThresholds));
            fail("IllegalArgumentException expected when set thresholds that is too long");
        } catch (IllegalArgumentException expected) {
        } finally {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.clearSignalStrengthUpdateRequest(requestWithTooLongThresholds));
        }
    }

    @Test
    public void testSetSignalStrengthUpdateRequest_duplicatedRequest() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        final SignalStrengthUpdateRequest normalRequest =
                new SignalStrengthUpdateRequest.Builder()
                        .setSignalThresholdInfos(List.of(
                                new SignalThresholdInfo.Builder()
                                        .setRadioAccessNetworkType(
                                                AccessNetworkConstants.AccessNetworkType.GERAN)
                                        .setSignalMeasurementType(
                                                SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
                                        .setThresholds(new int[]{-113, -103, -97, -51})
                                        .build()))
                        .setReportingRequestedWhileIdle(true)
                        .build();

        // Verify IllegalStateException should throw when set the same request twice
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                (tm) -> tm.setSignalStrengthUpdateRequest(normalRequest));
        try {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.setSignalStrengthUpdateRequest(normalRequest));
            fail("IllegalStateException expected when setSignalStrengthUpdateRequest twice with "
                    + "same request object");
        } catch (IllegalStateException expected) {
        } finally {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    (tm) -> tm.clearSignalStrengthUpdateRequest(normalRequest));
        }
    }

    @Test
    public void testClearSignalStrengthUpdateRequest_nullRequest() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // Verify NPE should throw if clear request with null object
        try {
            mTelephonyManager.clearSignalStrengthUpdateRequest(null);
            fail("NullPointerException expected when clearSignalStrengthUpdateRequest with null");
        } catch (NullPointerException expected) {
        }
    }

    @Test
    public void testClearSignalStrengthUpdateRequest_noPermission() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        final SignalStrengthUpdateRequest normalRequest =
                new SignalStrengthUpdateRequest.Builder()
                        .setSignalThresholdInfos(List.of(
                                new SignalThresholdInfo.Builder()
                                        .setRadioAccessNetworkType(
                                                AccessNetworkConstants.AccessNetworkType.GERAN)
                                        .setSignalMeasurementType(
                                                SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
                                        .setThresholds(new int[]{-113, -103, -97, -51})
                                        .build()))
                        .setReportingRequestedWhileIdle(true)
                        .build();

        // Verify SE throws for apps without carrier privilege or MODIFY_PHONE_STATE permission
        try {
            mTelephonyManager.clearSignalStrengthUpdateRequest(normalRequest);
            fail("SecurityException expected when clearSignalStrengthUpdateRequest without "
                    + "carrier privilege or MODIFY_PHONE_STATE permission");
        } catch (SecurityException expected) {
        }
    }

    @Test
    public void testClearSignalStrengthUpdateRequest_clearWithNoSet() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        SignalStrengthUpdateRequest requestNeverSetBefore = new SignalStrengthUpdateRequest
                .Builder()
                .setSignalThresholdInfos(List.of(new SignalThresholdInfo.Builder()
                        .setRadioAccessNetworkType(AccessNetworkConstants.AccessNetworkType.GERAN)
                        .setSignalMeasurementType(SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
                        .setThresholds(new int[]{-113, -103, -97, -51})
                        .build()))
                .setReportingRequestedWhileIdle(true)
                .build();

        // Verify clearSignalStrengthUpdateRequest is no-op when clear request that was not set
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                (tm) -> tm.clearSignalStrengthUpdateRequest(requestNeverSetBefore));
    }

    @Test
    public void testSendThermalMitigationRequest() throws Exception {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        StringBuilder cmdBuilder = new StringBuilder();
        cmdBuilder.append(THERMAL_MITIGATION_COMMAND_BASE).append(ALLOW_PACKAGE_SUBCOMMAND)
                .append(TELEPHONY_CTS_PACKAGE);
        TelephonyUtils.executeShellCommand(InstrumentationRegistry.getInstrumentation(),
                cmdBuilder.toString());

        long arbitraryCompletionWindowMillis = 60000L;

        boolean isDataThrottlingSupported = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.isRadioInterfaceCapabilitySupported(
                        TelephonyManager.CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING));

        int thermalMitigationResult = -1;
        if (isDataThrottlingSupported) {
            // Test a proper data throttling thermal mitigation request.
            thermalMitigationResult = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.sendThermalMitigationRequest(
                        new ThermalMitigationRequest.Builder()
                                .setThermalMitigationAction(ThermalMitigationRequest
                                        .THERMAL_MITIGATION_ACTION_DATA_THROTTLING)
                                .setDataThrottlingRequest(new DataThrottlingRequest.Builder()
                                        .setDataThrottlingAction(DataThrottlingRequest
                                                .DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER)
                                        .setCompletionDurationMillis(arbitraryCompletionWindowMillis)
                                        .build())
                                .build()));

            assertEquals(thermalMitigationResult,
                    TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS);
        }
        // Test negative completionDurationSecs is an invalid parameter.
        try {
            thermalMitigationResult = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.sendThermalMitigationRequest(
                            new ThermalMitigationRequest.Builder()
                                    .setThermalMitigationAction(ThermalMitigationRequest
                                            .THERMAL_MITIGATION_ACTION_DATA_THROTTLING)
                                    .setDataThrottlingRequest(new DataThrottlingRequest.Builder()
                                            .setDataThrottlingAction(DataThrottlingRequest
                                                    .DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER
                                            )
                                            .setCompletionDurationMillis(-1)
                                            .build())
                                    .build()));
        } catch (IllegalArgumentException e) {
        }

        // Test non-zero completionDurationSecs is an invalid parameter for data throttling hold.
        try {
            thermalMitigationResult = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.sendThermalMitigationRequest(
                            new ThermalMitigationRequest.Builder()
                                    .setThermalMitigationAction(ThermalMitigationRequest
                                            .THERMAL_MITIGATION_ACTION_DATA_THROTTLING)
                                    .setDataThrottlingRequest(new DataThrottlingRequest.Builder()
                                            .setDataThrottlingAction(
                                                    DataThrottlingRequest
                                                            .DATA_THROTTLING_ACTION_HOLD)
                                            .setCompletionDurationMillis(
                                                    arbitraryCompletionWindowMillis)
                                            .build())
                                    .build()));
        } catch (IllegalArgumentException e) {
        }

        // Test null DataThrottlingParams is an invalid parameter for data throttling request.
        try {
            thermalMitigationResult = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.sendThermalMitigationRequest(
                            new ThermalMitigationRequest.Builder()
                                    .setThermalMitigationAction(ThermalMitigationRequest
                                            .THERMAL_MITIGATION_ACTION_DATA_THROTTLING)
                                    .build()));
        } catch (IllegalArgumentException e) {
        }

        // Test non-null DataThrottlingParams is an invalid parameter for voice only request.
        try {
            thermalMitigationResult = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.sendThermalMitigationRequest(
                            new ThermalMitigationRequest.Builder()
                                    .setThermalMitigationAction(
                                            ThermalMitigationRequest
                                                    .THERMAL_MITIGATION_ACTION_VOICE_ONLY)
                                    .setDataThrottlingRequest(new DataThrottlingRequest.Builder()
                                            .setDataThrottlingAction(
                                                    DataThrottlingRequest
                                                    .DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER
                                            )
                                            .setCompletionDurationMillis(-1)
                                            .build())
                            .build()));
        } catch (IllegalArgumentException e) {
        }

        // Test non-null DataThrottlingParams is an invalid parameter for radio off request.
        try {
            thermalMitigationResult = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.sendThermalMitigationRequest(
                            new ThermalMitigationRequest.Builder()
                                    .setThermalMitigationAction(
                                            ThermalMitigationRequest
                                                    .THERMAL_MITIGATION_ACTION_RADIO_OFF)
                                    .setDataThrottlingRequest(new DataThrottlingRequest.Builder()
                                            .setDataThrottlingAction(DataThrottlingRequest
                                                    .DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER
                                            )
                                            .setCompletionDurationMillis(-1)
                                            .build())
                            .build()));
        } catch (IllegalArgumentException e) {
        }
    }

    @Test
    public void testIsRadioInterfaceCapabilitySupported() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        assertFalse(mTelephonyManager.isRadioInterfaceCapabilitySupported("empty"));
        assertFalse(mTelephonyManager.isRadioInterfaceCapabilitySupported(null));
        assertFalse(mTelephonyManager.isRadioInterfaceCapabilitySupported(""));
    }

    private Set<CellIdentity> getRegisteredCellIdentities() {
        ServiceState ss = mTelephonyManager.getServiceState();
        Set<CellIdentity> cidSet = new ArraySet<>(2);
        for (NetworkRegistrationInfo nri : ss.getNetworkRegistrationInfoListForTransportType(
                AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) {
            if (nri.isRegistered()) cidSet.add(nri.getCellIdentity());
        }
        return cidSet;
    }

    private boolean hasMultipleRegisteredSubscriptions() {
        final int[] activeSubIds = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mSubscriptionManager, (sm) ->sm.getActiveSubscriptionIdList());
        int registeredSubscriptions = 0;
        for (int subId : activeSubIds) {
            ServiceState ss = mTelephonyManager.createForSubscriptionId(subId).getServiceState();
            for (NetworkRegistrationInfo nri : ss.getNetworkRegistrationInfoListForTransportType(
                    AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) {
                if (nri.isRegistered()) {
                    registeredSubscriptions++;
                    break;
                }
            }
        }
        return registeredSubscriptions > 1;
    }

    @Test
    public void testGetAllCellInfo() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
        // For INetworkRadio <1.5, just verify that calling the method doesn't throw an error.
        if (mNetworkHalVersion < RADIO_HAL_VERSION_1_5) {
            mTelephonyManager.getAllCellInfo();
            return;
        }

        List<CellInfo> allCellInfo = mTelephonyManager.getAllCellInfo();
        assertTrue(!allCellInfo.isEmpty());
        for (CellInfo cellInfo : allCellInfo) {
            CellIdentity cellIdentity = cellInfo.getCellIdentity();
            int[] bands;
            if (cellIdentity instanceof CellIdentityLte) {
                bands = ((CellIdentityLte) cellIdentity).getBands();
                if (cellInfo.isRegistered()) assertTrue(bands.length > 0);
                for (int band : bands) {
                    assertTrue(band >= AccessNetworkConstants.EutranBand.BAND_1
                            && band <= AccessNetworkConstants.EutranBand.BAND_88);
                }
            } else if (cellIdentity instanceof CellIdentityNr) {
                bands = ((CellIdentityNr) cellIdentity).getBands();
                if (cellInfo.isRegistered()) assertTrue(bands.length > 0);
                for (int band : bands) {
                    assertTrue((band >= AccessNetworkConstants.NgranBands.BAND_1
                            && band <= AccessNetworkConstants.NgranBands.BAND_95)
                            || (band >= AccessNetworkConstants.NgranBands.BAND_257
                            && band <= AccessNetworkConstants.NgranBands.BAND_261));
                }
            }

            // TODO(229311863): This can theoretically break on a DSDS device where both SIMs are
            // registered because CellInfo returns data for both modems and this code only cross
            // checks against the default subscription.
            if (hasMultipleRegisteredSubscriptions()) continue;

            boolean isSameCell = false;
            if (cellInfo.isRegistered()) {
                for (CellIdentity cid : getRegisteredCellIdentities()) {
                    if (cellIdentity.isSameCell(cid)) isSameCell = true;
                }
                assertTrue(sNetworkTypes.get(cellIdentity.getClass()).contains(
                            mTelephonyManager.getDataNetworkType())
                                    || sNetworkTypes.get(cellIdentity.getClass()).contains(
                                            mTelephonyManager.getVoiceNetworkType()));
                assertTrue(
                        "Registered CellInfo#CellIdentity not found in ServiceState",
                        isSameCell);
            }
        }

    }

    @Test
    @ApiTest(apis = {"android.telephony.CarrierConfigManager#KEY_CARRIER_METERED_APN_TYPES_STRINGS",
            "android.telephony.CarrierConfigManager#KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS",
            "android.telephony.TelephonyManager#isApnMetered"})
    public void testIsApnMetered() throws Exception {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        PersistableBundle carrierConfig = new PersistableBundle();
        carrierConfig.putStringArray(
                CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                new String[] {ApnSetting.TYPE_MMS_STRING});
        carrierConfig.putStringArray(
                CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
                new String[] {ApnSetting.TYPE_MMS_STRING});
        overrideCarrierConfig(carrierConfig);

        try {
            InstrumentationRegistry.getInstrumentation()
                    .getUiAutomation()
                    .adoptShellPermissionIdentity(
                            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
            PollingCheck.waitFor(5000, () -> !mTelephonyManager.isApnMetered(ApnSetting.TYPE_DUN),
                    "Timeout when waiting for DUN APN to become unmetered");

            assertTrue(mTelephonyManager.isApnMetered(ApnSetting.TYPE_MMS));
            assertFalse(mTelephonyManager.isApnMetered(ApnSetting.TYPE_DUN));
        } finally {
            // Restore the original carrier config
            overrideCarrierConfig(null);
            // Revoke the permission READ_PRIVILEGED_PHONE_STATE
            InstrumentationRegistry.getInstrumentation()
                    .getUiAutomation()
                    .dropShellPermissionIdentity();
        }

        carrierConfig.putStringArray(
                CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                new String[] {ApnSetting.TYPE_DUN_STRING});
        carrierConfig.putStringArray(
                CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
                new String[] {ApnSetting.TYPE_DUN_STRING});
        overrideCarrierConfig(carrierConfig);
        try {
            InstrumentationRegistry.getInstrumentation()
                    .getUiAutomation()
                    .adoptShellPermissionIdentity(
                            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
            PollingCheck.waitFor(5000, () -> mTelephonyManager.isApnMetered(ApnSetting.TYPE_DUN),
                    "Timeout when waiting for DUN APN to become metered");

            assertFalse(mTelephonyManager.isApnMetered(ApnSetting.TYPE_MMS));
            assertTrue(mTelephonyManager.isApnMetered(ApnSetting.TYPE_DUN));
        } finally {
            overrideCarrierConfig(null);
            InstrumentationRegistry.getInstrumentation()
                    .getUiAutomation()
                    .dropShellPermissionIdentity();
        }
    }

    /**
     * Validate Emergency Number address that only contains the dialable character.
     *
     * @param address Emergency number address to validate
     * @return {@code true} if the address is valid; {@code false} otherwise.
     */
    private static boolean validateEmergencyNumberAddress(String address) {
        if (address == null) {
            return false;
        }
        for (char c : address.toCharArray()) {
            if (!isDialable(c)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Validate Emergency Number country Iso
     *
     * @param countryIso Emergency number country iso to validate
     * @return {@code true} if the country iso is valid; {@code false} otherwise.
     */
    private static boolean validateEmergencyNumberCountryIso(String countryIso) {
        if (countryIso == null) {
            return false;
        }
        int length = countryIso.length();
        return length >= 0 && length <= 2;
    }

    /**
     * Validate Emergency Number MNC
     *
     * @param mnc Emergency number MNC to validate
     * @return {@code true} if the MNC is valid; {@code false} otherwise.
     */
    private static boolean validateEmergencyNumberMnc(String mnc) {
        if (mnc == null) {
            return false;
        }
        int length = mnc.length();
        return length >= 0 && length <= 3;
    }

    /**
     * Validate Emergency service category list
     *
     * @param categories Emergency service category list to validate
     * @return {@code true} if the category list is valid; {@code false} otherwise.
     */
    private static boolean validateEmergencyServiceCategoryList(List<Integer> categories) {
        if (categories == null) {
            return false;
        }
        if (categories.contains(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED)) {
            return categories.size() == 1;
        }
        for (int category : categories) {
            if (!EMERGENCY_SERVICE_CATEGORY_SET.contains(category)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Validate Emergency number source list
     *
     * @param categories Emergency number source list to validate
     * @return {@code true} if the source list is valid; {@code false} otherwise.
     */
    private static boolean validateEmergencyNumberSourceList(List<Integer> sources) {
        if (sources == null) {
            return false;
        }
        for (int source : sources) {
            if (!EMERGENCY_NUMBER_SOURCE_SET.contains(source)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Validate Emergency call routing.
     *
     * @param routing Emergency call routing to validate
     * @return {@code true} if the emergency call routing is valid; {@code false} otherwise.
     */
    private static boolean validateEmergencyCallRouting(int routing) {
        return routing >= EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN
                && routing <= (EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY
                | EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
    }

    /**
     * Valid the emergency number should be at least from a valid source.
     *
     * @param emergencyNumber Emergency number to verify
     * @return {@code true} if the emergency number is from any source; {@code false} otherwise.
     */
    private static boolean validateEmergencyNumberFromAnySource(EmergencyNumber emergencyNumber) {
        boolean isFromAnySource = false;
        for (int possibleSourceValue = EMERGENCY_NUMBER_SOURCE_RIL_ECCLIST;
                possibleSourceValue <= (EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING
                        | EmergencyNumber.EMERGENCY_NUMBER_SOURCE_SIM
                        | EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE
                        | EmergencyNumber.EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG
                        | EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DEFAULT);
                possibleSourceValue++) {
            if (emergencyNumber.isFromSources(possibleSourceValue)) {
                isFromAnySource = true;
                break;
            }
        }
        return isFromAnySource;
    }

    /**
     * Valid the emergency number should be at least in a valid category.
     *
     * @param emergencyNumber Emergency number to verify
     * @return {@code true} if it is in any category; {@code false} otherwise.
     */
    private static boolean validateEmergencyNumberInAnyCategory(EmergencyNumber emergencyNumber) {
        boolean isInAnyCategory = false;
        for (int possibleCategoryValue = EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
                possibleCategoryValue <= (EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE
                        | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_AMBULANCE
                        | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE
                        | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD
                        | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE
                        | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_MIEC
                        | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_AIEC);
                possibleCategoryValue++) {
            if (emergencyNumber.isInEmergencyServiceCategories(possibleCategoryValue)) {
                isInAnyCategory = true;
                break;
            }
        }
        return isInAnyCategory;
    }

    @SuppressWarnings("SelfComparison") // TODO: Fix me
    private static boolean validateEmergencyNumberCompareTo(
            List<EmergencyNumber> emergencyNumberList) {
        if (emergencyNumberList == null) {
            return false;
        }
        if (emergencyNumberList.size() > 0) {
            EmergencyNumber emergencyNumber = emergencyNumberList.get(0);
            if (emergencyNumber.compareTo(emergencyNumber) != 0) {
                return false;
            }
        }
        return true;
    }

    private static boolean isDialable(char c) {
        return (c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+' || c == 'N';
    }

    private Map.Entry<Integer, Integer> getValidSlotIndexAndPort() {
        return ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> {

                    List<UiccCardInfo> cardInfos = mTelephonyManager.getUiccCardsInfo();
                    Set<String> presentCards = Arrays.stream(mTelephonyManager.getUiccSlotsInfo())
                            .filter(Objects::nonNull)
                            .filter(port -> port.getPorts().stream().anyMatch(portInfo ->
                                    portInfo.isActive()))
                            .map(UiccSlotInfo::getCardId)
                            .filter(Objects::nonNull)
                            // hack around getUiccSlotsInfo not stripping trailing F
                            .map(s -> s.endsWith("F") ? s.substring(0, s.length() - 1) : s)
                            .collect(Collectors.toSet());
                    int slotIndex = -1;
                    int portIndex = -1;
                    for (UiccCardInfo cardInfo : cardInfos) {
                        for (UiccPortInfo portInfo : cardInfo.getPorts()) {
                            if (presentCards.contains(portInfo.getIccId())
                                    || presentCards.contains(cardInfo.getEid())) {
                                slotIndex = cardInfo.getPhysicalSlotIndex();
                                portIndex = portInfo.getPortIndex();
                                Log.d(TAG, "SlotIndex : " + slotIndex + " and portIndex :"
                                        + portIndex);
                                break;
                            }
                        }
                    }
                    if (slotIndex < 0) {
                        fail("Test must be run with SIM card inserted, presentCards = "
                                + presentCards + "cardinfos = " + cardInfos);
                    }
                    return Map.entry(slotIndex, portIndex);
                });
    }

    public static void waitForMs(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            Log.d(TAG, "InterruptedException while waiting: " + e);
        }
    }

    /**
     * Verify that the phone is supporting the action of setForbiddenPlmn.
     *
     * @return whether to proceed the test
     */
    private boolean supportSetFplmn() {
        if (!hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)) {
            return false;
        }
        return mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM;
    }

    /**
     * Verify that the phone is supporting the action of setForbiddenPlmn.
     *
     * @return whether to proceed the test
     */
    private boolean test() {
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
            return false;
        }
        return mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM;
    }

    private static int makeRadioVersion(int major, int minor) {
        if (major < 0 || minor < 0) return 0;
        return major * 100 + minor;
    }

    private Executor mSimpleExecutor = Runnable::run;

    private static MockSignalStrengthsTelephonyCallback mMockSignalStrengthsTelephonyCallback;

    private class MockSignalStrengthsTelephonyCallback extends TelephonyCallback
            implements TelephonyCallback.SignalStrengthsListener {
        @Override
        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
            if (!mOnSignalStrengthsChanged) {
                synchronized (mLock) {
                    mOnSignalStrengthsChanged = true;
                    mLock.notify();
                }
            }
        }
    }

    @Test
    public void testRegisterTelephonyCallbackWithNonLooper() throws Throwable {
        mMockSignalStrengthsTelephonyCallback = new MockSignalStrengthsTelephonyCallback();

        // Test register, generates an mOnSignalStrengthsChanged event
        mTelephonyManager.registerTelephonyCallback(mSimpleExecutor,
                mMockSignalStrengthsTelephonyCallback);

        synchronized (mLock) {
            if (!mOnSignalStrengthsChanged) {
                mLock.wait(TOLERANCE);
            }
        }
        assertTrue("Test register, mOnSignalStrengthsChanged should be true.",
                mOnSignalStrengthsChanged);

        // Test unregister
        mOnSignalStrengthsChanged = false;
        // unregister again, to make sure doing so does not call the listener
        mTelephonyManager.unregisterTelephonyCallback(mMockSignalStrengthsTelephonyCallback);

        assertFalse("Test unregister, mOnSignalStrengthsChanged should be false.",
                mOnSignalStrengthsChanged);
    }

    private static MockCellInfoListener mMockCellInfoListener;

    private class MockCellInfoListener extends TelephonyCallback
            implements TelephonyCallback.CellInfoListener {
        @Override
        public void onCellInfoChanged(@NonNull List<CellInfo> cellInfo) {
            if (!mOnCellInfoChanged) {
                synchronized (mLock) {
                    mOnCellInfoChanged = true;
                    mLock.notify();
                }
            }
        }
    }

    @Test
    public void testRegisterTelephonyCallback() throws Throwable {
        if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
            // TODO: temp workaround, need to adjust test to for CDMA
            return;
        }
        grantLocationPermissions();

        TestThread t = new TestThread(() -> {
            Looper.prepare();
            mMockCellInfoListener = new MockCellInfoListener();
            synchronized (mLock) {
                mLock.notify(); // listener is ready
            }

            Looper.loop();
        });

        synchronized (mLock) {
            t.start();
            mLock.wait(TOLERANCE); // wait for listener
        }

        // Test register
        synchronized (mLock) {
            // .registerTelephonyCallback generates an onCellLocationChanged event
            mTelephonyManager.registerTelephonyCallback(mSimpleExecutor, mMockCellInfoListener);
            mLock.wait(TOLERANCE);

            assertTrue("Test register, mOnCellLocationChangedCalled should be true.",
                    mOnCellInfoChanged);
        }

        synchronized (mLock) {
            mOnCellInfoChanged = false;

            CellInfoResultsCallback resultsCallback = new CellInfoResultsCallback();
            mTelephonyManager.requestCellInfoUpdate(mSimpleExecutor, resultsCallback);
            mLock.wait(TOLERANCE);

            assertTrue("Test register, mOnCellLocationChangedCalled should be true.",
                    mOnCellInfoChanged);
        }

        // unregister the listener
        mTelephonyManager.unregisterTelephonyCallback(mMockCellInfoListener);
        Thread.sleep(TOLERANCE);

        // Test unregister
        synchronized (mLock) {
            mOnCellInfoChanged = false;
            // unregister again, to make sure doing so does not call the listener
            mTelephonyManager.unregisterTelephonyCallback(mMockCellInfoListener);
            CellLocation.requestLocationUpdate();
            mLock.wait(TOLERANCE);

            assertFalse("Test unregister, mOnCellLocationChangedCalled should be false.",
                    mOnCellInfoChanged);
        }
    }

    private class CellInfoResultsCallback extends TelephonyManager.CellInfoCallback {
        public List<CellInfo> cellInfo;

        @Override
        public synchronized void onCellInfo(List<CellInfo> cellInfo) {
            this.cellInfo = cellInfo;
            notifyAll();
        }

        public synchronized void wait(int millis) throws InterruptedException {
            if (cellInfo == null) {
                super.wait(millis);
            }
        }
    }

    private void setAppOpsPermissionAllowed(boolean allowed, String op) {
        AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
        int mode = allowed ? AppOpsManager.MODE_ALLOWED : AppOpsManager.opToDefaultMode(op);
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                appOpsManager, (appOps) -> appOps.setUidMode(op, Process.myUid(), mode));
    }

    /**
     * Verifies that {@link TelephonyManager#getNetworkSlicingConfiguration()} does not throw any
     * exception
     */
    @Test
    public void testGetNetworkSlicingConfiguration() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        CompletableFuture<NetworkSlicingConfig> resultFuture = new CompletableFuture<>();
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                (tm) -> tm.getNetworkSlicingConfiguration(mSimpleExecutor, resultFuture::complete));
    }

    @Test
    @ApiTest(apis = {"android.telephony.TelephonyManager#checkCarrierPrivilegesForPackage"})
    public void testCheckCarrierPrivilegesForPackageEnforcesReadPrivilege() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        try {
            InstrumentationRegistry.getInstrumentation()
                    .getUiAutomation()
                    .adoptShellPermissionIdentity(
                            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
            mTelephonyManager.checkCarrierPrivilegesForPackage(mSelfPackageName);
        } catch (SecurityException e) {
            fail("TelephonyManager#checkCarrierPrivilegesForPackage requires "
                    + "READ_PRIVILEGED_PHONE_STATE");
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .dropShellPermissionIdentity();
        }
    }

    @Test
    public void testCheckCarrierPrivilegesForPackageThrowsExceptionWithoutReadPrivilege() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        try {
            mTelephonyManager.checkCarrierPrivilegesForPackage(mSelfPackageName);
            fail("TelephonyManager#checkCarrierPrivilegesForPackage must be protected "
                    + "with READ_PRIVILEGED_PHONE_STATE");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    @ApiTest(apis = {"android.telephony.TelephonyManager#checkCarrierPrivilegesForPackageAnyPhone"})
    public void testCheckCarrierPrivilegesForPackageAnyPhone() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        try {
            mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(mSelfPackageName);
            fail("TelephonyManager#checkCarrierPrivilegesForPackageAnyPhone must be protected "
                    + "with READ_PRIVILEGED_PHONE_STATE");
        } catch (SecurityException expected) {
        }

        try {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .adoptShellPermissionIdentity(
                        android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
            mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(mSelfPackageName);
        } catch (SecurityException e) {
            fail("TelephonyManager#checkCarrierPrivilegesForPackageAnyPhone should not throw "
                    + "SecurityException with READ_PRIVILEGED_PHONE_STATE permission");
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .dropShellPermissionIdentity();
        }
    }

    @Test
    @ApiTest(apis = {"android.telephony.TelephonyManager#getCarrierPackageNamesForIntentAndPhone"})
    public void testGetCarrierPackageNamesForIntentAndPhoneEnforcesReadPrivilege() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        try {
            InstrumentationRegistry.getInstrumentation()
                    .getUiAutomation()
                    .adoptShellPermissionIdentity(
                            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
            Intent intent = new Intent();
            int phoneId = 1;
            mTelephonyManager.getCarrierPackageNamesForIntentAndPhone(intent, phoneId);
        } catch (SecurityException e) {
            fail("TelephonyManager#getCarrierPackageNamesForIntentAndPhone requires "
                    + "READ_PRIVILEGED_PHONE_STATE");
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .dropShellPermissionIdentity();
        }
    }

    @Test
    public void testGetCarrierPackageNamesForIntentAndPhoneThrowsExceptionWithoutReadPrivilege() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        try {
            Intent intent = new Intent();
            int phoneId = 1;
            mTelephonyManager.getCarrierPackageNamesForIntentAndPhone(intent, phoneId);
            fail("TelephonyManager#getCarrierPackageNamesForIntentAndPhone must be protected "
                    + "with READ_PRIVILEGED_PHONE_STATE");
        } catch (SecurityException e) {
            // expected
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .dropShellPermissionIdentity();
        }
    }

    @Test
    @ApiTest(apis = {"android.telephony.TelephonyManager#getPackagesWithCarrierPrivileges"})
    public void testGetPackagesWithCarrierPrivilegesEnforcesReadPrivilege() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        try {
            InstrumentationRegistry.getInstrumentation()
                    .getUiAutomation()
                    .adoptShellPermissionIdentity(
                            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
            mTelephonyManager.getPackagesWithCarrierPrivileges();
        } catch (SecurityException e) {
            fail("TelephonyManager#getPackagesWithCarrierPrivileges requires "
                    + "READ_PRIVILEGED_PHONE_STATE");
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .dropShellPermissionIdentity();
        }
    }

    @Test
    public void testGetPackagesWithCarrierPrivilegesThrowsExceptionWithoutReadPrivilege() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        try {
            mTelephonyManager.getPackagesWithCarrierPrivileges();
            fail("TelephonyManager#getPackagesWithCarrierPrivileges must be protected "
                    + "with READ_PRIVILEGED_PHONE_STATE");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    @ApiTest(apis = {"android.telephony.TelephonyManager#getSimSlotMapping",
            "android.telephony.TelephonyManager#setSimSlotMapping"})
    public void testSimSlotMapping() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
        InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .adoptShellPermissionIdentity(
                        android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
        Collection<UiccSlotMapping> simSlotMapping = mTelephonyManager.getSimSlotMapping();
        // passing slotMapping combination
        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .adoptShellPermissionIdentity(android.Manifest.permission.MODIFY_PHONE_STATE);
        try {
            mTelephonyManager.setSimSlotMapping(simSlotMapping);
        } catch (IllegalArgumentException | IllegalStateException e) {
            // if HAL version is less than 2.0, vendors may not have implemented API,
            // skipping the failure.
            if (mConfigHalVersion >= RADIO_HAL_VERSION_2_0) {
                fail("Not Expected Fail, Error in setSimSlotMapping :" + e);
            }
        }

        List<UiccSlotMapping> slotMappingList = new ArrayList<>();
        // invalid logicalSlotIndex - Fail
        UiccSlotMapping slotMapping1 = new UiccSlotMapping(
                TelephonyManager.DEFAULT_PORT_INDEX, /*portIndex*/
                1, /*physicalSlotIndex*/
                SubscriptionManager.INVALID_PHONE_INDEX /*logicalSlotIndex*/);
        UiccSlotMapping slotMapping2 = new UiccSlotMapping(
                TelephonyManager.DEFAULT_PORT_INDEX, /*portIndex*/
                0, /*physicalSlotIndex*/
                0 /*logicalSlotIndex*/);
        slotMappingList.add(slotMapping1);
        slotMappingList.add(slotMapping2);
        try {
            mTelephonyManager.setSimSlotMapping(slotMappingList);
            fail("Expected IllegalStateException, invalid UiccSlotMapping data found");
        } catch (IllegalStateException e) {
            //expected
        }
        slotMappingList.clear();

        // Duplicate logicalSlotIndex - Fail
        UiccSlotMapping slotMapping3 = new UiccSlotMapping(
                TelephonyManager.DEFAULT_PORT_INDEX, /*portIndex*/
                1, /*physicalSlotIndex*/
                0 /*logicalSlotIndex*/);
        UiccSlotMapping slotMapping4 = new UiccSlotMapping(
                TelephonyManager.DEFAULT_PORT_INDEX, /*portIndex*/
                0, /*physicalSlotIndex*/
                0 /*logicalSlotIndex*/);
        slotMappingList.add(slotMapping3);
        slotMappingList.add(slotMapping4);
        try {
            mTelephonyManager.setSimSlotMapping(slotMappingList);
            fail("Expected IllegalArgumentException, Duplicate UiccSlotMapping data found");
        } catch (IllegalArgumentException e) {
            //expected
        }
        slotMappingList.clear();

        // Duplicate {portIndex+physicalSlotIndex} - Fail
        UiccSlotMapping slotMapping5 = new UiccSlotMapping(
                TelephonyManager.DEFAULT_PORT_INDEX, /*portIndex*/
                1, /*physicalSlotIndex*/
                0 /*logicalSlotIndex*/);
        UiccSlotMapping slotMapping6 = new UiccSlotMapping(
                TelephonyManager.DEFAULT_PORT_INDEX, /*portIndex*/
                1, /*physicalSlotIndex*/
                1 /*logicalSlotIndex*/);
        slotMappingList.add(slotMapping5);
        slotMappingList.add(slotMapping6);
        try {
            mTelephonyManager.setSimSlotMapping(slotMappingList);
            fail("Expected IllegalArgumentException, Duplicate UiccSlotMapping data found");
        } catch (IllegalArgumentException e) {
            //expected
        }
        slotMappingList.clear();

        // Duplicate {portIndex+physicalSlotIndex+logicalSlotIndex} - Fail
        UiccSlotMapping slotMapping7 = new UiccSlotMapping(
                TelephonyManager.DEFAULT_PORT_INDEX, /*portIndex*/
                1, /*physicalSlotIndex*/
                0 /*logicalSlotIndex*/);
        UiccSlotMapping slotMapping8 = new UiccSlotMapping(
                TelephonyManager.DEFAULT_PORT_INDEX, /*portIndex*/
                1, /*physicalSlotIndex*/
                0 /*logicalSlotIndex*/);
        slotMappingList.add(slotMapping7);
        slotMappingList.add(slotMapping8);
        try {
            mTelephonyManager.setSimSlotMapping(slotMappingList);
            fail("Expected IllegalArgumentException, Duplicate UiccSlotMapping data found");
        } catch (IllegalArgumentException e) {
            //expected
        }
        slotMappingList.clear();

        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .dropShellPermissionIdentity();

    }

    @Test
    @ApiTest(apis = {"android.telephony.TelephonyManager#getUiccSlotsInfo"})
    public void getUiccSlotInfoTest() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .adoptShellPermissionIdentity(
                        android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
        UiccSlotInfo[] slotInfos = mTelephonyManager.getUiccSlotsInfo();

        if (slotInfos == null) {
            return;
        }

        // Call below methods to make sure it doesn't crash.
        for (UiccSlotInfo slotInfo : slotInfos) {
            slotInfo.getIsEuicc();
            slotInfo.getCardId();
            slotInfo.getCardStateInfo();
            slotInfo.getIsExtendedApduSupported();
            slotInfo.isRemovable();
            for (UiccPortInfo portInfo :slotInfo.getPorts()) {
                portInfo.isActive();
                portInfo.getIccId();
                portInfo.getLogicalSlotIndex();
                portInfo.getPortIndex();
            }
        }

        for (UiccSlotInfo slotInfo : slotInfos) {
            // Make sure portIndex value is less than the number of ports available.
            int count = slotInfo.getPorts().stream().filter(portInfo
                    -> portInfo.getPortIndex() >= slotInfo.getPorts().size()).toList().size();
            if (count > 0) {
                fail("port index should be less than the total number of ports available");
            }
            // Make sure both port indexes are unique.
            for (int index = 0; index < slotInfo.getPorts().size(); index++) {
                final int portIndex = index;
                assertEquals(1, slotInfo.getPorts().stream().filter(
                        portInfo -> portInfo.getPortIndex() == portIndex).toList().size());
            }
        }

        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .dropShellPermissionIdentity();
    }

    @Test
    public void testGetUiccSlotInfosFailsWithoutReadPhoneStatePrivilege() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
        try {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .dropShellPermissionIdentity();
            mTelephonyManager.getUiccSlotsInfo();
            fail("TelephonyManager#getUiccSlotsInfo must be protected "
                    + "with READ_PRIVILEGED_PHONE_STATE");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void getSimSlotMappingTestReadPermission() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        try {
            Collection<UiccSlotMapping> simSlotMapping = mTelephonyManager.getSimSlotMapping();
            fail("Expected SecurityException, no READ_PRIVILEGED_PHONE_STATE permission");
        } catch (SecurityException e) {
            // expected
        }
    }

    @Test
    public void testSetAllowedNetworkTypesForReason_ignoreInvalidNetworkType() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        // NETWORK_TYPE_BITMASK_LTE_CA is invalid, should be converted into NETWORK_TYPE_BITMASK_LTE
        long invalidAllowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_LTE
                | TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
        long expectedAllowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
        try {
            mIsAllowedNetworkTypeChanged = true;
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                    mTelephonyManager,
                    (tm) -> tm.setAllowedNetworkTypesForReason(
                            TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER,
                            invalidAllowedNetworkTypes));

            long deviceAllowedNetworkTypes = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> {
                        return tm.getAllowedNetworkTypesForReason(
                                TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER);
                    }
            );
            assertEquals(expectedAllowedNetworkTypes, deviceAllowedNetworkTypes);
        } catch (SecurityException se) {
            fail("testIgnoreInvalidNetworkType: SecurityException not expected");
        }
    }

    @Test
    @ApiTest(apis = {"android.telephony.TelephonyManager#getSimSlotMapping"})
    public void getSimSlotMappingTest() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));

        InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .adoptShellPermissionIdentity(
                        android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
        try {
            Collection<UiccSlotMapping> simSlotMapping = mTelephonyManager.getSimSlotMapping();
            assertTrue(isSlotMappingValid(simSlotMapping));
        } catch (IllegalArgumentException e) {
            fail("IllegalArgumentException, Duplicate UiccSlotMapping data found");
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .dropShellPermissionIdentity();
        }
    }
    private static boolean isSlotMappingValid(@NonNull Collection<UiccSlotMapping> slotMapping) {
        // Grouping the collection by logicalSlotIndex, finding different entries mapping to the
        // same logical slot
        Map<Integer, List<UiccSlotMapping>> slotMappingInfo = slotMapping.stream().collect(
                Collectors.groupingBy(UiccSlotMapping::getLogicalSlotIndex));
        for (Map.Entry<Integer, List<UiccSlotMapping>> entry : slotMappingInfo.entrySet()) {
            List<UiccSlotMapping> logicalSlotMap = entry.getValue();
            if (logicalSlotMap.size() > 1) {
                // duplicate logicalSlotIndex found
                return false;
            }
        }
        return true;
    }

    public static class ServiceStateRadioStateListener extends TelephonyCallback
            implements TelephonyCallback.ServiceStateListener,
            TelephonyCallback.RadioPowerStateListener {
        private static final long TIMEOUT_TO_WAIT_FOR_DESIRED_STATE =
                TimeUnit.SECONDS.toMillis(20);
        private final Object mPowerStateLock = new Object();
        private final Object mServiceStateLock = new Object();
        ServiceState mServiceState;
        int mDesireServiceState;

        int mRadioPowerState;
        int mDesireRadioPowerState;

        public ServiceStateRadioStateListener(ServiceState serviceState, int radioPowerState) {
            mServiceState = serviceState;
            mRadioPowerState = radioPowerState;
            mDesireRadioPowerState = radioPowerState;
        }

        @Override
        public void onServiceStateChanged(ServiceState ss) {
            Log.d(TAG, "onServiceStateChanged to " + ss);
            synchronized (mServiceStateLock) {
                mServiceState = ss;
                if (ss.getState() == mDesireServiceState) {
                    mServiceStateLock.notify();
                }
            }
        }

        @Override
        public void onRadioPowerStateChanged(int radioState) {
            Log.d(TAG, "onRadioPowerStateChanged to " + radioState);
            synchronized (mPowerStateLock) {
                mRadioPowerState = radioState;
                if (radioState == mDesireRadioPowerState) {
                    mPowerStateLock.notify();
                }
            }
        }

        public void waitForRadioStateIntent(int desiredRadioState) {
            Log.d(TAG, "waitForRadioStateIntent: desiredRadioState=" + desiredRadioState);
            synchronized (mPowerStateLock) {
                mDesireRadioPowerState = desiredRadioState;
                /**
                 * Since SST sets waiting time up to 10 seconds for the power off radio, the
                 * RadioStateIntent timer extends the wait time up to 20 seconds here as well.
                 */
                waitForDesiredState(mPowerStateLock, desiredRadioState,
                        () -> mRadioPowerState, true);
            }
        }

        public void waitForServiceStateIntent(int desiredServiceState, boolean failOnTimeOut) {
            Log.d(TAG, "waitForServiceStateIntent: desiredServiceState=" + desiredServiceState);
            synchronized (mServiceStateLock) {
                mDesireServiceState = desiredServiceState;
                waitForDesiredState(mServiceStateLock, desiredServiceState,
                        () -> mServiceState.getState(), failOnTimeOut);
            }
        }

        private void waitForDesiredState(@NonNull Object lock, int desiredState,
                @NonNull IntSupplier currentStateSupplier, boolean failOnTimeOut) {
            synchronized (lock) {
                long now = SystemClock.elapsedRealtime();
                long deadline = now + TIMEOUT_TO_WAIT_FOR_DESIRED_STATE;
                while (currentStateSupplier.getAsInt() != desiredState && now < deadline) {
                    try {
                        lock.wait(TIMEOUT_TO_WAIT_FOR_DESIRED_STATE);
                    } catch (Exception e) {
                        if (failOnTimeOut) {
                            fail(e.getMessage());
                        } else {
                            Log.w(TAG, "waitForDesiredState: e=" + e);
                        }
                    }
                    now = SystemClock.elapsedRealtime();
                }
            }
        }
    }

    @Test
    public void testSetVoiceServiceStateOverride() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_CALLING));
        ServiceStateRadioStateListener callback = new ServiceStateRadioStateListener(
                mTelephonyManager.getServiceState(), mTelephonyManager.getRadioPowerState());
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.registerTelephonyCallback(Runnable::run, callback));

        boolean turnedRadioOff = false;
        boolean setServiceStateOverride = false;
        try {
            if (mTelephonyManager.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) {
                Log.i(TAG, "testSetVoiceServiceStateOverride: turning radio off to force OOS");
                ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                        tm -> tm.setRadioPower(false), permission.MODIFY_PHONE_STATE);
                callback.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_OFF);
                callback.waitForServiceStateIntent(ServiceState.STATE_POWER_OFF, true);
                assertEquals(TelephonyManager.RADIO_POWER_OFF, callback.mRadioPowerState);
                assertEquals(ServiceState.STATE_POWER_OFF, callback.mServiceState.getState());
                turnedRadioOff = true;
            }
            // This could be OUT_OF_SERVICE or POWER_OFF, it doesn't really matter for this test as
            // long as it's not IN_SERVICE
            ServiceState serviceState = mTelephonyManager.getServiceState();
            int retry = 0;
            while ((serviceState == null
                    || serviceState.getState() == ServiceState.STATE_IN_SERVICE) && retry < 3) {
                serviceState = mTelephonyManager.getServiceState();
                retry++;
                // wait up to 3s for radio power off/out of service
                waitForMs(1000);
            }
            int originalServiceState = serviceState != null ? serviceState.getState()
                    : callback.mServiceState.getState();
            Log.i(TAG, "testSetVoiceServiceStateOverride: originalSS = " + originalServiceState);
            assertNotEquals(ServiceState.STATE_IN_SERVICE, originalServiceState);

            // Telecom will sometimes remove the override after radio reboots.
            // Retry setting the override to prevent flaky test failures.
            int listenerState = callback.mServiceState.getState();
            int telephonyManagerState = originalServiceState;
            retry = 0;
            while ((listenerState != ServiceState.STATE_IN_SERVICE
                    || telephonyManagerState != ServiceState.STATE_IN_SERVICE) && retry < 3) {
                // We should see the override in both ServiceStateListener and getServiceState
                ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                        tm -> tm.setVoiceServiceStateOverride(true),
                        permission.BIND_TELECOM_CONNECTION_SERVICE);
                callback.waitForServiceStateIntent(ServiceState.STATE_IN_SERVICE, false);
                setServiceStateOverride = true;

                serviceState = mTelephonyManager.getServiceState();
                if (serviceState != null) {
                    telephonyManagerState = serviceState.getState();
                }
                listenerState = callback.mServiceState.getState();
                retry++;
            }
            assertEquals(ServiceState.STATE_IN_SERVICE, listenerState);
            assertEquals(ServiceState.STATE_IN_SERVICE, telephonyManagerState);

            // When we take away the override, things flip back to the original state since there
            // were no other material changes made to the device that would impact ServiceState
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                    tm -> tm.setVoiceServiceStateOverride(false),
                    permission.BIND_TELECOM_CONNECTION_SERVICE);
            callback.waitForServiceStateIntent(originalServiceState, true);
            assertEquals(originalServiceState, callback.mServiceState.getState());
            assertEquals(originalServiceState, mTelephonyManager.getServiceState().getState());
        } finally {
            if (setServiceStateOverride) {
                // No harm in calling this again if we already did, but call just in case we failed
                // an assertion related to setOverride(true)
                ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                        tm -> tm.setVoiceServiceStateOverride(false),
                        permission.BIND_TELECOM_CONNECTION_SERVICE);
            }
            if (turnedRadioOff) {
                // Turn the radio back on and wait for ServiceState to become stable again, so we
                // don't cause flakes in other tests
                Log.i(TAG, "testSetVoiceServiceStateOverride: turning radio back on");
                ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                        tm -> tm.setRadioPower(true), permission.MODIFY_PHONE_STATE);
                callback.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_ON);
                callback.waitForServiceStateIntent(ServiceState.STATE_IN_SERVICE, true);
                assertEquals(TelephonyManager.RADIO_POWER_ON, callback.mRadioPowerState);
                assertEquals(ServiceState.STATE_IN_SERVICE, callback.mServiceState.getState());
            }
        }
    }

    @Test
    @ApiTest(apis = {
            "android.telephony.TelephonyManager#requestRadioPowerOffForReason",
            "android.telephony.TelephonyManager#clearRadioPowerOffForReason",
            "android.telephony.TelephonyManager#getRadioPowerOffReasons"})
    public void testSetRadioPowerForReasonNearbyDevice() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
        ServiceStateRadioStateListener callback = new ServiceStateRadioStateListener(
                mTelephonyManager.getServiceState(), mTelephonyManager.getRadioPowerState());
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.registerTelephonyCallback(Runnable::run, callback));

        boolean turnedRadioOn = false;
        if (mTelephonyManager.getRadioPowerState() == TelephonyManager.RADIO_POWER_OFF) {
            Log.i(TAG, "testSetRadioPowerForReasonNearbyDevice:"
                    + "turning on radio since it is off");
            turnRadioOn(callback, TelephonyManager.RADIO_POWER_REASON_USER);
            assertEquals(TelephonyManager.RADIO_POWER_ON, callback.mRadioPowerState);
            turnedRadioOn = true;
        }

        Log.i(TAG, "testSetRadioPowerForReasonNearbyDevice:"
                + "turning radio off due to nearby device ...");
        turnRadioOff(callback, TelephonyManager.RADIO_POWER_REASON_NEARBY_DEVICE);
        assertRadioOffWithReason(callback, TelephonyManager.RADIO_POWER_REASON_NEARBY_DEVICE);

        Log.i(TAG, "testSetRadioPowerForReasonNearbyDevice: turning on airplane mode ...");
        turnRadioOff(callback, TelephonyManager.RADIO_POWER_REASON_USER);
        assertRadioOffWithReason(callback, TelephonyManager.RADIO_POWER_REASON_USER);

        Log.i(TAG, "testSetRadioPowerForReasonNearbyDevice: turning off airplane mode ...");
        turnRadioOn(callback, TelephonyManager.RADIO_POWER_REASON_USER);
        assertRadioOffWithReason(callback, TelephonyManager.RADIO_POWER_REASON_NEARBY_DEVICE);

        Log.i(TAG, "testSetRadioPowerForReasonNearbyDevice:"
                + " turning on radio due to nearby device...");
        turnRadioOn(callback, TelephonyManager.RADIO_POWER_REASON_NEARBY_DEVICE);
        assertEquals(TelephonyManager.RADIO_POWER_ON, callback.mRadioPowerState);

        if (turnedRadioOn) {
            Log.i(TAG, "testSetRadioPowerForReasonNearbyDevice: turning radio back off");
            turnRadioOff(callback, TelephonyManager.RADIO_POWER_REASON_USER);
            assertRadioOffWithReason(callback, TelephonyManager.RADIO_POWER_REASON_USER);
        }
    }

    @Test
    @ApiTest(apis = {
            "android.telephony.TelephonyManager#requestRadioPowerOffForReason",
            "android.telephony.TelephonyManager#clearRadioPowerOffForReason",
            "android.telephony.TelephonyManager#getRadioPowerOffReasons",
            "android.telephony.TelephonyManager#setRadioEnabled"})
    public void testSetRadioPowerForReasonCarrier() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
        ServiceStateRadioStateListener callback = new ServiceStateRadioStateListener(
                mTelephonyManager.getServiceState(), mTelephonyManager.getRadioPowerState());
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.registerTelephonyCallback(Runnable::run, callback));

        boolean turnedRadioOn = false;
        if (mTelephonyManager.getRadioPowerState() == TelephonyManager.RADIO_POWER_OFF) {
            Log.i(TAG, "testSetRadioPowerForReasonCarrier: turning on radio since it is off");
            turnRadioOn(callback, TelephonyManager.RADIO_POWER_REASON_USER);
            assertEquals(TelephonyManager.RADIO_POWER_ON, callback.mRadioPowerState);
            turnedRadioOn = true;
        }

        Log.i(TAG, "testSetRadioPowerForReasonCarrier: turning radio off due to carrier ...");
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setRadioEnabled(false), permission.MODIFY_PHONE_STATE);
        callback.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_OFF);
        assertRadioOffWithReason(callback, TelephonyManager.RADIO_POWER_REASON_CARRIER);

        Log.i(TAG, "testSetRadioPowerForReasonCarrier: turning on airplane mode ...");
        turnRadioOff(callback, TelephonyManager.RADIO_POWER_REASON_USER);
        assertRadioOffWithReason(callback, TelephonyManager.RADIO_POWER_REASON_CARRIER);

        Log.i(TAG, "testSetRadioPowerForReasonCarrier: turning off airplane mode ...");
        turnRadioOn(callback, TelephonyManager.RADIO_POWER_REASON_USER);
        assertRadioOffWithReason(callback, TelephonyManager.RADIO_POWER_REASON_CARRIER);

        Log.i(TAG, "testSetRadioPowerForReasonCarrier: turning on radio due to carrier...");
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.setRadioEnabled(true), permission.MODIFY_PHONE_STATE);
        callback.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_ON);
        assertEquals(TelephonyManager.RADIO_POWER_ON, callback.mRadioPowerState);

        if (turnedRadioOn) {
            Log.i(TAG, "testSetRadioPowerForReasonCarrier: turning radio back off");
            turnRadioOff(callback, TelephonyManager.RADIO_POWER_REASON_USER);
            assertRadioOffWithReason(callback, TelephonyManager.RADIO_POWER_REASON_USER);
        }
    }

    @Test
    @ApiTest(apis = {
            "android.telephony.TelephonyManager#getCellBroadcastIdRanges",
            "android.telephony.TelephonyManager#setCellBroadcastIdRanges"})
    public void testSetCellBroadcastIdRanges() throws Exception {
        final List<CellBroadcastIdRange> ranges = new ArrayList<>();
        ranges.add(new CellBroadcastIdRange(0, 999, SmsCbMessage.MESSAGE_FORMAT_3GPP, true));

        // Permission check
        assertThrows(SecurityException.class, () ->
                mTelephonyManager.getCellBroadcastIdRanges());

        assertThrows(SecurityException.class, () ->
                mTelephonyManager.setCellBroadcastIdRanges(ranges,
                        AsyncTask.SERIAL_EXECUTOR, (result) -> {}));

        final List<Integer> resultsExpected = new ArrayList<>();
        resultsExpected.add(TelephonyManager.CELL_BROADCAST_RESULT_UNKNOWN);
        resultsExpected.add(TelephonyManager.CELL_BROADCAST_RESULT_SUCCESS);
        resultsExpected.add(TelephonyManager.CELL_BROADCAST_RESULT_UNSUPPORTED);
        resultsExpected.add(TelephonyManager.CELL_BROADCAST_RESULT_FAIL_CONFIG);
        resultsExpected.add(TelephonyManager.CELL_BROADCAST_RESULT_FAIL_ACTIVATION);

        final List<CellBroadcastIdRange> rangesExpected = ShellIdentityUtils
                .invokeMethodWithShellPermissions(
                        mTelephonyManager, (tm) -> tm.getCellBroadcastIdRanges());
        CountDownLatch latch = new CountDownLatch(1);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                (tm) -> tm.setCellBroadcastIdRanges(ranges, AsyncTask.SERIAL_EXECUTOR,
                        (result) -> {
                            latch.countDown();
                            // The result must be a valid value
                            assertTrue("Got " + result + " not in expected set",
                                    resultsExpected.contains(result));
                            // The range will be updated when result is success
                            if (result == TelephonyManager.CELL_BROADCAST_RESULT_SUCCESS) {
                                rangesExpected.clear();
                                rangesExpected.addAll(ranges);
                            }
                        }));
        assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
        List<CellBroadcastIdRange> ranges2 = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager, (tm) -> tm.getCellBroadcastIdRanges());

        assertEquals(rangesExpected, ranges2);

        ranges.add(new CellBroadcastIdRange(999, 999, SmsCbMessage.MESSAGE_FORMAT_3GPP, false));
        assertThrows(IllegalArgumentException.class, () ->
                ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                        (tm) -> tm.setCellBroadcastIdRanges(ranges, null, null)));
    }

    private void turnRadioOn(ServiceStateRadioStateListener callback, int reason) {
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.clearRadioPowerOffForReason(reason), permission.MODIFY_PHONE_STATE);
        callback.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_ON);
    }

    private void turnRadioOff(ServiceStateRadioStateListener callback, int reason) {
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.requestRadioPowerOffForReason(reason), permission.MODIFY_PHONE_STATE);
        callback.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_OFF);
    }

    private void assertRadioOffWithReason(ServiceStateRadioStateListener callback, int reason) {
        assertEquals(TelephonyManager.RADIO_POWER_OFF, callback.mRadioPowerState);

        Set<Integer> radioPowerOffReasons = ShellIdentityUtils.invokeMethodWithShellPermissions(
                mTelephonyManager,
                tm -> tm.getRadioPowerOffReasons(), permission.READ_PRIVILEGED_PHONE_STATE);
        assertTrue(radioPowerOffReasons.contains(reason));
    }

    private void assertRadioOffWithReason(TelephonyManager telephonyManager,
            ServiceStateRadioStateListener callback, int reason) {
        assertEquals(TelephonyManager.RADIO_POWER_OFF, callback.mRadioPowerState);

        Set<Integer> radioPowerOffReasons = ShellIdentityUtils.invokeMethodWithShellPermissions(
                telephonyManager,
                tm -> tm.getRadioPowerOffReasons(), permission.READ_PRIVILEGED_PHONE_STATE);
        assertTrue(radioPowerOffReasons.contains(reason));
    }

    /**
     * Verifies that {@link TelephonyManager#getImsPrivateUserIdentity()} does not throw any
     * exception when called and has the correct permissions.
     */
    @Ignore("TelephonyManager#getImsPrivateUserIdentity()" + " is hidden. Internal use only.")
    @Test
    public void getImsPrivateUserIdentity() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
        // make sure not to face any permission problem while calling the API
        try {
            setAppOpsPermissionAllowed(true, OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER);
            mTelephonyManager.getImsPrivateUserIdentity();
        } catch (IllegalStateException e) {
            // expected in case SIM do not support ISIM
        } catch (SecurityException secExp) {
            fail();
        } finally {
            setAppOpsPermissionAllowed(false, OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER);
        }
    }

    /**
     * Verifies that {@link TelephonyManager#getImsPrivateUserIdentity()} does throw
     * SecurityException when required permissions are not granted.
     */
    @Ignore("TelephonyManager#getImsPrivateUserIdentity()" + " is hidden. Internal use only.")
    @Test
    public void getImsPrivateUserIdentity_NoPermissionGranted() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
        try {
            mTelephonyManager.getImsPrivateUserIdentity();
            fail(); // if no SecurityException then it fails()
        } catch (IllegalStateException e) {
            // expected in case SIM do not support ISIM
        } catch (SecurityException secExp) {
            // expected as API has no permission to fetch ISIM
        }
    }

    /**
     * Verifies that {@link TelephonyManager#getImsPublicUserIdentities()} does not throw any
     * exception when granted with READ_PRIVILEGED_PHONE_STATE permission.
     */
    @Ignore("TelephonyManager#getImsPublicUserIdentities()" + " is hidden. Internal use only.")
    @Test
    public void getImsPublicUserIdentities_ReadPrivilegedPermission() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
        // make sure not to face any permission problem while calling the API
        try {
            List<Uri> impuList = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, tm -> tm.getImsPublicUserIdentities(),
                    Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
            assertNotNull(impuList);
            for (Uri impu : impuList) {
                assertTrue(impu.getScheme().equalsIgnoreCase("sip"));
            }
        } catch (IllegalStateException e) {
            // expected in case SIM do not support ISIM
            fail();
        }
    }

    /**
     * Verifies that {@link TelephonyManager#getImsPublicUserIdentities()} does not throw any
     * exception when granted with READ_PHONE_NUMBERS permission.
     */
    @Ignore("TelephonyManager#getImsPublicUserIdentities()" + " is hidden. Internal use only.")
    @Test
    public void getImsPublicUserIdentities_ReadPhoneNumberPermission() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
        // make sure not to face any permission problem while calling the API
        try {
            List<Uri> impuList = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, tm -> tm.getImsPublicUserIdentities(),
                    Manifest.permission.READ_PHONE_NUMBERS);
            assertNotNull(impuList);
            for (Uri impu : impuList) {
                assertTrue(impu.getScheme().equalsIgnoreCase("sip"));
            }
        } catch (IllegalStateException e) {
            // expected in case SIM do not support ISIM
        }
    }

    /**
     * Verifies that {@link TelephonyManager#getImsPublicUserIdentities()} does throw
     * SecurityException when called with out any permissions granted.
     */
    @Ignore("TelephonyManager#getImsPublicUserIdentities()" + " is hidden. Internal use only.")
    @Test
    public void getImsPublicUserIdentities_NoPermissionGranted() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
        try {
            if (hasReadContactsPermission(mSelfPackageName)) {
                InstrumentationRegistry.getInstrumentation().getUiAutomation().
                        revokeRuntimePermission(mSelfPackageName,
                                "android.permission.READ_PHONE_NUMBERS");
            }
            List<Uri> impuList = mTelephonyManager.getImsPublicUserIdentities();
            fail(); // if no SecurityException then it fails()
        } catch (IllegalStateException e) {
            // expected in case SIM do not support ISIM
        } catch (SecurityException secExp) {
            // expected as caller is not granted with required permissions
        }
    }

    private boolean hasReadContactsPermission(String pkgName) {
        return mPackageManager.checkPermission(Manifest.permission.READ_CONTACTS, pkgName)
                == PackageManager.PERMISSION_GRANTED;
    }

    @Test
    public void testLastKnownCountryIso() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));

        CountryChangedReceiver countryChangedReceiver = new CountryChangedReceiver();

        getContext().registerReceiver(countryChangedReceiver,
                new IntentFilter(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED),
                Context.RECEIVER_EXPORTED);

        ServiceStateRadioStateListener callback = new ServiceStateRadioStateListener(
                mTelephonyManager.getServiceState(), mTelephonyManager.getRadioPowerState());
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.registerTelephonyCallback(Runnable::run, callback));

        int initialRadioState = mTelephonyManager.getRadioPowerState();
        try {
            if (initialRadioState == TelephonyManager.RADIO_POWER_OFF) {
                Log.i(TAG, "testLastKnownCountryIso:"
                        + "turning on radio since it is off");
                turnRadioOn(callback, TelephonyManager.RADIO_POWER_REASON_USER);
                assertEquals(TelephonyManager.RADIO_POWER_ON, callback.mRadioPowerState);
            }

            String countryCode = mTelephonyManager.getNetworkCountryIso();
            if (TextUtils.isEmpty(countryCode)) {
                Log.i(TAG, "testLastKnownCountryIso: country iso is already known. Not testable.");
                // Not testable.
                return;
            }

            Log.i(TAG, "testLastKnownCountryIso:"
                    + "turning radio off due to testing last known country ...");
            turnRadioOff(callback, TelephonyManager.RADIO_POWER_REASON_USER);
            try {
                countryChangedReceiver.waitForIntent();
                assertThat(countryChangedReceiver.getExtras().getString(
                        TelephonyManager.EXTRA_NETWORK_COUNTRY)).isEmpty();
                assertThat(countryChangedReceiver.getExtras().getString(
                        TelephonyManager.EXTRA_LAST_KNOWN_NETWORK_COUNTRY)).isEqualTo(countryCode);
                Log.i(TAG, "testLastKnownCountryIso: country code \"" + countryCode
                        + "\" matched.");
            } catch (Exception e) {
                fail(e.getMessage());
            }
        } finally {
            if (initialRadioState == TelephonyManager.RADIO_POWER_OFF
                    && mTelephonyManager.getRadioPowerState() != TelephonyManager.RADIO_POWER_OFF) {
                Log.i(TAG, "testLastKnownCountryIso: turning radio back off");
                turnRadioOff(callback, TelephonyManager.RADIO_POWER_REASON_USER);
            } else if (initialRadioState == TelephonyManager.RADIO_POWER_ON
                    && mTelephonyManager.getRadioPowerState() != TelephonyManager.RADIO_POWER_ON) {
                Log.i(TAG, "testLastKnownCountryIso: turning radio back on");
                turnRadioOn(callback, TelephonyManager.RADIO_POWER_REASON_USER);
            }
            getContext().unregisterReceiver(countryChangedReceiver);
        }
    }

    private static class CarrierInfo {
        final private int mCallerCarrierId;
        final private List<String> mSHAIdList;

        public CarrierInfo(int carrierId, List<String> SHAIds) {
            mCallerCarrierId = carrierId;
            mSHAIdList = SHAIds;
        }

        public int getCallerCarrierId() {
            return mCallerCarrierId;
        }

        public List<String> getSHAIdList() {
            return mSHAIdList;
        }
    }

    private static final String CALLER_SHA_1_ID = "callerSHA1Id";
    private static final String CALLER_CARRIER_ID = "carrierId";
    private CarrierInfo parseJsonForCallerInfo(String callerPackage, JSONObject dataJson) {
        try {
            if (dataJson != null && callerPackage != null) {
                JSONObject callerJSON = dataJson.getJSONObject(callerPackage.trim());
                JSONArray callerJSONArray = callerJSON.getJSONArray(CALLER_SHA_1_ID);
                int carrierId = callerJSON.getInt(CALLER_CARRIER_ID);
                List<String> appSignatures = new ArrayList<>();
                for (int index = 0; index < callerJSONArray.length(); index++) {
                    appSignatures.add((String) callerJSONArray.get(index));
                }
                return new CarrierInfo(carrierId, appSignatures);
            }
        } catch (JSONException ex) {
            Log.e(TAG, "getCallerSignatureInfo: JSONException = " + ex);
        }
        return null;
    }

    @Test
    public void testCarrierRestrictionStatusAllowList() throws JSONException {
        JSONObject testJson = new JSONObject(CARRIER_RESTRICTION_OPERATOR_DETAILS);
        Set<String> testPkgSet = testJson.keySet();
        testPkgSet.remove("_comment");
        for (String srcPkg : testPkgSet) {
            final CarrierInfo testCarrierInfo = parseJsonForCallerInfo(srcPkg, testJson);
            List<String> shaIdList = ShellIdentityUtils.invokeMethodWithShellPermissions(
                    mTelephonyManager, (tm) -> tm.getShaIdFromAllowList(srcPkg,
                            testCarrierInfo.mCallerCarrierId));

            if (shaIdList == null || shaIdList.isEmpty()) {
                Log.d(TAG, "shaIdList is empty");
                fail();
            }
            assertTrue(shaIdList.equals(testCarrierInfo.getSHAIdList()));
        }
    }

    @Test
    @ApiTest(apis = {
            "android.telephony.TelephonyManager#requestRadioPowerOffForReason",
            "android.telephony.TelephonyManager#clearRadioPowerOffForReason",
            "android.telephony.TelephonyManager#getRadioPowerOffReasons"})
    public void testSetRadioPowerForMultiSimDevice() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
        if (mTelephonyManager.isMultiSimSupported() != TelephonyManager.MULTISIM_ALLOWED) {
            Log.d(TAG, "testSetRadioPowerForMultiSimDevice: Multi SIM is not supported");
            return;
        }
        Integer secondTestSubId = getSecondTestSubId();
        if (secondTestSubId == null) {
            Log.d(TAG, "Need at least 2 active subscriptions to run this test");
            return;
        }
        Log.d(TAG, "testSetRadioPowerForMultiSimDevice: secondTestSubId=" + secondTestSubId);

        TelephonyManager secondTelephonyManager = getContext().getSystemService(
                TelephonyManager.class).createForSubscriptionId(secondTestSubId);
        ServiceStateRadioStateListener callbackForFirstSub = new ServiceStateRadioStateListener(
                mTelephonyManager.getServiceState(), mTelephonyManager.getRadioPowerState());
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                tm -> tm.registerTelephonyCallback(Runnable::run, callbackForFirstSub));
        ServiceStateRadioStateListener callbackForSecondSub =
                new ServiceStateRadioStateListener(secondTelephonyManager.getServiceState(),
                        secondTelephonyManager.getRadioPowerState());
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(secondTelephonyManager,
                tm -> tm.registerTelephonyCallback(Runnable::run, callbackForSecondSub));

        boolean turnedRadioOn = false;
        if (mTelephonyManager.getRadioPowerState() == TelephonyManager.RADIO_POWER_OFF) {
            Log.i(TAG, "testSetRadioPowerForMultiSimDevice:"
                    + "turning on radio since it is off");
            turnRadioOn(callbackForFirstSub, TelephonyManager.RADIO_POWER_REASON_USER);
            assertEquals(TelephonyManager.RADIO_POWER_ON, callbackForFirstSub.mRadioPowerState);
            callbackForSecondSub.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_ON);
            assertEquals(TelephonyManager.RADIO_POWER_ON, callbackForSecondSub.mRadioPowerState);
            turnedRadioOn = true;
        }

        Log.i(TAG, "testSetRadioPowerForMultiSimDevice:"
                + "turning radio off due to nearby device ...");
        turnRadioOff(callbackForFirstSub, TelephonyManager.RADIO_POWER_REASON_NEARBY_DEVICE);
        assertRadioOffWithReason(callbackForFirstSub,
                TelephonyManager.RADIO_POWER_REASON_NEARBY_DEVICE);
        callbackForSecondSub.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_OFF);
        assertRadioOffWithReason(secondTelephonyManager, callbackForSecondSub,
                TelephonyManager.RADIO_POWER_REASON_NEARBY_DEVICE);

        Log.i(TAG, "testSetRadioPowerForMultiSimDevice: turning on airplane mode ...");
        turnRadioOff(callbackForFirstSub, TelephonyManager.RADIO_POWER_REASON_USER);
        assertRadioOffWithReason(callbackForFirstSub, TelephonyManager.RADIO_POWER_REASON_USER);
        callbackForSecondSub.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_OFF);
        assertRadioOffWithReason(secondTelephonyManager, callbackForSecondSub,
                TelephonyManager.RADIO_POWER_REASON_USER);

        Log.i(TAG, "testSetRadioPowerForMultiSimDevice: turning off airplane mode ...");
        turnRadioOn(callbackForFirstSub, TelephonyManager.RADIO_POWER_REASON_USER);
        assertRadioOffWithReason(callbackForFirstSub,
                TelephonyManager.RADIO_POWER_REASON_NEARBY_DEVICE);
        assertRadioOffWithReason(secondTelephonyManager, callbackForSecondSub,
                TelephonyManager.RADIO_POWER_REASON_NEARBY_DEVICE);

        Log.i(TAG, "testSetRadioPowerForMultiSimDevice:"
                + " turning on radio due to nearby device...");
        turnRadioOn(callbackForFirstSub, TelephonyManager.RADIO_POWER_REASON_NEARBY_DEVICE);
        assertEquals(TelephonyManager.RADIO_POWER_ON, callbackForFirstSub.mRadioPowerState);
        callbackForSecondSub.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_ON);
        assertEquals(TelephonyManager.RADIO_POWER_ON, callbackForSecondSub.mRadioPowerState);

        if (turnedRadioOn) {
            Log.i(TAG, "testSetRadioPowerForMultiSimDevice: turning radio back off");
            turnRadioOff(callbackForFirstSub, TelephonyManager.RADIO_POWER_REASON_USER);
            callbackForSecondSub.waitForRadioStateIntent(TelephonyManager.RADIO_POWER_OFF);
        }
    }

    @Test
    @ApiTest(apis = {
            "android.telephony.TelephonyManager#isCellularIdentifierDisclosureNotificationEnabled",
            "android.telephony.TelephonyManager#enableCellularIdentifierDisclosureNotifications"})
    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY)
    public void testEnableCellularIdentifierDisclosureNotifications() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
        if (mNetworkHalVersion < RADIO_HAL_VERSION_2_2) {
            Log.d(TAG,
                    "Skipping test since modem does not support IRadioNetwork HAL v2.2");
            return;
        }

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                (tm) -> tm.enableCellularIdentifierDisclosureNotifications(true));
        boolean enabled = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.isCellularIdentifierDisclosureNotificationEnabled());
        assertTrue(enabled);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                (tm) -> tm.enableCellularIdentifierDisclosureNotifications(false));
        enabled = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                (tm) -> tm.isCellularIdentifierDisclosureNotificationEnabled());
        assertFalse(enabled);
    }

    @Test
    @ApiTest(apis = {
            "android.telephony.TelephonyManager#isCellularIdentifierDisclosureNotificationEnabled",
            "android.telephony.TelephonyManager#enableCellularIdentifierDisclosureNotifications"})
    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY)
    public void testCellularIdentifierDisclosureNotificationsPermissions() {
        assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
        if (mNetworkHalVersion < RADIO_HAL_VERSION_2_2) {
            Log.d(TAG,
                    "Skipping test since modem does not support IRadioNetwork HAL v2.2");
            return;
        }

        assertThrows(SecurityException.class, () -> {
                    mTelephonyManager.enableCellularIdentifierDisclosureNotifications(true);
                }
        );

        assertThrows(SecurityException.class, () -> {
                    mTelephonyManager.isCellularIdentifierDisclosureNotificationEnabled();
                }
        );
    }

    private Integer getSecondTestSubId() {
        try {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .adoptShellPermissionIdentity(
                            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
            for (int subId : mSubscriptionManager.getActiveSubscriptionIdList()) {
                if (subId != mTestSub) {
                    return subId;
                }
            }
        } catch (SecurityException e) {
            fail("SubscriptionManager#getActiveSubscriptionIdList requires "
                    + "READ_PRIVILEGED_PHONE_STATE");
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .dropShellPermissionIdentity();
        }
        return null;
    }
}
