Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0392dca5 authored by joonhunshin's avatar joonhunshin
Browse files

Enforce map the telephony features with APIs in

EuiccCardController, EuiccController

If the required telephony feature is not defined, throw
UnsupportedOperationException

Bug: 297989574
Test: atest EuiccCardControllerTest EuiccControllerTest
Change-Id: Ib8596952fb30ee90f34b77ca7330c04a68610086
parent 326f7107
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -215,8 +215,8 @@ public class PhoneFactory {

                if (context.getPackageManager().hasSystemFeature(
                        PackageManager.FEATURE_TELEPHONY_EUICC)) {
                    sEuiccController = EuiccController.init(context);
                    sEuiccCardController = EuiccCardController.init(context);
                    sEuiccController = EuiccController.init(context, sFeatureFlags);
                    sEuiccCardController = EuiccCardController.init(context, sFeatureFlags);
                }

                for (int i = 0; i < numPhones; i++) {
+87 −5
Original line number Diff line number Diff line
@@ -16,14 +16,20 @@

package com.android.internal.telephony.euicc;

import static android.content.pm.PackageManager.FEATURE_TELEPHONY_EUICC;
import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.compat.CompatChanges;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Handler;
import android.os.RemoteException;
@@ -39,6 +45,7 @@ import android.text.TextUtils;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.UiccCard;
import com.android.internal.telephony.uicc.UiccController;
@@ -66,6 +73,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
    private SimSlotStatusChangedBroadcastReceiver mSimSlotStatusChangeReceiver;
    private EuiccController mEuiccController;
    private UiccController mUiccController;
    private FeatureFlags mFeatureFlags;
    private PackageManager mPackageManager;

    private static EuiccCardController sInstance;

@@ -87,10 +96,10 @@ public class EuiccCardController extends IEuiccCardController.Stub {
    }

    /** Initialize the instance. Should only be called once. */
    public static EuiccCardController init(Context context) {
    public static EuiccCardController init(Context context, FeatureFlags featureFlags) {
        synchronized (EuiccCardController.class) {
            if (sInstance == null) {
                sInstance = new EuiccCardController(context);
                sInstance = new EuiccCardController(context, featureFlags);
            } else {
                Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
            }
@@ -110,8 +119,9 @@ public class EuiccCardController extends IEuiccCardController.Stub {
        return sInstance;
    }

    private EuiccCardController(Context context) {
        this(context, new Handler(), EuiccController.get(), UiccController.getInstance());
    private EuiccCardController(Context context, FeatureFlags featureFlags) {
        this(context, new Handler(), EuiccController.get(), UiccController.getInstance(),
                featureFlags);
        TelephonyFrameworkInitializer
                .getTelephonyServiceManager()
                .getEuiccCardControllerServiceRegisterer()
@@ -123,13 +133,16 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            Context context,
            Handler handler,
            EuiccController euiccController,
            UiccController uiccController) {
            UiccController uiccController,
            FeatureFlags featureFlags) {
        mContext = context;
        mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);

        mEuiccMainThreadHandler = handler;
        mUiccController = uiccController;
        mEuiccController = euiccController;
        mFeatureFlags = featureFlags;
        mPackageManager = context.getPackageManager();

        if (isBootUp(mContext)) {
            mSimSlotStatusChangeReceiver = new SimSlotStatusChangedBroadcastReceiver();
@@ -293,6 +306,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "getAllProfiles");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -342,6 +357,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "getProfile");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -390,6 +407,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "getEnabledProfile");

        String iccId = null;
        boolean isValidSlotPort = false;
        // get the iccid whether or not the port is active
@@ -474,6 +493,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "disableProfile");

        EuiccPort port = getEuiccPortFromIccId(cardId, iccid);
        if (port == null) {
            try {
@@ -522,6 +543,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "switchToProfile");

        EuiccPort port = getEuiccPort(cardId, portIndex);
        if (port == null) {
            try {
@@ -588,6 +611,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "setNickname");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -636,6 +661,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "deleteProfile");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -687,6 +714,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "resetMemory");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -738,6 +767,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "getDefaultSmdpAddress");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -786,6 +817,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "getSmdsAddress");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -834,6 +867,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "setDefaultSmdpAddress");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -882,6 +917,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "getRulesAuthTable");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -931,6 +968,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "getEuiccChallenge");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -979,6 +1018,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "getEuiccInfo1");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -1027,6 +1068,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "getEuiccInfo2");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -1076,6 +1119,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "authenticateServer");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -1126,6 +1171,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "prepareDownload");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -1175,6 +1222,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "loadBoundProfilePackage");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -1226,6 +1275,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "cancelSession");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -1274,6 +1325,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "listNotifications");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -1323,6 +1376,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "retrieveNotificationList");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -1372,6 +1427,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "retrieveNotification");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -1421,6 +1478,8 @@ public class EuiccCardController extends IEuiccCardController.Stub {
            return;
        }

        enforceTelephonyFeatureWithException(callingPackage, "removeNotificationFromList");

        EuiccPort port = getFirstActiveEuiccPort(cardId);
        if (port == null) {
            try {
@@ -1469,6 +1528,29 @@ public class EuiccCardController extends IEuiccCardController.Stub {
        Binder.restoreCallingIdentity(token);
    }

    /**
     * Make sure the device has required telephony feature
     *
     * @throws UnsupportedOperationException if the device does not have required telephony feature
     */
    private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
            @NonNull String methodName) {
        if (callingPackage == null || mPackageManager == null) {
            return;
        }

        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                Binder.getCallingUserHandle())) {
            return;
        }

        if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY_EUICC)) {
            throw new UnsupportedOperationException(
                    methodName + " is unsupported without " + FEATURE_TELEPHONY_EUICC);
        }
    }

    private static void loge(String message) {
        Log.e(TAG, message);
    }
