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:
@@ -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 {
|
||||||
|
|||||||
@@ -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}.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user