diff options
5 files changed, 35 insertions, 1 deletions
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 7e50518cb3e1..68118fc3555d 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringRes; import android.annotation.XmlRes; +import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Intent; @@ -1759,7 +1760,7 @@ public class ApplicationPackageManager extends PackageManager { return candidates; } - private static boolean isPackageCandidateVolume( + private boolean isPackageCandidateVolume( ContextImpl context, ApplicationInfo app, VolumeInfo vol) { final boolean forceAllowOnExternal = Settings.Global.getInt( context.getContentResolver(), Settings.Global.FORCE_ALLOW_ON_EXTERNAL, 0) != 0; @@ -1789,6 +1790,15 @@ public class ApplicationPackageManager extends PackageManager { return app.isInternal(); } + // Some apps can't be moved. (e.g. device admins) + try { + if (mPM.isPackageDeviceAdminOnAnyUser(app.packageName)) { + return false; + } + } catch (RemoteException e) { + throw new RuntimeException("Package manager has died", e); + } + // Otherwise we can move to any private volume return (vol.getType() == VolumeInfo.TYPE_PRIVATE); } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index c71a60353e1a..b9d5ef65d40a 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -536,4 +536,6 @@ interface IPackageManager { boolean setRequiredForSystemUser(String packageName, boolean systemUserApp); String getServicesSystemSharedLibraryPackageName(); + + boolean isPackageDeviceAdminOnAnyUser(String packageName); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 36b902c3e481..7cf7df5c641a 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1233,6 +1233,14 @@ public abstract class PackageManager { public static final int MOVE_FAILED_OPERATION_PENDING = -7; /** + * Error code that is passed to the {@link IPackageMoveObserver} if the + * specified package cannot be moved since it contains a device admin. + * + * @hide + */ + public static final int MOVE_FAILED_DEVICE_ADMIN = -8; + + /** * Flag parameter for {@link #movePackage} to indicate that * the package should be moved to internal storage if its * been installed on external media. diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 6011e071e5d2..3d5bc5806da7 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -65,6 +65,7 @@ import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; +import static android.content.pm.PackageManager.MOVE_FAILED_DEVICE_ADMIN; import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST; import static android.content.pm.PackageManager.MOVE_FAILED_INTERNAL_ERROR; import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING; @@ -14048,6 +14049,11 @@ public class PackageManagerService extends IPackageManager.Stub { }); } + @Override + public boolean isPackageDeviceAdminOnAnyUser(String packageName) { + return isPackageDeviceAdmin(packageName, UserHandle.USER_ALL); + } + private boolean isPackageDeviceAdmin(String packageName, int userId) { IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface( ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)); @@ -18114,6 +18120,10 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Package already moved to " + volumeUuid); } + if (pkg.applicationInfo.isInternal() && isPackageDeviceAdminOnAnyUser(packageName)) { + throw new PackageManagerException(MOVE_FAILED_DEVICE_ADMIN, + "Device admin cannot be moved"); + } if (ps.frozen) { throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING, diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 8a2a57892209..2a0e1aca7548 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -2701,6 +2701,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (info == null) { throw new IllegalArgumentException("Bad admin: " + adminReceiver); } + if (!info.getActivityInfo().applicationInfo.isInternal()) { + throw new IllegalArgumentException("Only apps in internal storage can be active admin: " + + adminReceiver); + } synchronized (this) { long ident = mInjector.binderClearCallingIdentity(); try { |