+37 −5
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.internal.telephony.euicc;

import static android.content.pm.PackageManager.FEATURE_TELEPHONY_EUICC;
import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;

import android.Manifest;
import android.Manifest.permission;
import android.annotation.NonNull;
@@ -60,6 +63,7 @@ import com.android.internal.telephony.CarrierPrivilegesTracker;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.uicc.UiccController;
@@ -111,6 +115,7 @@ public class EuiccController extends IEuiccController.Stub {
    private final TelephonyManager mTelephonyManager;
    private final AppOpsManager mAppOpsManager;
    private final PackageManager mPackageManager;
    private final FeatureFlags mFeatureFlags;

    // These values should be set or updated upon 1) system boot, 2) EuiccService/LPA is bound to
    // the phone process, 3) values are updated remotely by server flags.
@@ -118,10 +123,10 @@ public class EuiccController extends IEuiccController.Stub {
    private List<String> mUnsupportedCountries;

    /** Initialize the instance. Should only be called once. */
    public static EuiccController init(Context context) {
    public static EuiccController init(Context context, FeatureFlags featureFlags) {
        synchronized (EuiccController.class) {
            if (sInstance == null) {
                sInstance = new EuiccController(context);
                sInstance = new EuiccController(context, featureFlags);
            } else {
                Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
            }
@@ -141,14 +146,14 @@ public class EuiccController extends IEuiccController.Stub {
        return sInstance;
    }

    private EuiccController(Context context) {
        this(context, new EuiccConnector(context));
    private EuiccController(Context context, FeatureFlags featureFlags) {
        this(context, new EuiccConnector(context), featureFlags);
        TelephonyFrameworkInitializer
                .getTelephonyServiceManager().getEuiccControllerService().register(this);
    }

    @VisibleForTesting
    public EuiccController(Context context, EuiccConnector connector) {
    public EuiccController(Context context, EuiccConnector connector, FeatureFlags featureFlags) {
        mContext = context;
        mConnector = connector;
        mSubscriptionManager = (SubscriptionManager)
@@ -157,6 +162,7 @@ public class EuiccController extends IEuiccController.Stub {
                context.getSystemService(Context.TELEPHONY_SERVICE);
        mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        mPackageManager = context.getPackageManager();
        mFeatureFlags = featureFlags;
    }

    /**
@@ -1957,6 +1963,9 @@ public class EuiccController extends IEuiccController.Stub {
    @Override
    public boolean isSimPortAvailable(int cardId, int portIndex, String callingPackage) {
        mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);

        enforceTelephonyFeatureWithException(callingPackage, "isSimPortAvailable");

        // If calling app is targeted for Android U and beyond, check for other conditions
        // to decide the port availability.
        boolean shouldCheckConditionsForInactivePort = isCompatChangeEnabled(callingPackage,
@@ -2063,4 +2072,27 @@ public class EuiccController extends IEuiccController.Stub {
                + " changeEnabled: " + changeEnabled);
        return changeEnabled;
    }

    /**
     * Make sure the device has required telephony feature
     *
     * @throws UnsupportedOperationException if the device does not have required telephony feature
     */
    private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
            @NonNull String methodName) {
        if (callingPackage == null || mPackageManager == null) {
            return;
        }

        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                Binder.getCallingUserHandle())) {
            return;
        }

        if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY_EUICC)) {
            throw new UnsupportedOperationException(
                    methodName + " is unsupported without " + FEATURE_TELEPHONY_EUICC);
        }
    }
}
+12 −12
Original line number Diff line number Diff line
@@ -146,8 +146,8 @@ public class EuiccCardControllerTest extends TelephonyTest {

    @Test
    public void testIsEmbeddedSlotActivated() {
        mEuiccCardController =
                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
        mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
                mUiccController, mFeatureFlags);
        when(mUiccController.getUiccSlots())
                .thenReturn(new UiccSlot[] {mActivatedRemovableSlot});
        assertFalse(mEuiccCardController.isEmbeddedSlotActivated());
@@ -173,8 +173,8 @@ public class EuiccCardControllerTest extends TelephonyTest {

    @Test
    public void testIsEmbeddedCardPresent() {
        mEuiccCardController =
                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
        mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
                mUiccController, mFeatureFlags);
        when(mUiccController.getUiccSlots())
                .thenReturn(new UiccSlot[] {mActivatedRemovableSlot});
        assertFalse(mEuiccCardController.isEmbeddedCardPresent());
@@ -204,8 +204,8 @@ public class EuiccCardControllerTest extends TelephonyTest {
        mSp.edit().remove(KEY_LAST_BOOT_COUNT);
        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
        when(mUiccController.getUiccSlots()).thenReturn(new UiccSlot[] {mActivatedEsimSlot});
        mEuiccCardController =
                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
        mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
                mUiccController, mFeatureFlags);

        mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
        processAllMessages();
@@ -218,8 +218,8 @@ public class EuiccCardControllerTest extends TelephonyTest {
        mSp.edit().remove(KEY_LAST_BOOT_COUNT);
        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
        when(mUiccController.getUiccSlots()).thenReturn(new UiccSlot[] {mNotPresentEsimSlot});
        mEuiccCardController =
            new EuiccCardController(mContext, null, mEuiccController, mUiccController);
        mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
                mUiccController, mFeatureFlags);

        mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
        processAllMessages();
@@ -232,8 +232,8 @@ public class EuiccCardControllerTest extends TelephonyTest {
        mSp.edit().putInt(KEY_LAST_BOOT_COUNT, 1).apply();
        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 1);
        when(mUiccController.getUiccSlots()).thenReturn(new UiccSlot[] {mActivatedEsimSlot});
        mEuiccCardController =
                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
        mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
                mUiccController, mFeatureFlags);

        mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
        processAllMessages();
@@ -247,8 +247,8 @@ public class EuiccCardControllerTest extends TelephonyTest {
        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
        when(mUiccController.getUiccSlots())
                .thenReturn(new UiccSlot[] {mActivatedRemovableSlot, mInactivatedEsimSlot});
        mEuiccCardController =
                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
        mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
                mUiccController, mFeatureFlags);

        mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
        processAllMessages();
+29 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
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.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -70,6 +71,7 @@ import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.euicc.EuiccConnector.GetOtaStatusCommandCallback;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.uicc.UiccSlot;

import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
@@ -156,8 +158,8 @@ public class EuiccControllerTest extends TelephonyTest {
        // Number of OTA status changed.
        private int mNumOtaStatusChanged;

        TestEuiccController(Context context, EuiccConnector connector) {
            super(context, connector);
        TestEuiccController(Context context, EuiccConnector connector, FeatureFlags featureFlags) {
            super(context, connector, featureFlags);
            mNumOtaStatusChanged = 0;
        }

@@ -196,7 +198,7 @@ public class EuiccControllerTest extends TelephonyTest {
        super.setUp(getClass().getSimpleName());
        mMockConnector = Mockito.mock(EuiccConnector.class);
        mUiccSlot = Mockito.mock(UiccSlot.class);
        mController = new TestEuiccController(mContext, mMockConnector);
        mController = new TestEuiccController(mContext, mMockConnector, mFeatureFlags);

        PackageInfo pi = new PackageInfo();
        pi.packageName = PACKAGE_NAME;
@@ -1294,6 +1296,30 @@ public class EuiccControllerTest extends TelephonyTest {
                SWITCH_WITHOUT_PORT_INDEX_EXCEPTION_ON_DISABLE));
    }

    @Test
    @EnableCompatChanges({EuiccManager.INACTIVE_PORT_AVAILABILITY_CHECK,
            TelephonyManager.ENABLE_FEATURE_MAPPING})
    public void testIsSimPortAvailable_WithTelephonyFeatureMapping() {
        // Feature flag enabled, device has required telephony feature.
        doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
        doReturn(true).when(mPackageManager).hasSystemFeature(
                eq(PackageManager.FEATURE_TELEPHONY_EUICC));

        setUiccCardInfos(false, true, true);

        // assert non euicc card id
        assertFalse(mController.isSimPortAvailable(REMOVABLE_CARD_ID, 0, TEST_PACKAGE_NAME));

        // assert invalid port index
        assertFalse(mController.isSimPortAvailable(CARD_ID, 5 /* portIndex */, TEST_PACKAGE_NAME));

        // Device does not have required telephony feature.
        doReturn(false).when(mPackageManager).hasSystemFeature(
                eq(PackageManager.FEATURE_TELEPHONY_EUICC));
        assertThrows(UnsupportedOperationException.class,
                () -> mController.isSimPortAvailable(REMOVABLE_CARD_ID, 0, TEST_PACKAGE_NAME));
    }

    @Test
    @EnableCompatChanges({EuiccManager.INACTIVE_PORT_AVAILABILITY_CHECK})
    public void testIsSimPortAvailable_invalidCase() {