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

Commit 02e6474e authored by Anthony Alridge's avatar Anthony Alridge
Browse files

APIs to download and delete eSIM for admins

Updates the documenation of the download and delete APIs
to reflect the ability for enterprise admins to
manage eSIMs. Also, adds a mechanism in subscription info
to track if a sim is "owned" by an admin. This can be
used across the system to determine what actions a user
can perform on the sim (e.g. by default, users cannot
delete esims).

A separate user restriction (disallow_unmanaged_sims_globally) is
being introduced in a separate cl to block the user from
adding sims. Once merged, the permission check in
downloadSubscription can be extended to only allow the download
if the admin holds the MANAGE_DEVICE_POLICY_MOBILE_NETWORKS permission,
thus blocking download for all but admins.

Bug: 293456669
Test: btest android.devicepolicy.cts.EmbeddedSubscriptionTest
API-Coverage-Bug: 322944132
Change-Id: Id228b9ac1e1a63a519c06e7b104262ba48532373
parent 328556ac
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ package android {
    field public static final String MANAGE_DEVICE_POLICY_LOCK = "android.permission.MANAGE_DEVICE_POLICY_LOCK";
    field public static final String MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS = "android.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS";
    field public static final String MANAGE_DEVICE_POLICY_LOCK_TASK = "android.permission.MANAGE_DEVICE_POLICY_LOCK_TASK";
    field @FlaggedApi("android.app.admin.flags.esim_management_enabled") public static final String MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS = "android.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS";
    field public static final String MANAGE_DEVICE_POLICY_METERED_DATA = "android.permission.MANAGE_DEVICE_POLICY_METERED_DATA";
    field public static final String MANAGE_DEVICE_POLICY_MICROPHONE = "android.permission.MANAGE_DEVICE_POLICY_MICROPHONE";
    field public static final String MANAGE_DEVICE_POLICY_MOBILE_NETWORK = "android.permission.MANAGE_DEVICE_POLICY_MOBILE_NETWORK";
@@ -8016,6 +8017,7 @@ package android.app.admin {
    method public CharSequence getStartUserSessionMessage(@NonNull android.content.ComponentName);
    method @Deprecated public boolean getStorageEncryption(@Nullable android.content.ComponentName);
    method public int getStorageEncryptionStatus();
    method @FlaggedApi("android.app.admin.flags.esim_management_enabled") @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS) public java.util.Set<java.lang.Integer> getSubscriptionsIds();
    method @Nullable public android.app.admin.SystemUpdatePolicy getSystemUpdatePolicy();
    method @Nullable public android.os.PersistableBundle getTransferOwnershipBundle();
    method @Nullable public java.util.List<android.os.PersistableBundle> getTrustAgentConfiguration(@Nullable android.content.ComponentName, @NonNull android.content.ComponentName);
@@ -46313,8 +46315,8 @@ package android.telephony.euicc {
  public class EuiccManager {
    method @NonNull public android.telephony.euicc.EuiccManager createForCardId(int);
    method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void deleteSubscription(int, android.app.PendingIntent);
    method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent);
    method @RequiresPermission(anyOf={"android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS", android.Manifest.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS}) public void deleteSubscription(int, android.app.PendingIntent);
    method @RequiresPermission(anyOf={"android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS", android.Manifest.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS}) public void downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent);
    method @FlaggedApi("com.android.internal.telephony.flags.esim_available_memory") @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE", "carrier privileges"}) public long getAvailableMemoryInBytes();
    method @Nullable public String getEid();
    method @Nullable public android.telephony.euicc.EuiccInfo getEuiccInfo();
+30 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.Manifest.permission.SET_TIME;
import static android.Manifest.permission.SET_TIME_ZONE;
import static android.app.admin.flags.Flags.FLAG_ESIM_MANAGEMENT_ENABLED;
import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
@@ -17279,4 +17280,33 @@ public class DevicePolicyManager {
    public boolean isOnboardingBugreportV2FlagEnabled() {
        return onboardingBugreportV2Enabled();
    }
    /**
     * Returns the subscription ids of all subscriptions which was downloaded by the calling
     * admin.
     *
     * <p> This returns only the subscriptions which were downloaded by the calling admin via
     *      {@link android.telephony.euicc.EuiccManager#downloadSubscription}.
     *      If a susbcription is returned by this method then in it subject to management controls
     *      and cannot be removed by users.
     *
     * <p> Callable by device owners and profile owners.
     *
     * @throws SecurityException if the caller is not authorized to call this method
     * @return ids of all managed subscriptions currently downloaded by an admin on the device
     */
    @FlaggedApi(FLAG_ESIM_MANAGEMENT_ENABLED)
    @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS)
    @NonNull
    public Set<Integer> getSubscriptionsIds() {
        throwIfParentInstance("getSubscriptionsIds");
        if (mService != null) {
            try {
                return intArrayToSet(mService.getSubscriptionIds(mContext.getPackageName()));
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return new HashSet<>();
    }
}
 No newline at end of file
+2 −0
Original line number Diff line number Diff line
@@ -613,4 +613,6 @@ interface IDevicePolicyManager {

    void setContentProtectionPolicy(in ComponentName who, String callerPackageName, int policy);
    int getContentProtectionPolicy(in ComponentName who, String callerPackageName);

    int[] getSubscriptionIds(String callerPackageName);
}
+7 −0
Original line number Diff line number Diff line
@@ -3799,6 +3799,13 @@
    <permission android:name="android.permission.MANAGE_DEVICE_POLICY_CONTENT_PROTECTION"
                android:protectionLevel="internal|role" />

    <!-- Allows an application to set policy related to subscriptions downloaded by an admin.
        <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
            APIs protected by this permission on users different to the calling user.
        @FlaggedApi("android.app.admin.flags.esim_management_enabled") -->
    <permission android:name="android.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS"
        android:protectionLevel="internal|role" />

    <!-- Allows an application to set device policies outside the current user
        that are critical for securing data within the current user.
        <p>Holding this permission allows the use of other held MANAGE_DEVICE_POLICY_*
+32 −1
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCATION;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_TASK;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MICROPHONE;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MOBILE_NETWORK;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MODIFY_USERS;
@@ -443,6 +444,7 @@ import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.ParcelableKeyGenParameterSpec;
import android.stats.devicepolicy.DevicePolicyEnums;
import android.telecom.TelecomManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
@@ -22299,6 +22301,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            MANAGE_DEVICE_POLICY_LOCK,
            MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
            MANAGE_DEVICE_POLICY_LOCK_TASK,
            MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS,
            MANAGE_DEVICE_POLICY_MICROPHONE,
            MANAGE_DEVICE_POLICY_MOBILE_NETWORK,
            MANAGE_DEVICE_POLICY_MODIFY_USERS,
@@ -22379,7 +22382,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    MANAGE_DEVICE_POLICY_LOCATION,
                    MANAGE_DEVICE_POLICY_LOCK,
                    MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
                    MANAGE_DEVICE_POLICY_CERTIFICATES,
                    MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS,
                    MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION,
                    MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
                    MANAGE_DEVICE_POLICY_PACKAGE_STATE,
@@ -23968,4 +23971,32 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            Slogf.d(LOG_TAG, "Unable to get stacktrace");
        }
    }
    @Override
    public int[] getSubscriptionIds(String callerPackageName) {
        final CallerIdentity caller = getCallerIdentity(callerPackageName);
        enforceCanQuery(
                MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS,
                caller.getPackageName(),
                caller.getUserId());
        return getSubscriptionIdsInternal(callerPackageName).toArray();
    }
    private IntArray getSubscriptionIdsInternal(String callerPackageName) {
        SubscriptionManager subscriptionManager =
                mContext.getSystemService(SubscriptionManager.class);
        return mInjector.binderWithCleanCallingIdentity(() -> {
            IntArray adminOwnedSubscriptions = new IntArray();
            List<SubscriptionInfo> subs = subscriptionManager.getAvailableSubscriptionInfoList();
            int subCount = (subs != null) ? subs.size() : 0;
            for (int i = 0; i < subCount; i++) {
                SubscriptionInfo sub = subs.get(i);
                if (sub.getGroupOwner()
                        .equals(callerPackageName)) {
                    adminOwnedSubscriptions.add(sub.getSubscriptionId());
                }
            }
            return adminOwnedSubscriptions;
        });
    }
}
Loading