OSDN Git Service

Allow secondary user POs on affiliated devices more DPM APIs
authorBenjamin Franz <bfranz@google.com>
Tue, 8 Aug 2017 11:33:19 +0000 (12:33 +0100)
committerAlex Chau <alexchau@google.com>
Thu, 30 Nov 2017 16:38:19 +0000 (16:38 +0000)
- DevicePolicyManager.setKeyguardDisabled
- DevicePolicyManager.setStatusBarDisabled
- DevicePolicyManager.setDeviceOwnerLockScreenInfo
- PackageInstaller install and uninstall apps

Bug: 64383519
Test: Can set keyguard disabled, status bar disabled and lock screen message in
      affliated PO
Test: Can install and uninstall apps in affiliated PO
Test: CTS tracked in b/68925683

Change-Id: I71be25098436ba0b42050478c049850c2b21f6f4

core/java/android/app/admin/DevicePolicyManagerInternal.java
services/core/java/com/android/server/pm/PackageInstallerService.java
services/core/java/com/android/server/pm/PackageInstallerSession.java
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java

index eef2f98..05f6c2a 100644 (file)
@@ -101,4 +101,18 @@ public abstract class DevicePolicyManagerInternal {
      * not enforced by the profile/device owner.
      */
     public abstract Intent createUserRestrictionSupportIntent(int userId, String userRestriction);
+
+    /**
+     * Returns whether this user/profile is affiliated with the device.
+     *
+     * <p>
+     * By definition, the user that the device owner runs on is always affiliated with the device.
+     * Any other user/profile is considered affiliated with the device if the set specified by its
+     * profile owner via {@link DevicePolicyManager#setAffiliationIds} intersects with the device
+     * owner's.
+     * <p>
+     * Profile owner on the primary user will never be considered as affiliated as there is no
+     * device owner to be affiliated with.
+     */
+    public abstract boolean isUserAffiliatedWithDevice(int userId);
 }
index be9b2f3..14128a7 100644 (file)
@@ -27,7 +27,8 @@ import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PackageDeleteObserver;
 import android.app.PackageInstallObserver;
-import android.app.admin.DevicePolicyManager;
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -704,20 +705,25 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
             mAppOps.checkPackage(callingUid, callerPackageName);
         }
 
-        // Check whether the caller is device owner, in which case we do it silently.
-        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-        boolean isDeviceOwner = (dpm != null) && dpm.isDeviceOwnerAppOnCallingUser(
-                callerPackageName);
+        // Check whether the caller is device owner or affiliated profile owner, in which case we do
+        // it silently.
+        final int callingUserId = UserHandle.getUserId(callingUid);
+        DevicePolicyManagerInternal dpmi =
+                LocalServices.getService(DevicePolicyManagerInternal.class);
+        final boolean isDeviceOwnerOrAffiliatedProfileOwner =
+                dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
+                        DeviceAdminInfo.USES_POLICY_PROFILE_OWNER)
+                        && dpmi.isUserAffiliatedWithDevice(callingUserId);
 
         final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
-                statusReceiver, versionedPackage.getPackageName(), isDeviceOwner, userId);
+                statusReceiver, versionedPackage.getPackageName(),
+                isDeviceOwnerOrAffiliatedProfileOwner, userId);
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
                     == PackageManager.PERMISSION_GRANTED) {
             // Sweet, call straight through!
             mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
-        } else if (isDeviceOwner) {
-            // Allow the DeviceOwner to silently delete packages
+        } else if (isDeviceOwnerOrAffiliatedProfileOwner) {
+            // Allow the device owner and affiliated profile owner to silently delete packages
             // Need to clear the calling identity to get DELETE_PACKAGES permission
             long ident = Binder.clearCallingIdentity();
             try {
index 0e11cc7..711352f 100644 (file)
@@ -41,7 +41,8 @@ import static com.android.server.pm.PackageInstallerService.prepareStageDir;
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.admin.DevicePolicyManager;
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -91,6 +92,7 @@ import com.android.internal.os.SomeArgs;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.server.LocalServices;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
 
@@ -311,14 +313,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
     };
 
     /**
-     * @return {@code true} iff the installing is app an device owner?
+     * @return {@code true} iff the installing is app an device owner or affiliated profile owner.
      */
-    private boolean isInstallerDeviceOwnerLocked() {
-        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-
-        return (dpm != null) && dpm.isDeviceOwnerAppOnCallingUser(
-                mInstallerPackageName);
+    private boolean isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked() {
+        DevicePolicyManagerInternal dpmi =
+                LocalServices.getService(DevicePolicyManagerInternal.class);
+        return dpmi != null && dpmi.isActiveAdminWithPolicy(mInstallerUid,
+                DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) && dpmi.isUserAffiliatedWithDevice(
+                userId);
     }
 
     /**
@@ -347,10 +349,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
         final boolean forcePermissionPrompt =
                 (params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0;
 
-        // Device owners are allowed to silently install packages, so the permission check is
-        // waived if the installer is the device owner.
+        // Device owners and affiliated profile owners  are allowed to silently install packages, so
+        // the permission check is waived if the installer is the device owner.
         return forcePermissionPrompt || !(isPermissionGranted || isInstallerRoot
-                || isInstallerDeviceOwnerLocked());
+                || isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked());
     }
 
     public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
@@ -705,7 +707,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
             assertPreparedAndNotDestroyedLocked("commit");
 
             final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(
-                    mContext, statusReceiver, sessionId, isInstallerDeviceOwnerLocked(), userId);
+                    mContext, statusReceiver, sessionId,
+                    isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId);
             mRemoteObserver = adapter.getBinder();
 
             if (forTransfer) {
index 60c36d1..46f8935 100644 (file)
@@ -6943,8 +6943,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
             return;
         }
 
+        final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (this) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            if (!isUserAffiliatedWithDeviceLocked(userId)) {
+                throw new SecurityException("Admin " + who +
+                        " is neither the device owner or affiliated user's profile owner.");
+            }
             long token = mInjector.binderClearCallingIdentity();
             try {
                 mLockPatternUtils.setDeviceOwnerInfo(info != null ? info.toString() : null);
@@ -9236,10 +9241,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     @Override
     public boolean setKeyguardDisabled(ComponentName who, boolean disabled) {
         Preconditions.checkNotNull(who, "ComponentName is null");
+        final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (this) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            if (!isUserAffiliatedWithDeviceLocked(userId)) {
+                throw new SecurityException("Admin " + who +
+                        " is neither the device owner or affiliated user's profile owner.");
+            }
         }
-        final int userId = UserHandle.getCallingUserId();
 
         long ident = mInjector.binderClearCallingIdentity();
         try {
@@ -9261,7 +9270,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     public boolean setStatusBarDisabled(ComponentName who, boolean disabled) {
         int userId = UserHandle.getCallingUserId();
         synchronized (this) {
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            if (!isUserAffiliatedWithDeviceLocked(userId)) {
+                throw new SecurityException("Admin " + who +
+                        " is neither the device owner or affiliated user's profile owner.");
+            }
             DevicePolicyData policy = getUserData(userId);
             if (policy.mStatusBarDisabled != disabled) {
                 boolean isLockTaskMode = false;
@@ -9526,6 +9539,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
             }
             return null;
         }
+
+        @Override
+        public boolean isUserAffiliatedWithDevice(int userId) {
+            return DevicePolicyManagerService.this.isUserAffiliatedWithDeviceLocked(userId);
+        }
     }
 
     private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {