diff options
| author | 2020-01-23 18:42:54 +0000 | |
|---|---|---|
| committer | 2020-01-23 18:42:54 +0000 | |
| commit | 371edb56f33c70589c654a96c04c3c6f16318ea9 (patch) | |
| tree | a6f683d225788e9bc2d676baf62d3f4f523a5462 | |
| parent | 2b13f4e55fc786165ad01e4ceced495cfa83d813 (diff) | |
| parent | a552dd65fa28ffecb81db9d3877c4ee54cf2790a (diff) | |
Merge "Modify setApplicationHidden and isApplicationHidden APIs"
4 files changed, 128 insertions, 32 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index aeeabb7c1726..62557dca9e7e 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -8260,6 +8260,11 @@ public class DevicePolicyManager { * actual package file remain. This function can be called by a device owner, profile owner, or * by a delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via * {@link #setDelegatedScopes}. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance, returned by + * {@link #getParentProfileInstance(ComponentName)}, where the caller must be the profile owner + * of an organization-owned managed profile and the package must be a system package. If called + * on the parent instance, then the package is hidden or unhidden in the personal profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if the caller is a package access delegate. @@ -8267,17 +8272,20 @@ public class DevicePolicyManager { * @param hidden {@code true} if the package should be hidden, {@code false} if it should be * unhidden. * @return boolean Whether the hidden setting of the package was successfully updated. - * @throws SecurityException if {@code admin} is not a device or profile owner. + * @throws SecurityException if {@code admin} is not a device or profile owner or if called on + * the parent profile and the {@code admin} is not a profile owner of an + * organization-owned managed profile. + * @throws IllegalArgumentException if called on the parent profile and the package provided + * is not a system package. * @see #setDelegatedScopes * @see #DELEGATION_PACKAGE_ACCESS */ public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName, boolean hidden) { - throwIfParentInstance("setApplicationHidden"); if (mService != null) { try { return mService.setApplicationHidden(admin, mContext.getPackageName(), packageName, - hidden); + hidden, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -8289,20 +8297,30 @@ public class DevicePolicyManager { * Determine if a package is hidden. This function can be called by a device owner, profile * owner, or by a delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via * {@link #setDelegatedScopes}. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance, returned by + * {@link #getParentProfileInstance(ComponentName)}, where the caller must be the profile owner + * of an organization-owned managed profile and the package must be a system package. If called + * on the parent instance, this will determine whether the package is hidden or unhidden in the + * personal profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if the caller is a package access delegate. * @param packageName The name of the package to retrieve the hidden status of. * @return boolean {@code true} if the package is hidden, {@code false} otherwise. - * @throws SecurityException if {@code admin} is not a device or profile owner. + * @throws SecurityException if {@code admin} is not a device or profile owner or if called on + * the parent profile and the {@code admin} is not a profile owner of an + * organization-owned managed profile. + * @throws IllegalArgumentException if called on the parent profile and the package provided + * is not a system package. * @see #setDelegatedScopes * @see #DELEGATION_PACKAGE_ACCESS */ public boolean isApplicationHidden(@NonNull ComponentName admin, String packageName) { - throwIfParentInstance("isApplicationHidden"); if (mService != null) { try { - return mService.isApplicationHidden(admin, mContext.getPackageName(), packageName); + return mService.isApplicationHidden(admin, mContext.getPackageName(), packageName, + mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index b9ffc4e214a6..3d6bf9db5535 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -233,8 +233,8 @@ interface IDevicePolicyManager { boolean isNotificationListenerServicePermitted(in String packageName, int userId); Intent createAdminSupportIntent(in String restriction); - boolean setApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean hidden); - boolean isApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName); + boolean setApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean hidden, boolean parent); + boolean isApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean parent); UserHandle createAndManageUser(in ComponentName who, in String name, in ComponentName profileOwner, in PersistableBundle adminExtras, in int flags); boolean removeUser(in ComponentName who, in UserHandle userHandle); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 0171582e9d86..da107d04b551 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -10737,30 +10737,35 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean setApplicationHidden(ComponentName who, String callerPackage, String packageName, - boolean hidden) { - int callingUserId = UserHandle.getCallingUserId(); - boolean result = false; + boolean hidden, boolean parent) { + final int userId = parent ? getProfileParentId(UserHandle.getCallingUserId()) + : UserHandle.getCallingUserId(); + boolean result; + synchronized (getLockObject()) { // Ensure the caller is a DO/PO or a package access delegate. enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, DELEGATION_PACKAGE_ACCESS); - long id = mInjector.binderClearCallingIdentity(); - try { - result = mIPackageManager - .setApplicationHiddenSettingAsUser(packageName, hidden, callingUserId); - } catch (RemoteException re) { - // shouldn't happen - Slog.e(LOG_TAG, "Failed to setApplicationHiddenSetting", re); - } finally { - mInjector.binderRestoreCallingIdentity(id); + if (parent) { + getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER, parent); + // Ensure the package provided is a system package, this is to ensure that this + // API cannot be used to leak if certain non-system package exists in the person + // profile. + mInjector.binderWithCleanCallingIdentity(() -> + enforcePackageIsSystemPackage(packageName, hidden, userId)); } + + result = mInjector.binderWithCleanCallingIdentity(() -> mIPackageManager + .setApplicationHiddenSettingAsUser(packageName, hidden, userId)); } final boolean isDelegate = (who == null); DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_APPLICATION_HIDDEN) .setAdmin(callerPackage) .setBoolean(isDelegate) + .setBoolean(parent) .setStrings(packageName, hidden ? "hidden" : "not_hidden") .write(); return result; @@ -10768,24 +10773,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean isApplicationHidden(ComponentName who, String callerPackage, - String packageName) { - int callingUserId = UserHandle.getCallingUserId(); + String packageName, boolean parent) { + final int userId = parent ? getProfileParentId(UserHandle.getCallingUserId()) + : UserHandle.getCallingUserId(); + synchronized (getLockObject()) { // Ensure the caller is a DO/PO or a package access delegate. enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, DELEGATION_PACKAGE_ACCESS); - long id = mInjector.binderClearCallingIdentity(); - try { - return mIPackageManager.getApplicationHiddenSettingAsUser( - packageName, callingUserId); - } catch (RemoteException re) { - // shouldn't happen - Slog.e(LOG_TAG, "Failed to getApplicationHiddenSettingAsUser", re); - } finally { - mInjector.binderRestoreCallingIdentity(id); + if (parent) { + getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER, parent); + // Ensure the package provided is a system package. + mInjector.binderWithCleanCallingIdentity(() -> + enforcePackageIsSystemPackage(packageName, false, userId)); } - return false; + + return mInjector.binderWithCleanCallingIdentity( + () -> mIPackageManager.getApplicationHiddenSettingAsUser(packageName, userId)); + } + } + + private void enforcePackageIsSystemPackage(String packageName, boolean hidden, int userId) + throws RemoteException { + int flags = PackageManager.MATCH_SYSTEM_ONLY; + // If the package is currently hidden then it is considered uninstalled and + // the MATCH_UNINSTALLED_PACKAGES flag has to be added. + if (!hidden) { + flags |= PackageManager.MATCH_UNINSTALLED_PACKAGES; + } + PackageInfo packageInfo = mIPackageManager.getPackageInfo(packageName, flags, userId); + if (packageInfo == null || !packageInfo.applicationInfo.isSystemApp()) { + throw new IllegalArgumentException( + "The provided package is not a system package"); } } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 8f1d0f7648f5..def5b617becd 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -2183,6 +2183,63 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(actualAccounts).containsExactlyElementsIn(expectedAccounts); } + public void testSetApplicationHiddenWithDO() throws Exception { + mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; + setupDeviceOwner(); + mContext.packageName = admin1.getPackageName(); + setUpPackageManagerForAdmin(admin1, mContext.binder.callingUid); + + String packageName = "com.google.android.test"; + + dpm.setApplicationHidden(admin1, packageName, true); + verify(getServices().ipackageManager).setApplicationHiddenSettingAsUser(packageName, + true, UserHandle.USER_SYSTEM); + + dpm.setApplicationHidden(admin1, packageName, false); + verify(getServices().ipackageManager).setApplicationHiddenSettingAsUser(packageName, + false, UserHandle.USER_SYSTEM); + + verify(getServices().ipackageManager, never()).getPackageInfo(packageName, + PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); + verify(getServices().ipackageManager, never()).getPackageInfo(packageName, + PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_SYSTEM_ONLY, + UserHandle.USER_SYSTEM); + } + + public void testSetApplicationHiddenWithPOOfOrganizationOwnedDevice() throws Exception { + final int MANAGED_PROFILE_USER_ID = DpmMockContext.CALLER_USER_HANDLE; + final int MANAGED_PROFILE_ADMIN_UID = + UserHandle.getUid(MANAGED_PROFILE_USER_ID, DpmMockContext.SYSTEM_UID); + mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; + + addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1); + configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE); + mContext.packageName = admin1.getPackageName(); + setUpPackageManagerForAdmin(admin1, mContext.binder.callingUid); + + String packageName = "com.google.android.test"; + + PackageInfo packageInfo = new PackageInfo(); + packageInfo.applicationInfo = new ApplicationInfo(); + packageInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; + when(getServices().userManager.getProfileParent(MANAGED_PROFILE_USER_ID)) + .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0)); + when(getServices().ipackageManager.getPackageInfo(packageName, + PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM)).thenReturn( + packageInfo); + when(getServices().ipackageManager.getPackageInfo(packageName, + PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_SYSTEM_ONLY, + UserHandle.USER_SYSTEM)).thenReturn(packageInfo); + + parentDpm.setApplicationHidden(admin1, packageName, true); + verify(getServices().ipackageManager).setApplicationHiddenSettingAsUser(packageName, + true, UserHandle.USER_SYSTEM); + + parentDpm.setApplicationHidden(admin1, packageName, false); + verify(getServices().ipackageManager).setApplicationHiddenSettingAsUser(packageName, + false, UserHandle.USER_SYSTEM); + } + public void testGetMacAddress() throws Exception { mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS); mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); |