Merge "Allow profile owners to protect packages." into tm-dev am: 20bd378d55

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18186904

Change-Id: I72b8d2006d13821ffc2bfe888d32be69ff4829df
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Pavel Grafov
2022-05-11 21:17:44 +00:00
committed by Automerger Merge Worker
6 changed files with 71 additions and 61 deletions

View File

@@ -14569,12 +14569,13 @@ public class DevicePolicyManager {
} }
/** /**
* Called by Device owner to disable user control over apps. User will not be able to clear * Called by a device owner or a profile owner to disable user control over apps. User will not
* app data or force-stop packages. * be able to clear app data or force-stop packages. When called by a device owner, applies to
* all users on the device.
* *
* @param admin which {@link DeviceAdminReceiver} this request is associated with * @param admin which {@link DeviceAdminReceiver} this request is associated with
* @param packages The package names for the apps. * @param packages The package names for the apps.
* @throws SecurityException if {@code admin} is not a device owner. * @throws SecurityException if {@code admin} is not a device owner or a profile owner.
*/ */
public void setUserControlDisabledPackages(@NonNull ComponentName admin, public void setUserControlDisabledPackages(@NonNull ComponentName admin,
@NonNull List<String> packages) { @NonNull List<String> packages) {
@@ -14589,12 +14590,14 @@ public class DevicePolicyManager {
} }
/** /**
* Returns the list of packages over which user control is disabled by the device owner. * Returns the list of packages over which user control is disabled by a device or profile
* owner.
* *
* @param admin which {@link DeviceAdminReceiver} this request is associated with * @param admin which {@link DeviceAdminReceiver} this request is associated with
* @throws SecurityException if {@code admin} is not a device owner. * @throws SecurityException if {@code admin} is not a device or profile owner.
*/ */
public @NonNull List<String> getUserControlDisabledPackages(@NonNull ComponentName admin) { @NonNull
public List<String> getUserControlDisabledPackages(@NonNull ComponentName admin) {
throwIfParentInstance("getUserControlDisabledPackages"); throwIfParentInstance("getUserControlDisabledPackages");
if (mService != null) { if (mService != null) {
try { try {

View File

@@ -371,10 +371,10 @@ public abstract class PackageManagerInternal {
int deviceOwnerUserId, String deviceOwner, SparseArray<String> profileOwners); int deviceOwnerUserId, String deviceOwner, SparseArray<String> profileOwners);
/** /**
* Called by Owners to set the package names protected by the device owner. * Marks packages as protected for a given user or all users in case of USER_ALL.
*/ */
public abstract void setDeviceOwnerProtectedPackages( public abstract void setOwnerProtectedPackages(
String deviceOwnerPackageName, List<String> packageNames); @UserIdInt int userId, @NonNull List<String> packageNames);
/** /**
* Returns {@code true} if a given package can't be wiped. Otherwise, returns {@code false}. * Returns {@code true} if a given package can't be wiped. Otherwise, returns {@code false}.

View File

@@ -352,10 +352,9 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal {
@Override @Override
@Deprecated @Deprecated
public final void setDeviceOwnerProtectedPackages( public final void setOwnerProtectedPackages(
String deviceOwnerPackageName, List<String> packageNames) { @UserIdInt int userId, @NonNull List<String> packageNames) {
getProtectedPackages().setDeviceOwnerProtectedPackages( getProtectedPackages().setOwnerProtectedPackages(userId, packageNames);
deviceOwnerPackageName, packageNames);
} }
@Override @Override

View File

@@ -16,11 +16,11 @@
package com.android.server.pm; package com.android.server.pm;
import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
import android.content.Context; import android.content.Context;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.SparseArray; import android.util.SparseArray;
@@ -56,7 +56,7 @@ public class ProtectedPackages {
@Nullable @Nullable
@GuardedBy("this") @GuardedBy("this")
private final ArrayMap<String, Set<String>> mDeviceOwnerProtectedPackages = new ArrayMap<>(); private final SparseArray<Set<String>> mOwnerProtectedPackages = new SparseArray<>();
private final Context mContext; private final Context mContext;
@@ -79,13 +79,13 @@ public class ProtectedPackages {
: profileOwnerPackages.clone(); : profileOwnerPackages.clone();
} }
/** Sets the protected packages for the device owner. */ /** Sets packages protected by a device or profile owner. */
public synchronized void setDeviceOwnerProtectedPackages( public synchronized void setOwnerProtectedPackages(
String deviceOwnerPackageName, List<String> packageNames) { @UserIdInt int userId, @NonNull List<String> packageNames) {
if (packageNames.isEmpty()) { if (packageNames.isEmpty()) {
mDeviceOwnerProtectedPackages.remove(deviceOwnerPackageName); mOwnerProtectedPackages.remove(userId);
} else { } else {
mDeviceOwnerProtectedPackages.put(deviceOwnerPackageName, new ArraySet<>(packageNames)); mOwnerProtectedPackages.put(userId, new ArraySet<>(packageNames));
} }
} }
@@ -123,19 +123,24 @@ public class ProtectedPackages {
* <p>A protected package means that, apart from the package owner, no system or privileged apps * <p>A protected package means that, apart from the package owner, no system or privileged apps
* can modify its data or package state. * can modify its data or package state.
*/ */
private synchronized boolean isProtectedPackage(String packageName) { private synchronized boolean isProtectedPackage(@UserIdInt int userId, String packageName) {
return packageName != null && (packageName.equals(mDeviceProvisioningPackage) return packageName != null && (packageName.equals(mDeviceProvisioningPackage)
|| isDeviceOwnerProtectedPackage(packageName)); || isOwnerProtectedPackage(userId, packageName));
} }
/** Returns {@code true} if the given package is a protected package set by any device owner. */ /**
private synchronized boolean isDeviceOwnerProtectedPackage(String packageName) { * Returns {@code true} if the given package is a protected package set by any device or
for (Set<String> protectedPackages : mDeviceOwnerProtectedPackages.values()) { * profile owner.
if (protectedPackages.contains(packageName)) { */
return true; private synchronized boolean isOwnerProtectedPackage(
} @UserIdInt int userId, String packageName) {
} return isPackageProtectedForUser(UserHandle.USER_ALL, packageName)
return false; || isPackageProtectedForUser(userId, packageName);
}
private synchronized boolean isPackageProtectedForUser(int userId, String packageName) {
int userIdx = mOwnerProtectedPackages.indexOfKey(userId);
return userIdx >= 0 && mOwnerProtectedPackages.valueAt(userIdx).contains(packageName);
} }
/** /**
@@ -146,7 +151,7 @@ public class ProtectedPackages {
*/ */
public boolean isPackageStateProtected(@UserIdInt int userId, String packageName) { public boolean isPackageStateProtected(@UserIdInt int userId, String packageName) {
return hasDeviceOwnerOrProfileOwner(userId, packageName) return hasDeviceOwnerOrProfileOwner(userId, packageName)
|| isProtectedPackage(packageName); || isProtectedPackage(userId, packageName);
} }
/** /**
@@ -155,6 +160,6 @@ public class ProtectedPackages {
*/ */
public boolean isPackageDataProtected(@UserIdInt int userId, String packageName) { public boolean isPackageDataProtected(@UserIdInt int userId, String packageName) {
return hasDeviceOwnerOrProfileOwner(userId, packageName) return hasDeviceOwnerOrProfileOwner(userId, packageName)
|| isProtectedPackage(packageName); || isProtectedPackage(userId, packageName);
} }
} }

View File

@@ -3116,6 +3116,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
deleteTransferOwnershipBundleLocked(metadata.userId); deleteTransferOwnershipBundleLocked(metadata.userId);
} }
updateSystemUpdateFreezePeriodsRecord(/* saveIfChanged */ true); updateSystemUpdateFreezePeriodsRecord(/* saveIfChanged */ true);
pushUserControlDisabledPackagesLocked(metadata.userId);
} }
private void maybeLogStart() { private void maybeLogStart() {
@@ -3178,18 +3179,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
startOwnerService(userId, "start-user"); startOwnerService(userId, "start-user");
} }
// TODO(b/218639412): Once PM stores these on a per-user basis, push even empty lists to handle
// DO/PO removal correctly.
void pushUserControlDisabledPackagesLocked(int userId) { void pushUserControlDisabledPackagesLocked(int userId) {
if (userId != mOwners.getDeviceOwnerUserId()) { final int targetUserId;
return; final ActiveAdmin owner;
if (getDeviceOwnerUserIdUncheckedLocked() == userId) {
owner = getDeviceOwnerAdminLocked();
targetUserId = UserHandle.USER_ALL;
} else {
owner = getProfileOwnerAdminLocked(userId);
targetUserId = userId;
} }
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
if (deviceOwner == null || deviceOwner.protectedPackages == null) { List<String> protectedPackages = (owner == null || owner.protectedPackages == null)
return; ? Collections.emptyList() : owner.protectedPackages;
} mInjector.binderWithCleanCallingIdentity(() ->
mInjector.getPackageManagerInternal().setDeviceOwnerProtectedPackages( mInjector.getPackageManagerInternal().setOwnerProtectedPackages(
deviceOwner.info.getPackageName(), deviceOwner.protectedPackages); targetUserId, protectedPackages));
} }
@Override @Override
@@ -16967,23 +16972,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null"); Objects.requireNonNull(who, "ComponentName is null");
Objects.requireNonNull(packages, "packages is null"); Objects.requireNonNull(packages, "packages is null");
final CallerIdentity caller = getCallerIdentity(who); final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization( Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) || isProfileOwner(caller)
isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller)); || isFinancedDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe( checkCanExecuteOrThrowUnsafe(
DevicePolicyManager.OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES); DevicePolicyManager.OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES);
synchronized (getLockObject()) { synchronized (getLockObject()) {
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(caller.getUserId());
if (!Objects.equals(deviceOwner.protectedPackages, packages)) { if (!Objects.equals(owner.protectedPackages, packages)) {
deviceOwner.protectedPackages = packages.isEmpty() ? null : packages; owner.protectedPackages = packages.isEmpty() ? null : packages;
saveSettingsLocked(caller.getUserId()); saveSettingsLocked(caller.getUserId());
pushUserControlDisabledPackagesLocked(caller.getUserId());
} }
} }
mInjector.binderWithCleanCallingIdentity(
() -> mInjector.getPackageManagerInternal().setDeviceOwnerProtectedPackages(
who.getPackageName(), packages));
DevicePolicyEventLogger DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_USER_CONTROL_DISABLED_PACKAGES) .createEvent(DevicePolicyEnums.SET_USER_CONTROL_DISABLED_PACKAGES)
.setAdmin(who) .setAdmin(who)
@@ -16996,11 +16998,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null"); Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who); final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization( Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) || isProfileOwner(caller)
isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller)); || isFinancedDeviceOwner(caller));
synchronized (getLockObject()) { synchronized (getLockObject()) {
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); ActiveAdmin deviceOwner = getDeviceOrProfileOwnerAdminLocked(caller.getUserId());
return deviceOwner.protectedPackages != null return deviceOwner.protectedPackages != null
? deviceOwner.protectedPackages : Collections.emptyList(); ? deviceOwner.protectedPackages : Collections.emptyList();
} }

View File

@@ -6996,22 +6996,23 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setUserControlDisabledPackages(admin1, testPackages); dpm.setUserControlDisabledPackages(admin1, testPackages);
verify(getServices().packageManagerInternal) verify(getServices().packageManagerInternal)
.setDeviceOwnerProtectedPackages(admin1.getPackageName(), testPackages); .setOwnerProtectedPackages(UserHandle.USER_ALL, testPackages);
assertThat(dpm.getUserControlDisabledPackages(admin1)).isEqualTo(testPackages); assertThat(dpm.getUserControlDisabledPackages(admin1)).isEqualTo(testPackages);
} }
@Test @Test
public void testSetUserControlDisabledPackages_failingAsPO() { public void testSetUserControlDisabledPackages_asPO() {
final List<String> testPackages = new ArrayList<>(); final List<String> testPackages = new ArrayList<>();
testPackages.add("package_1"); testPackages.add("package_1");
testPackages.add("package_2"); testPackages.add("package_2");
mServiceContext.permissions.add(permission.MANAGE_DEVICE_ADMINS); mServiceContext.permissions.add(permission.MANAGE_DEVICE_ADMINS);
setAsProfileOwner(admin1); setAsProfileOwner(admin1);
assertExpectException(SecurityException.class, /* messageRegex= */ null, dpm.setUserControlDisabledPackages(admin1, testPackages);
() -> dpm.setUserControlDisabledPackages(admin1, testPackages));
assertExpectException(SecurityException.class, /* messageRegex= */ null, verify(getServices().packageManagerInternal)
() -> dpm.getUserControlDisabledPackages(admin1)); .setOwnerProtectedPackages(CALLER_USER_HANDLE, testPackages);
assertThat(dpm.getUserControlDisabledPackages(admin1)).isEqualTo(testPackages);
} }
private void configureProfileOwnerOfOrgOwnedDevice(ComponentName who, int userId) { private void configureProfileOwnerOfOrgOwnedDevice(ComponentName who, int userId) {
@@ -7845,7 +7846,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setUserControlDisabledPackages(admin1, packages); dpm.setUserControlDisabledPackages(admin1, packages);
verify(getServices().packageManagerInternal) verify(getServices().packageManagerInternal)
.setDeviceOwnerProtectedPackages(eq(admin1.getPackageName()), eq(packages)); .setOwnerProtectedPackages(eq(UserHandle.USER_ALL), eq(packages));
} }
@Test @Test