Loading src/java/com/android/internal/telephony/euicc/EuiccController.java +149 −9 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; import android.app.admin.flags.Flags; import android.app.compat.CompatChanges; import android.content.ComponentName; import android.content.Context; Loading @@ -33,6 +35,8 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Binder; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.service.euicc.DownloadSubscriptionResult; import android.service.euicc.EuiccService; Loading @@ -54,6 +58,7 @@ import android.telephony.euicc.EuiccInfo; import android.telephony.euicc.EuiccManager; import android.telephony.euicc.EuiccManager.OtaStatus; import android.text.TextUtils; import android.util.ArraySet; import android.util.EventLog; import android.util.Log; import android.util.Pair; Loading @@ -75,6 +80,7 @@ import java.io.PrintWriter; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.Stack; import java.util.UUID; import java.util.concurrent.CountDownLatch; Loading Loading @@ -610,6 +616,19 @@ public class EuiccController extends IEuiccController.Stub { boolean switchAfterDownload, String callingPackage, boolean forceDeactivateSim, Bundle resolvedBundle, PendingIntent callbackIntent) { boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); boolean callerCanDownloadAdminManagedSubscription = Flags.esimManagementEnabled() && callerCanManageDevicePolicyManagedSubscriptions(callingPackage); if (Flags.esimManagementEnabled()) { if (mContext .getSystemService(UserManager.class) .hasUserRestriction(UserManager.DISALLOW_SIM_GLOBALLY) && !callerCanDownloadAdminManagedSubscription) { // Only admin managed subscriptions are allowed, but the caller is not authorised to // download admin managed subscriptions. Abort. throw new SecurityException("Caller is not authorized to download subscriptions"); } } mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); // Don't try to resolve the port index for apps which are not targeting on T for backward // compatibility. instead always use default port 0. Loading @@ -627,18 +646,27 @@ public class EuiccController extends IEuiccController.Stub { isConsentNeededToResolvePortIndex = (portIndex == TelephonyManager.INVALID_PORT_INDEX); } // Caller has admin privileges if they can download admin managed subscription, // and are not switching the subscription after download (admins cannot silently // enable the subscription). boolean hasAdminPrivileges = callerCanDownloadAdminManagedSubscription && !switchAfterDownload; Log.d(TAG, " downloadSubscription cardId: " + cardId + " switchAfterDownload: " + switchAfterDownload + " portIndex: " + portIndex + " forceDeactivateSim: " + forceDeactivateSim + " callingPackage: " + callingPackage + " isConsentNeededToResolvePortIndex: " + isConsentNeededToResolvePortIndex + " shouldResolvePortIndex:" + shouldResolvePortIndex); if (!isConsentNeededToResolvePortIndex && callerCanWriteEmbeddedSubscriptions) { + " shouldResolvePortIndex:" + shouldResolvePortIndex + " hasAdminPrivileges:" + hasAdminPrivileges); if (!isConsentNeededToResolvePortIndex && (callerCanWriteEmbeddedSubscriptions || hasAdminPrivileges)) { // With WRITE_EMBEDDED_SUBSCRIPTIONS, we can skip profile-specific permission checks // and move straight to the profile download. downloadSubscriptionPrivileged(cardId, portIndex, token, subscription, switchAfterDownload, forceDeactivateSim, callingPackage, resolvedBundle, callbackIntent); callbackIntent, callerCanDownloadAdminManagedSubscription, getCurrentEmbeddedSubscriptionIds(cardId)); return; } Loading Loading @@ -774,11 +802,30 @@ public class EuiccController extends IEuiccController.Stub { true /* withUserConsent */, portIndex)); } void downloadSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, final PendingIntent callbackIntent) { downloadSubscriptionPrivileged( cardId, portIndex, callingToken, subscription, switchAfterDownload, forceDeactivateSim, callingPackage, resolvedBundle, callbackIntent, false /* markAsOwnedByAdmin */, new ArraySet<>() /* existingSubscriptions */); } // Continue to download subscription without checking anything. void downloadSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, final PendingIntent callbackIntent) { final PendingIntent callbackIntent, boolean markAsOwnedByAdmin, Set<Integer> existingSubscriptions) { mConnector.downloadSubscription( cardId, portIndex, Loading Loading @@ -807,7 +854,13 @@ public class EuiccController extends IEuiccController.Stub { // Since we're not switching, nothing will trigger a // subscription list refresh on its own, so request one here. refreshSubscriptionsAndSendResult( callbackIntent, resultCode, extrasIntent); callbackIntent, resultCode, extrasIntent, markAsOwnedByAdmin, callingPackage, cardId, existingSubscriptions); return; } break; Loading Loading @@ -1009,6 +1062,9 @@ public class EuiccController extends IEuiccController.Stub { public void deleteSubscription(int cardId, int subscriptionId, String callingPackage, PendingIntent callbackIntent) { boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); boolean callerIsAdmin = Flags.esimManagementEnabled() && callerCanManageDevicePolicyManagedSubscriptions(callingPackage); mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); long token = Binder.clearCallingIdentity(); Loading @@ -1019,13 +1075,14 @@ public class EuiccController extends IEuiccController.Stub { sendResult(callbackIntent, ERROR, null /* extrasIntent */); return; } boolean adminOwned = callerIsAdmin && sub.getGroupOwner().equals(callingPackage); // For both single active SIM device and multi-active SIM device, if the caller is // system or the caller manage the target subscription, we let it continue. This is // because deleting subscription won't change status of any other subscriptions. if (!callerCanWriteEmbeddedSubscriptions && !mSubscriptionManager.canManageSubscription(sub, callingPackage)) { Log.e(TAG, "No permissions: " + subscriptionId); && !mSubscriptionManager.canManageSubscription(sub, callingPackage) && !adminOwned) { Log.e(TAG, "No permissions: " + subscriptionId + " adminOwned=" + adminOwned); sendResult(callbackIntent, ERROR, null /* extrasIntent */); return; } Loading Loading @@ -1643,9 +1700,43 @@ public class EuiccController extends IEuiccController.Stub { @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public void refreshSubscriptionsAndSendResult( PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { refreshSubscriptionsAndSendResult( callbackIntent, resultCode, extrasIntent, /* isCallerAdmin= */ false, /* callingPackage= */ "", /* cardId */ -1, /* subscriptionsBefore= */ new ArraySet<>()); } /** Refresh the embedded subscription list and dispatch the given result upon completion. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public void refreshSubscriptionsAndSendResult( PendingIntent callbackIntent, int resultCode, Intent extrasIntent, boolean isCallerAdmin, String callingPackage, int cardId, Set<Integer> subscriptionsBefore) { SubscriptionManagerService.getInstance().updateEmbeddedSubscriptions( List.of(mTelephonyManager.getCardIdForDefaultEuicc()), () -> sendResult(callbackIntent, resultCode, extrasIntent)); () -> { if (Flags.esimManagementEnabled() && isCallerAdmin) { // Mark the newly downloaded subscriptions as being owned by an admin so // that actions for that subscription can be restricted, // and the admin is limited to effecting only these subscriptions. Set<Integer> subscriptionsAfter = getCurrentEmbeddedSubscriptionIds(cardId); subscriptionsAfter.removeAll(subscriptionsBefore); for (int subId: subscriptionsAfter) { SubscriptionManagerService .getInstance().setGroupOwner(subId, callingPackage); } } sendResult(callbackIntent, resultCode, extrasIntent); }); } /** Dispatch the given callback intent with the given result code and data. */ Loading Loading @@ -1761,6 +1852,23 @@ public class EuiccController extends IEuiccController.Stub { return null; } private Set<Integer> getCurrentEmbeddedSubscriptionIds(int cardId) { if (!Flags.esimManagementEnabled()) { return new ArraySet<>(); } List<SubscriptionInfo> subscriptionInfos = mSubscriptionManager.getAvailableSubscriptionInfoList(); int subCount = (subscriptionInfos != null) ? subscriptionInfos.size() : 0; Set<Integer> currentEmbeddedSubscriptionIds = new ArraySet<>(); for (int i = 0; i < subCount; i++) { SubscriptionInfo subscriptionInfo = subscriptionInfos.get(i); if (subscriptionInfo.isEmbedded() && subscriptionInfo.getCardId() == cardId) { currentEmbeddedSubscriptionIds.add(subscriptionInfo.getSubscriptionId()); } } return currentEmbeddedSubscriptionIds; } @Nullable private String blockingGetEidFromEuiccService(int cardId) { CountDownLatch latch = new CountDownLatch(1); Loading Loading @@ -2019,6 +2127,38 @@ public class EuiccController extends IEuiccController.Stub { == PackageManager.PERMISSION_GRANTED; } private DevicePolicyManager retrieveDevicePolicyManagerFromUserContext(UserHandle userHandle) { Context userContext; long ident = Binder.clearCallingIdentity(); try { userContext = mContext.createPackageContextAsUser( mContext.getPackageName(), /* flags= */ 0, userHandle); } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Unknown package name"); return null; } finally { Binder.restoreCallingIdentity(ident); } return userContext.getSystemService(DevicePolicyManager.class); } private boolean callerCanManageDevicePolicyManagedSubscriptions(String callingPackage) { // isProfileOwner/isDeviceOwner needs to callers user, so create device policy manager // with the correct context associated with the caller. DevicePolicyManager devicePolicyManager = retrieveDevicePolicyManagerFromUserContext(Binder.getCallingUserHandle()); if (devicePolicyManager == null) { Log.w(TAG, "Unable to get device policy manager"); return false; } boolean isAdmin = devicePolicyManager.isProfileOwnerApp(callingPackage) || devicePolicyManager.isDeviceOwnerApp(callingPackage); return isAdmin || mContext.checkCallingOrSelfPermission( Manifest.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS) == PackageManager.PERMISSION_GRANTED; } @Override public boolean isSimPortAvailable(int cardId, int portIndex, String callingPackage) { mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); Loading src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java +20 −0 Original line number Diff line number Diff line Loading @@ -924,6 +924,26 @@ public class SubscriptionManagerService extends ISub.Stub { } } /** * Set the group owner on the subscription * * <p> Note: This only sets the group owner field and doesn't update other relevant fields. * Prefer to call {@link #addSubscriptionsIntoGroup}. * * @param subId Subscription id. * @param groupOwner The group owner to assign to the subscription */ public void setGroupOwner(int subId, @NonNull String groupOwner) { // This can throw IllegalArgumentException if the subscription does not exist. try { mSubscriptionDatabaseManager.setGroupOwner( subId, groupOwner); } catch (IllegalArgumentException e) { loge("setManaged: invalid subId=" + subId); } } /** * Set last used TP message reference. * Loading tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java +6 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.app.DownloadManager; import android.app.KeyguardManager; import android.app.NotificationManager; import android.app.UiModeManager; import android.app.admin.DevicePolicyManager; import android.app.usage.UsageStatsManager; import android.content.BroadcastReceiver; import android.content.ComponentName; Loading Loading @@ -310,6 +311,8 @@ public class ContextFixture implements TestFixture<Context> { return mNetworkPolicyManager; case Context.TELEPHONY_IMS_SERVICE: return mImsManager; case Context.DEVICE_POLICY_SERVICE: return mDevicePolicyManager; default: return null; } Loading Loading @@ -357,6 +360,8 @@ public class ContextFixture implements TestFixture<Context> { return Context.EUICC_SERVICE; } else if (serviceClass == AlarmManager.class) { return Context.ALARM_SERVICE; } else if (serviceClass == DevicePolicyManager.class) { return Context.DEVICE_POLICY_SERVICE; } return super.getSystemServiceName(serviceClass); } Loading Loading @@ -731,6 +736,7 @@ public class ContextFixture implements TestFixture<Context> { private final VcnManager mVcnManager = mock(VcnManager.class); private final NetworkPolicyManager mNetworkPolicyManager = mock(NetworkPolicyManager.class); private final ImsManager mImsManager = mock(ImsManager.class); private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class); private final Configuration mConfiguration = new Configuration(); private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); private final SharedPreferences mSharedPreferences = PreferenceManager Loading tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java +231 −0 File changed.Preview size limit exceeded, changes collapsed. Show changes tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java +17 −0 Original line number Diff line number Diff line Loading @@ -418,6 +418,23 @@ public class SubscriptionManagerServiceTest extends TelephonyTest { verify(mMockedSubscriptionManagerServiceCallback).onSubscriptionChanged(eq(1)); } @Test public void testSetAdminOwned() { mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE); mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1, 0, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); processAllMessages(); String groupOwner = "test"; mSubscriptionManagerServiceUT.setGroupOwner(1, groupOwner); SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT .getSubscriptionInfoInternal(1); assertThat(subInfo).isNotNull(); assertThat(subInfo.getGroupOwner()).isEqualTo(groupOwner); verify(mMockedSubscriptionManagerServiceCallback).onSubscriptionChanged(eq(1)); } @Test @DisableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING}) public void testSetPhoneNumber() { Loading Loading
src/java/com/android/internal/telephony/euicc/EuiccController.java +149 −9 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; import android.app.admin.flags.Flags; import android.app.compat.CompatChanges; import android.content.ComponentName; import android.content.Context; Loading @@ -33,6 +35,8 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Binder; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.service.euicc.DownloadSubscriptionResult; import android.service.euicc.EuiccService; Loading @@ -54,6 +58,7 @@ import android.telephony.euicc.EuiccInfo; import android.telephony.euicc.EuiccManager; import android.telephony.euicc.EuiccManager.OtaStatus; import android.text.TextUtils; import android.util.ArraySet; import android.util.EventLog; import android.util.Log; import android.util.Pair; Loading @@ -75,6 +80,7 @@ import java.io.PrintWriter; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.Stack; import java.util.UUID; import java.util.concurrent.CountDownLatch; Loading Loading @@ -610,6 +616,19 @@ public class EuiccController extends IEuiccController.Stub { boolean switchAfterDownload, String callingPackage, boolean forceDeactivateSim, Bundle resolvedBundle, PendingIntent callbackIntent) { boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); boolean callerCanDownloadAdminManagedSubscription = Flags.esimManagementEnabled() && callerCanManageDevicePolicyManagedSubscriptions(callingPackage); if (Flags.esimManagementEnabled()) { if (mContext .getSystemService(UserManager.class) .hasUserRestriction(UserManager.DISALLOW_SIM_GLOBALLY) && !callerCanDownloadAdminManagedSubscription) { // Only admin managed subscriptions are allowed, but the caller is not authorised to // download admin managed subscriptions. Abort. throw new SecurityException("Caller is not authorized to download subscriptions"); } } mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); // Don't try to resolve the port index for apps which are not targeting on T for backward // compatibility. instead always use default port 0. Loading @@ -627,18 +646,27 @@ public class EuiccController extends IEuiccController.Stub { isConsentNeededToResolvePortIndex = (portIndex == TelephonyManager.INVALID_PORT_INDEX); } // Caller has admin privileges if they can download admin managed subscription, // and are not switching the subscription after download (admins cannot silently // enable the subscription). boolean hasAdminPrivileges = callerCanDownloadAdminManagedSubscription && !switchAfterDownload; Log.d(TAG, " downloadSubscription cardId: " + cardId + " switchAfterDownload: " + switchAfterDownload + " portIndex: " + portIndex + " forceDeactivateSim: " + forceDeactivateSim + " callingPackage: " + callingPackage + " isConsentNeededToResolvePortIndex: " + isConsentNeededToResolvePortIndex + " shouldResolvePortIndex:" + shouldResolvePortIndex); if (!isConsentNeededToResolvePortIndex && callerCanWriteEmbeddedSubscriptions) { + " shouldResolvePortIndex:" + shouldResolvePortIndex + " hasAdminPrivileges:" + hasAdminPrivileges); if (!isConsentNeededToResolvePortIndex && (callerCanWriteEmbeddedSubscriptions || hasAdminPrivileges)) { // With WRITE_EMBEDDED_SUBSCRIPTIONS, we can skip profile-specific permission checks // and move straight to the profile download. downloadSubscriptionPrivileged(cardId, portIndex, token, subscription, switchAfterDownload, forceDeactivateSim, callingPackage, resolvedBundle, callbackIntent); callbackIntent, callerCanDownloadAdminManagedSubscription, getCurrentEmbeddedSubscriptionIds(cardId)); return; } Loading Loading @@ -774,11 +802,30 @@ public class EuiccController extends IEuiccController.Stub { true /* withUserConsent */, portIndex)); } void downloadSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, final PendingIntent callbackIntent) { downloadSubscriptionPrivileged( cardId, portIndex, callingToken, subscription, switchAfterDownload, forceDeactivateSim, callingPackage, resolvedBundle, callbackIntent, false /* markAsOwnedByAdmin */, new ArraySet<>() /* existingSubscriptions */); } // Continue to download subscription without checking anything. void downloadSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, final PendingIntent callbackIntent) { final PendingIntent callbackIntent, boolean markAsOwnedByAdmin, Set<Integer> existingSubscriptions) { mConnector.downloadSubscription( cardId, portIndex, Loading Loading @@ -807,7 +854,13 @@ public class EuiccController extends IEuiccController.Stub { // Since we're not switching, nothing will trigger a // subscription list refresh on its own, so request one here. refreshSubscriptionsAndSendResult( callbackIntent, resultCode, extrasIntent); callbackIntent, resultCode, extrasIntent, markAsOwnedByAdmin, callingPackage, cardId, existingSubscriptions); return; } break; Loading Loading @@ -1009,6 +1062,9 @@ public class EuiccController extends IEuiccController.Stub { public void deleteSubscription(int cardId, int subscriptionId, String callingPackage, PendingIntent callbackIntent) { boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); boolean callerIsAdmin = Flags.esimManagementEnabled() && callerCanManageDevicePolicyManagedSubscriptions(callingPackage); mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); long token = Binder.clearCallingIdentity(); Loading @@ -1019,13 +1075,14 @@ public class EuiccController extends IEuiccController.Stub { sendResult(callbackIntent, ERROR, null /* extrasIntent */); return; } boolean adminOwned = callerIsAdmin && sub.getGroupOwner().equals(callingPackage); // For both single active SIM device and multi-active SIM device, if the caller is // system or the caller manage the target subscription, we let it continue. This is // because deleting subscription won't change status of any other subscriptions. if (!callerCanWriteEmbeddedSubscriptions && !mSubscriptionManager.canManageSubscription(sub, callingPackage)) { Log.e(TAG, "No permissions: " + subscriptionId); && !mSubscriptionManager.canManageSubscription(sub, callingPackage) && !adminOwned) { Log.e(TAG, "No permissions: " + subscriptionId + " adminOwned=" + adminOwned); sendResult(callbackIntent, ERROR, null /* extrasIntent */); return; } Loading Loading @@ -1643,9 +1700,43 @@ public class EuiccController extends IEuiccController.Stub { @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public void refreshSubscriptionsAndSendResult( PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { refreshSubscriptionsAndSendResult( callbackIntent, resultCode, extrasIntent, /* isCallerAdmin= */ false, /* callingPackage= */ "", /* cardId */ -1, /* subscriptionsBefore= */ new ArraySet<>()); } /** Refresh the embedded subscription list and dispatch the given result upon completion. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public void refreshSubscriptionsAndSendResult( PendingIntent callbackIntent, int resultCode, Intent extrasIntent, boolean isCallerAdmin, String callingPackage, int cardId, Set<Integer> subscriptionsBefore) { SubscriptionManagerService.getInstance().updateEmbeddedSubscriptions( List.of(mTelephonyManager.getCardIdForDefaultEuicc()), () -> sendResult(callbackIntent, resultCode, extrasIntent)); () -> { if (Flags.esimManagementEnabled() && isCallerAdmin) { // Mark the newly downloaded subscriptions as being owned by an admin so // that actions for that subscription can be restricted, // and the admin is limited to effecting only these subscriptions. Set<Integer> subscriptionsAfter = getCurrentEmbeddedSubscriptionIds(cardId); subscriptionsAfter.removeAll(subscriptionsBefore); for (int subId: subscriptionsAfter) { SubscriptionManagerService .getInstance().setGroupOwner(subId, callingPackage); } } sendResult(callbackIntent, resultCode, extrasIntent); }); } /** Dispatch the given callback intent with the given result code and data. */ Loading Loading @@ -1761,6 +1852,23 @@ public class EuiccController extends IEuiccController.Stub { return null; } private Set<Integer> getCurrentEmbeddedSubscriptionIds(int cardId) { if (!Flags.esimManagementEnabled()) { return new ArraySet<>(); } List<SubscriptionInfo> subscriptionInfos = mSubscriptionManager.getAvailableSubscriptionInfoList(); int subCount = (subscriptionInfos != null) ? subscriptionInfos.size() : 0; Set<Integer> currentEmbeddedSubscriptionIds = new ArraySet<>(); for (int i = 0; i < subCount; i++) { SubscriptionInfo subscriptionInfo = subscriptionInfos.get(i); if (subscriptionInfo.isEmbedded() && subscriptionInfo.getCardId() == cardId) { currentEmbeddedSubscriptionIds.add(subscriptionInfo.getSubscriptionId()); } } return currentEmbeddedSubscriptionIds; } @Nullable private String blockingGetEidFromEuiccService(int cardId) { CountDownLatch latch = new CountDownLatch(1); Loading Loading @@ -2019,6 +2127,38 @@ public class EuiccController extends IEuiccController.Stub { == PackageManager.PERMISSION_GRANTED; } private DevicePolicyManager retrieveDevicePolicyManagerFromUserContext(UserHandle userHandle) { Context userContext; long ident = Binder.clearCallingIdentity(); try { userContext = mContext.createPackageContextAsUser( mContext.getPackageName(), /* flags= */ 0, userHandle); } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Unknown package name"); return null; } finally { Binder.restoreCallingIdentity(ident); } return userContext.getSystemService(DevicePolicyManager.class); } private boolean callerCanManageDevicePolicyManagedSubscriptions(String callingPackage) { // isProfileOwner/isDeviceOwner needs to callers user, so create device policy manager // with the correct context associated with the caller. DevicePolicyManager devicePolicyManager = retrieveDevicePolicyManagerFromUserContext(Binder.getCallingUserHandle()); if (devicePolicyManager == null) { Log.w(TAG, "Unable to get device policy manager"); return false; } boolean isAdmin = devicePolicyManager.isProfileOwnerApp(callingPackage) || devicePolicyManager.isDeviceOwnerApp(callingPackage); return isAdmin || mContext.checkCallingOrSelfPermission( Manifest.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS) == PackageManager.PERMISSION_GRANTED; } @Override public boolean isSimPortAvailable(int cardId, int portIndex, String callingPackage) { mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); Loading
src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java +20 −0 Original line number Diff line number Diff line Loading @@ -924,6 +924,26 @@ public class SubscriptionManagerService extends ISub.Stub { } } /** * Set the group owner on the subscription * * <p> Note: This only sets the group owner field and doesn't update other relevant fields. * Prefer to call {@link #addSubscriptionsIntoGroup}. * * @param subId Subscription id. * @param groupOwner The group owner to assign to the subscription */ public void setGroupOwner(int subId, @NonNull String groupOwner) { // This can throw IllegalArgumentException if the subscription does not exist. try { mSubscriptionDatabaseManager.setGroupOwner( subId, groupOwner); } catch (IllegalArgumentException e) { loge("setManaged: invalid subId=" + subId); } } /** * Set last used TP message reference. * Loading
tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java +6 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.app.DownloadManager; import android.app.KeyguardManager; import android.app.NotificationManager; import android.app.UiModeManager; import android.app.admin.DevicePolicyManager; import android.app.usage.UsageStatsManager; import android.content.BroadcastReceiver; import android.content.ComponentName; Loading Loading @@ -310,6 +311,8 @@ public class ContextFixture implements TestFixture<Context> { return mNetworkPolicyManager; case Context.TELEPHONY_IMS_SERVICE: return mImsManager; case Context.DEVICE_POLICY_SERVICE: return mDevicePolicyManager; default: return null; } Loading Loading @@ -357,6 +360,8 @@ public class ContextFixture implements TestFixture<Context> { return Context.EUICC_SERVICE; } else if (serviceClass == AlarmManager.class) { return Context.ALARM_SERVICE; } else if (serviceClass == DevicePolicyManager.class) { return Context.DEVICE_POLICY_SERVICE; } return super.getSystemServiceName(serviceClass); } Loading Loading @@ -731,6 +736,7 @@ public class ContextFixture implements TestFixture<Context> { private final VcnManager mVcnManager = mock(VcnManager.class); private final NetworkPolicyManager mNetworkPolicyManager = mock(NetworkPolicyManager.class); private final ImsManager mImsManager = mock(ImsManager.class); private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class); private final Configuration mConfiguration = new Configuration(); private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); private final SharedPreferences mSharedPreferences = PreferenceManager Loading
tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java +231 −0 File changed.Preview size limit exceeded, changes collapsed. Show changes
tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java +17 −0 Original line number Diff line number Diff line Loading @@ -418,6 +418,23 @@ public class SubscriptionManagerServiceTest extends TelephonyTest { verify(mMockedSubscriptionManagerServiceCallback).onSubscriptionChanged(eq(1)); } @Test public void testSetAdminOwned() { mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE); mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1, 0, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); processAllMessages(); String groupOwner = "test"; mSubscriptionManagerServiceUT.setGroupOwner(1, groupOwner); SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT .getSubscriptionInfoInternal(1); assertThat(subInfo).isNotNull(); assertThat(subInfo.getGroupOwner()).isEqualTo(groupOwner); verify(mMockedSubscriptionManagerServiceCallback).onSubscriptionChanged(eq(1)); } @Test @DisableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING}) public void testSetPhoneNumber() { Loading