From ca761783a67cc3b1fdcb386883dc517f2a54e3e5 Mon Sep 17 00:00:00 2001 From: Pavel Grafov Date: Tue, 3 May 2022 19:24:26 +0100 Subject: [PATCH] Move DO protected packages to ActiveAdmin This is needed to allow POs to use this policy. After this change PackageManagerInternal isn't updated when transferring ownership, and thus retains the old DPC package in its map. This will be addressed in the next CL on the package manager side: owner package -> protected packages map will be replaced with one keyed by userId, so such update won't be necessary. Bug: 218639412 Test: atest com.android.server.devicepolicy Test: atest UserControlDisabledPackagesTest Test: atest DeviceOwnerTest#testSetUserControlDisabledPackages_singleUser_reboot_verifyPackageNotStopped Change-Id: I19c568461fdb4b341c9e3d4e7e101c859af176b6 --- .../server/devicepolicy/ActiveAdmin.java | 23 +++- .../server/devicepolicy/DevicePolicyData.java | 28 +++-- .../DevicePolicyManagerService.java | 71 ++++++----- .../android/server/devicepolicy/Owners.java | 52 --------- .../server/devicepolicy/OwnersData.java | 25 ++-- .../devicepolicy/PolicyVersionUpgrader.java | 109 +++++++++++++---- .../protected_packages_device_owner_2.xml | 6 + .../protected_packages_device_policies.xml | 13 +++ .../PolicyVersionUpgraderTest.java | 110 +++++++++++++----- 9 files changed, 262 insertions(+), 175 deletions(-) create mode 100644 services/tests/servicestests/assets/PolicyVersionUpgraderTest/protected_packages_device_owner_2.xml create mode 100644 services/tests/servicestests/assets/PolicyVersionUpgraderTest/protected_packages_device_policies.xml diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java index 3912991a41edd..0c69067ab1311 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java @@ -157,13 +157,14 @@ class ActiveAdmin { private static final String TAG_SSID_ALLOWLIST = "ssid-allowlist"; private static final String TAG_SSID_DENYLIST = "ssid-denylist"; private static final String TAG_SSID = "ssid"; - private static final String ATTR_VALUE = "value"; - private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification"; - private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications"; private static final String TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIGS = "preferential_network_service_configs"; private static final String TAG_PREFERENTIAL_NETWORK_SERVICE_CONFIG = "preferential_network_service_config"; + private static final String TAG_PROTECTED_PACKAGES = "protected_packages"; + private static final String ATTR_VALUE = "value"; + private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification"; + private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications"; DeviceAdminInfo info; @@ -253,6 +254,9 @@ class ActiveAdmin { // List of package names to keep cached. List keepUninstalledPackages; + // List of packages for which the user cannot invoke "clear data" or "force stop". + List protectedPackages; + // Wi-Fi SSID restriction policy. WifiSsidPolicy mWifiSsidPolicy; @@ -505,6 +509,7 @@ class ActiveAdmin { permittedNotificationListeners); writePackageListToXml(out, TAG_KEEP_UNINSTALLED_PACKAGES, keepUninstalledPackages); writePackageListToXml(out, TAG_METERED_DATA_DISABLED_PACKAGES, meteredDisabledPackages); + writePackageListToXml(out, TAG_PROTECTED_PACKAGES, protectedPackages); if (hasUserRestrictions()) { UserRestrictionsUtils.writeRestrictions( out, userRestrictions, TAG_USER_RESTRICTIONS); @@ -771,6 +776,8 @@ class ActiveAdmin { keepUninstalledPackages = readPackageList(parser, tag); } else if (TAG_METERED_DATA_DISABLED_PACKAGES.equals(tag)) { meteredDisabledPackages = readPackageList(parser, tag); + } else if (TAG_PROTECTED_PACKAGES.equals(tag)) { + protectedPackages = readPackageList(parser, tag); } else if (TAG_USER_RESTRICTIONS.equals(tag)) { userRestrictions = UserRestrictionsUtils.readRestrictions(parser); } else if (TAG_DEFAULT_ENABLED_USER_RESTRICTIONS.equals(tag)) { @@ -1210,6 +1217,16 @@ class ActiveAdmin { pw.println(keepUninstalledPackages); } + if (meteredDisabledPackages != null) { + pw.print("meteredDisabledPackages="); + pw.println(meteredDisabledPackages); + } + + if (protectedPackages != null) { + pw.print("protectedPackages="); + pw.println(protectedPackages); + } + pw.print("organizationColor="); pw.println(organizationColor); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java index 48a436f158038..fd97db23f01aa 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java @@ -17,6 +17,7 @@ package com.android.server.devicepolicy; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManager; @@ -129,8 +130,10 @@ class DevicePolicyData { // This is the list of component allowed to start lock task mode. List mLockTaskPackages = new ArrayList<>(); - // List of packages protected by device owner - List mUserControlDisabledPackages = new ArrayList<>(); + /** @deprecated moved to {@link ActiveAdmin#protectedPackages}. */ + @Deprecated + @Nullable + List mUserControlDisabledPackages; // Bitfield of feature flags to be enabled during LockTask mode. // We default on the power button menu, in order to be consistent with pre-P behaviour. @@ -364,13 +367,6 @@ class DevicePolicyData { out.endTag(null, TAG_OWNER_INSTALLED_CA_CERT); } - for (int i = 0, size = policyData.mUserControlDisabledPackages.size(); i < size; i++) { - String packageName = policyData.mUserControlDisabledPackages.get(i); - out.startTag(null, TAG_PROTECTED_PACKAGES); - out.attribute(null, ATTR_NAME, packageName); - out.endTag(null, TAG_PROTECTED_PACKAGES); - } - if (policyData.mAppsSuspended) { out.startTag(null, TAG_APPS_SUSPENDED); out.attributeBoolean(null, ATTR_VALUE, policyData.mAppsSuspended); @@ -473,7 +469,7 @@ class DevicePolicyData { policy.mAdminMap.clear(); policy.mAffiliationIds.clear(); policy.mOwnerInstalledCaCerts.clear(); - policy.mUserControlDisabledPackages.clear(); + policy.mUserControlDisabledPackages = null; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { @@ -561,15 +557,19 @@ class DevicePolicyData { policy.mCurrentInputMethodSet = true; } else if (TAG_OWNER_INSTALLED_CA_CERT.equals(tag)) { policy.mOwnerInstalledCaCerts.add(parser.getAttributeValue(null, ATTR_ALIAS)); - } else if (TAG_PROTECTED_PACKAGES.equals(tag)) { - policy.mUserControlDisabledPackages.add( - parser.getAttributeValue(null, ATTR_NAME)); } else if (TAG_APPS_SUSPENDED.equals(tag)) { policy.mAppsSuspended = parser.getAttributeBoolean(null, ATTR_VALUE, false); } else if (TAG_BYPASS_ROLE_QUALIFICATIONS.equals(tag)) { policy.mBypassDevicePolicyManagementRoleQualifications = true; policy.mCurrentRoleHolder = parser.getAttributeValue(null, ATTR_VALUE); + // Deprecated tags below + } else if (TAG_PROTECTED_PACKAGES.equals(tag)) { + if (policy.mUserControlDisabledPackages == null) { + policy.mUserControlDisabledPackages = new ArrayList<>(); + } + policy.mUserControlDisabledPackages.add( + parser.getAttributeValue(null, ATTR_NAME)); } else { Slogf.w(TAG, "Unknown tag: %s", tag); XmlUtils.skipCurrentTag(parser); @@ -674,8 +674,6 @@ class DevicePolicyData { pw.increaseIndent(); pw.print("mPasswordOwner="); pw.println(mPasswordOwner); pw.print("mPasswordTokenHandle="); pw.println(Long.toHexString(mPasswordTokenHandle)); - pw.print("mUserControlDisabledPackages="); - pw.println(mUserControlDisabledPackages); pw.print("mAppsSuspended="); pw.println(mAppsSuspended); pw.print("mUserSetupComplete="); pw.println(mUserSetupComplete); pw.print("mAffiliationIds="); pw.println(mAffiliationIds); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 8a7134e24cf86..372cb5d244e85 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -536,7 +536,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // to decide whether an existing policy in the {@link #DEVICE_POLICIES_XML} needs to // be upgraded. See {@link PolicyVersionUpgrader} on instructions how to add an upgrade // step. - static final int DPMS_VERSION = 2; + static final int DPMS_VERSION = 3; static { SECURE_SETTINGS_ALLOWLIST = new ArraySet<>(); @@ -1908,38 +1908,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (userHandle == UserHandle.USER_SYSTEM) { mStateCache.setDeviceProvisioned(policy.mUserSetupComplete); } - - migrateDeviceOwnerProtectedPackagesToOwners(userHandle, policy); } return policy; } } - /** - * Only used by {@link #getUserData(int)} to migrate existing device owner protected - * packages that were stored in {@link DevicePolicyData#mUserControlDisabledPackages} to - * {@link Owners} because the device owner protected packages are now stored on a per device - * owner basis instead of on a per user basis. - * - * Any calls to {@link #setUserControlDisabledPackages(ComponentName, List)} would now store - * the device owner protected packages in {@link Owners} instead of {@link DevicePolicyData}. - * @param userHandle The device owner user - * @param policy The policy data of the device owner user - */ - private void migrateDeviceOwnerProtectedPackagesToOwners( - int userHandle, DevicePolicyData policy) { - ComponentName deviceOwnerComponent = getOwnerComponent(userHandle); - if (isDeviceOwner(deviceOwnerComponent, userHandle) - && !policy.mUserControlDisabledPackages.isEmpty()) { - mOwners.setDeviceOwnerProtectedPackages( - deviceOwnerComponent.getPackageName(), - policy.mUserControlDisabledPackages); - - policy.mUserControlDisabledPackages = new ArrayList<>(); - saveSettingsLocked(userHandle); - } - } - /** * Creates and loads the policy data from xml for data that is shared between * various profiles of a user. In contrast to {@link #getUserData(int)} @@ -3182,6 +3155,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { void handleStartUser(int userId) { synchronized (getLockObject()) { pushScreenCapturePolicy(userId); + pushUserControlDisabledPackagesLocked(userId); } pushUserRestrictions(userId); // When system user is started (device boot), load cache for all users. @@ -3204,6 +3178,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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) { + if (userId != mOwners.getDeviceOwnerUserId()) { + return; + } + ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); + if (deviceOwner == null || deviceOwner.protectedPackages == null) { + return; + } + mInjector.getPackageManagerInternal().setDeviceOwnerProtectedPackages( + deviceOwner.info.getPackageName(), deviceOwner.protectedPackages); + } + @Override void handleUnlockUser(int userId) { startOwnerService(userId, "unlock-user"); @@ -8795,6 +8783,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { setNetworkLoggingActiveInternal(false); deleteTransferOwnershipBundleLocked(userId); toggleBackupServiceActive(UserHandle.USER_SYSTEM, true); + pushUserControlDisabledPackagesLocked(userId); } private void clearApplicationRestrictions(int userId) { @@ -8979,7 +8968,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { policy.mLockTaskPackages.clear(); updateLockTaskPackagesLocked(policy.mLockTaskPackages, userId); policy.mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_NONE; - policy.mUserControlDisabledPackages.clear(); saveSettingsLocked(userId); try { @@ -16976,13 +16964,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { DevicePolicyManager.OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES); synchronized (getLockObject()) { - mOwners.setDeviceOwnerProtectedPackages(who.getPackageName(), packages); - DevicePolicyEventLogger - .createEvent(DevicePolicyEnums.SET_USER_CONTROL_DISABLED_PACKAGES) - .setAdmin(who) - .setStrings(packages.toArray(new String[packages.size()])) - .write(); + ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); + if (!Objects.equals(deviceOwner.protectedPackages, packages)) { + deviceOwner.protectedPackages = packages.isEmpty() ? null : packages; + saveSettingsLocked(caller.getUserId()); + } } + + mInjector.binderWithCleanCallingIdentity( + () -> mInjector.getPackageManagerInternal().setDeviceOwnerProtectedPackages( + who.getPackageName(), packages)); + + DevicePolicyEventLogger + .createEvent(DevicePolicyEnums.SET_USER_CONTROL_DISABLED_PACKAGES) + .setAdmin(who) + .setStrings(packages.toArray(new String[packages.size()])) + .write(); } @Override @@ -16994,7 +16991,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller)); synchronized (getLockObject()) { - return mOwners.getDeviceOwnerProtectedPackages(who.getPackageName()); + ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); + return deviceOwner.protectedPackages != null + ? deviceOwner.protectedPackages : Collections.emptyList(); } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java index d1c6b3411b202..08bd3e4c7c47e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java @@ -31,7 +31,6 @@ import android.os.Binder; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; -import android.util.ArrayMap; import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Pair; @@ -49,7 +48,6 @@ import com.android.server.wm.ActivityTaskManagerInternal; import java.io.File; import java.time.LocalDate; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; @@ -108,12 +106,6 @@ class Owners { notifyChangeLocked(); pushToActivityTaskManagerLocked(); - - for (ArrayMap.Entry> entry : - mData.mDeviceOwnerProtectedPackages.entrySet()) { - mPackageManagerInternal.setDeviceOwnerProtectedPackages( - entry.getKey(), entry.getValue()); - } } } @@ -247,12 +239,6 @@ class Owners { void clearDeviceOwner() { synchronized (mData) { mData.mDeviceOwnerTypes.remove(mData.mDeviceOwner.packageName); - List protectedPackages = - mData.mDeviceOwnerProtectedPackages.remove(mData.mDeviceOwner.packageName); - if (protectedPackages != null) { - mPackageManagerInternal.setDeviceOwnerProtectedPackages( - mData.mDeviceOwner.packageName, new ArrayList<>()); - } mData.mDeviceOwner = null; mData.mDeviceOwnerUserId = UserHandle.USER_NULL; @@ -296,12 +282,6 @@ class Owners { synchronized (mData) { Integer previousDeviceOwnerType = mData.mDeviceOwnerTypes.remove( mData.mDeviceOwner.packageName); - List previousProtectedPackages = - mData.mDeviceOwnerProtectedPackages.remove(mData.mDeviceOwner.packageName); - if (previousProtectedPackages != null) { - mPackageManagerInternal.setDeviceOwnerProtectedPackages( - mData.mDeviceOwner.packageName, new ArrayList<>()); - } // We don't set a name because it's not used anyway. // See DevicePolicyManagerService#getDeviceOwnerName mData.mDeviceOwner = new OwnerInfo(null, target, @@ -313,10 +293,6 @@ class Owners { mData.mDeviceOwnerTypes.put( mData.mDeviceOwner.packageName, previousDeviceOwnerType); } - if (previousProtectedPackages != null) { - mData.mDeviceOwnerProtectedPackages.put( - mData.mDeviceOwner.packageName, previousProtectedPackages); - } notifyChangeLocked(); pushToActivityTaskManagerLocked(); } @@ -504,34 +480,6 @@ class Owners { } } - void setDeviceOwnerProtectedPackages(String packageName, List protectedPackages) { - synchronized (mData) { - if (!hasDeviceOwner()) { - Slog.e(TAG, - "Attempting to set device owner protected packages when there is no " - + "device owner"); - return; - } else if (!mData.mDeviceOwner.packageName.equals(packageName)) { - Slog.e(TAG, "Attempting to set device owner protected packages when the provided " - + "package name " + packageName - + " does not match the device owner package name"); - return; - } - - mData.mDeviceOwnerProtectedPackages.put(packageName, protectedPackages); - mPackageManagerInternal.setDeviceOwnerProtectedPackages(packageName, protectedPackages); - writeDeviceOwner(); - } - } - - List getDeviceOwnerProtectedPackages(String packageName) { - synchronized (mData) { - return mData.mDeviceOwnerProtectedPackages.containsKey(packageName) - ? mData.mDeviceOwnerProtectedPackages.get(packageName) - : Collections.emptyList(); - } - } - void writeDeviceOwner() { synchronized (mData) { pushToDevicePolicyManager(); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java index 4fe4f0d83f1ae..694842034d1fc 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java @@ -91,8 +91,10 @@ class OwnersData { // Device owner type for a managed device. final ArrayMap mDeviceOwnerTypes = new ArrayMap<>(); - final ArrayMap> mDeviceOwnerProtectedPackages = new ArrayMap<>(); - + /** @deprecated moved to {@link ActiveAdmin#protectedPackages}. */ + @Deprecated + @Nullable + ArrayMap> mDeviceOwnerProtectedPackages; // Internal state for the profile owner packages. final ArrayMap mProfileOwners = new ArrayMap<>(); @@ -366,21 +368,6 @@ class OwnersData { } } - if (!mDeviceOwnerProtectedPackages.isEmpty()) { - for (ArrayMap.Entry> entry : - mDeviceOwnerProtectedPackages.entrySet()) { - List protectedPackages = entry.getValue(); - - out.startTag(null, TAG_DEVICE_OWNER_PROTECTED_PACKAGES); - out.attribute(null, ATTR_PACKAGE, entry.getKey()); - out.attributeInt(null, ATTR_SIZE, protectedPackages.size()); - for (int i = 0, size = protectedPackages.size(); i < size; i++) { - out.attribute(null, ATTR_NAME + i, protectedPackages.get(i)); - } - out.endTag(null, TAG_DEVICE_OWNER_PROTECTED_PACKAGES); - } - } - if (mSystemUpdatePolicy != null) { out.startTag(null, TAG_SYSTEM_UPDATE_POLICY); mSystemUpdatePolicy.saveToXml(out); @@ -444,6 +431,7 @@ class OwnersData { null, ATTR_DEVICE_OWNER_TYPE_VALUE, DEVICE_OWNER_TYPE_DEFAULT); mDeviceOwnerTypes.put(packageName, deviceOwnerType); break; + // Deprecated fields below. case TAG_DEVICE_OWNER_PROTECTED_PACKAGES: packageName = parser.getAttributeValue(null, ATTR_PACKAGE); int protectedPackagesSize = parser.getAttributeInt(null, ATTR_SIZE, 0); @@ -451,6 +439,9 @@ class OwnersData { for (int i = 0; i < protectedPackagesSize; i++) { protectedPackages.add(parser.getAttributeValue(null, ATTR_NAME + i)); } + if (mDeviceOwnerProtectedPackages == null) { + mDeviceOwnerProtectedPackages = new ArrayMap<>(); + } mDeviceOwnerProtectedPackages.put(packageName, protectedPackages); break; default: diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java index 7556d690f6fd0..253851cdbf68e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java @@ -16,6 +16,7 @@ package com.android.server.devicepolicy; +import android.annotation.Nullable; import android.content.ComponentName; import android.os.UserHandle; import android.util.Slog; @@ -28,6 +29,8 @@ import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; /** * Class for dealing with Device Policy Manager Service version upgrades. @@ -91,30 +94,82 @@ public class PolicyVersionUpgrader { if (currentVersion == 1) { Slog.i(LOG_TAG, String.format("Upgrading from version %d", currentVersion)); - // This upgrade step is for Device Owner scenario only: For devices upgrading to S, - // if there is a device owner, it retains the ability to control sensors-related - // permission grants. - for (int userId : allUsers) { - DevicePolicyData userData = allUsersData.get(userId); - if (userData == null) { - continue; - } - for (ActiveAdmin admin : userData.mAdminList) { - if (ownersData.mDeviceOwnerUserId == userId - && ownersData.mDeviceOwner != null - && ownersData.mDeviceOwner.admin.equals(admin.info.getComponent())) { - Slog.i(LOG_TAG, String.format( - "Marking Device Owner in user %d for permission grant ", userId)); - admin.mAdminCanGrantSensorsPermissions = true; - } - } - } + upgradeSensorPermissionsAccess(allUsers, ownersData, allUsersData); currentVersion = 2; } + if (currentVersion == 2) { + Slog.i(LOG_TAG, String.format("Upgrading from version %d", currentVersion)); + upgradeProtectedPackages(ownersData, allUsersData); + currentVersion = 3; + } + writePoliciesAndVersion(allUsers, allUsersData, ownersData, currentVersion); } + /** + * This upgrade step is for Device Owner scenario only: For devices upgrading to S, if there is + * a device owner, it retains the ability to control sensors-related permission grants. + */ + private void upgradeSensorPermissionsAccess( + int[] allUsers, OwnersData ownersData, SparseArray allUsersData) { + for (int userId : allUsers) { + DevicePolicyData userData = allUsersData.get(userId); + if (userData == null) { + continue; + } + for (ActiveAdmin admin : userData.mAdminList) { + if (ownersData.mDeviceOwnerUserId == userId + && ownersData.mDeviceOwner != null + && ownersData.mDeviceOwner.admin.equals(admin.info.getComponent())) { + Slog.i(LOG_TAG, String.format( + "Marking Device Owner in user %d for permission grant ", userId)); + admin.mAdminCanGrantSensorsPermissions = true; + } + } + } + } + + /** + * This upgrade step moves device owner protected packages to ActiveAdmin. + * Initially these packages were stored in DevicePolicyData, then moved to Owners without + * employing PolicyVersionUpgrader. Here we check both places. + */ + private void upgradeProtectedPackages( + OwnersData ownersData, SparseArray allUsersData) { + if (ownersData.mDeviceOwner == null) { + return; + } + List protectedPackages = null; + DevicePolicyData doUserData = allUsersData.get(ownersData.mDeviceOwnerUserId); + if (doUserData == null) { + Slog.e(LOG_TAG, "No policy data for do user"); + return; + } + if (ownersData.mDeviceOwnerProtectedPackages != null) { + protectedPackages = ownersData.mDeviceOwnerProtectedPackages + .get(ownersData.mDeviceOwner.packageName); + if (protectedPackages != null) { + Slog.i(LOG_TAG, "Found protected packages in Owners"); + } + ownersData.mDeviceOwnerProtectedPackages = null; + } else if (doUserData.mUserControlDisabledPackages != null) { + Slog.i(LOG_TAG, "Found protected packages in DevicePolicyData"); + protectedPackages = doUserData.mUserControlDisabledPackages; + doUserData.mUserControlDisabledPackages = null; + } + + ActiveAdmin doAdmin = doUserData.mAdminMap.get(ownersData.mDeviceOwner.admin); + if (doAdmin == null) { + Slog.e(LOG_TAG, "DO admin not found in DO user"); + return; + } + + if (protectedPackages != null) { + doAdmin.protectedPackages = new ArrayList<>(protectedPackages); + } + } + private OwnersData loadOwners(int[] allUsers) { OwnersData ownersData = new OwnersData(mPathProvider); ownersData.load(allUsers); @@ -146,17 +201,23 @@ public class PolicyVersionUpgrader { OwnersData ownersData) { final SparseArray allUsersData = new SparseArray<>(); for (int user: allUsers) { - ComponentName owner = null; - if (ownersData.mDeviceOwnerUserId == user && ownersData.mDeviceOwner != null) { - owner = ownersData.mDeviceOwner.admin; - } else if (ownersData.mProfileOwners.containsKey(user)) { - owner = ownersData.mProfileOwners.get(user).admin; - } + ComponentName owner = getOwnerForUser(ownersData, user); allUsersData.append(user, loadDataForUser(user, loadVersion, owner)); } return allUsersData; } + @Nullable + private ComponentName getOwnerForUser(OwnersData ownersData, int user) { + ComponentName owner = null; + if (ownersData.mDeviceOwnerUserId == user && ownersData.mDeviceOwner != null) { + owner = ownersData.mDeviceOwner.admin; + } else if (ownersData.mProfileOwners.containsKey(user)) { + owner = ownersData.mProfileOwners.get(user).admin; + } + return owner; + } + private DevicePolicyData loadDataForUser( int userId, int loadVersion, ComponentName ownerComponent) { DevicePolicyData policy = new DevicePolicyData(userId); diff --git a/services/tests/servicestests/assets/PolicyVersionUpgraderTest/protected_packages_device_owner_2.xml b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/protected_packages_device_owner_2.xml new file mode 100644 index 0000000000000..0725d25cdcab3 --- /dev/null +++ b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/protected_packages_device_owner_2.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/services/tests/servicestests/assets/PolicyVersionUpgraderTest/protected_packages_device_policies.xml b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/protected_packages_device_policies.xml new file mode 100644 index 0000000000000..2d06ee6dca0e8 --- /dev/null +++ b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/protected_packages_device_policies.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/PolicyVersionUpgraderTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/PolicyVersionUpgraderTest.java index 9efc10cb55ec9..412722d68f436 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/PolicyVersionUpgraderTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/PolicyVersionUpgraderTest.java @@ -63,8 +63,9 @@ import java.util.function.Function; public class PolicyVersionUpgraderTest extends DpmTestBase { // NOTE: Only change this value if the corresponding CL also adds a test to test the upgrade // to the new version. - private static final int LATEST_TESTED_VERSION = 2; + private static final int LATEST_TESTED_VERSION = 3; public static final String PERMISSIONS_TAG = "admin-can-grant-sensors-permissions"; + public static final String DEVICE_OWNER_XML = "device_owner_2.xml"; private ComponentName mFakeAdmin; private class FakePolicyUpgraderDataProvider implements PolicyUpgraderDataProvider { @@ -119,18 +120,18 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { mUpgrader = new PolicyVersionUpgrader(mProvider, getServices().pathProvider); mFakeAdmin = new ComponentName( "com.android.frameworks.servicestests", - "com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"); + "com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"); ActivityInfo activityInfo = createActivityInfo(mFakeAdmin); DeviceAdminInfo dai = createDeviceAdminInfo(activityInfo); mProvider.mComponentToDeviceAdminInfo.put(mFakeAdmin, dai); - mProvider.mUsers = new int[] {0}; + mProvider.mUsers = new int[]{0}; } @Test public void testSameVersionDoesNothing() throws IOException { writeVersionToXml(DevicePolicyManagerService.DPMS_VERSION); final int userId = mProvider.mUsers[0]; - preparePoliciesFile(userId); + preparePoliciesFile(userId, "device_policies.xml"); String oldContents = readPoliciesFile(userId); mUpgrader.upgradePolicy(DevicePolicyManagerService.DPMS_VERSION); @@ -142,19 +143,19 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { @Test public void testUpgrade0To1RemovesPasswordMetrics() throws IOException, XmlPullParserException { final String activePasswordTag = "active-password"; - mProvider.mUsers = new int[] {0, 10}; + mProvider.mUsers = new int[]{0, 10}; getServices().addUser(10, /* flags= */ 0, USER_TYPE_PROFILE_MANAGED); writeVersionToXml(0); for (int userId : mProvider.mUsers) { - preparePoliciesFile(userId); + preparePoliciesFile(userId, "device_policies.xml"); } // Validate test set-up. assertThat(isTagPresent(readPoliciesFileToStream(0), activePasswordTag)).isTrue(); mUpgrader.upgradePolicy(1); - assertThat(readVersionFromXml()).isGreaterThan(1); - for (int user: mProvider.mUsers) { + assertThat(readVersionFromXml()).isAtLeast(1); + for (int user : mProvider.mUsers) { assertThat(isTagPresent(readPoliciesFileToStream(user), activePasswordTag)).isFalse(); } } @@ -163,17 +164,17 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { public void testUpgrade1To2MarksDoForPermissionControl() throws IOException, XmlPullParserException { final int ownerUser = 10; - mProvider.mUsers = new int[] {0, ownerUser}; + mProvider.mUsers = new int[]{0, ownerUser}; getServices().addUser(ownerUser, FLAG_PRIMARY, USER_TYPE_FULL_SYSTEM); writeVersionToXml(1); for (int userId : mProvider.mUsers) { - preparePoliciesFile(userId); + preparePoliciesFile(userId, "device_policies.xml"); } - prepareDeviceOwnerFile(ownerUser); + prepareDeviceOwnerFile(ownerUser, "device_owner_2.xml"); mUpgrader.upgradePolicy(2); - assertThat(readVersionFromXml()).isEqualTo(2); + assertThat(readVersionFromXml()).isAtLeast(2); assertThat(getBooleanValueTag(readPoliciesFileToStream(mProvider.mUsers[0]), PERMISSIONS_TAG)).isFalse(); assertThat(getBooleanValueTag(readPoliciesFileToStream(ownerUser), @@ -186,8 +187,8 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { getServices().addUser(ownerUser, FLAG_PRIMARY, USER_TYPE_FULL_SYSTEM); setUpPackageManagerForAdmin(admin1, UserHandle.getUid(ownerUser, 123 /* admin app ID */)); writeVersionToXml(0); - preparePoliciesFile(ownerUser); - prepareDeviceOwnerFile(ownerUser); + preparePoliciesFile(ownerUser, "device_policies.xml"); + prepareDeviceOwnerFile(ownerUser, "device_owner_2.xml"); DevicePolicyManagerServiceTestable dpms; final long ident = getContext().binder.clearCallingIdentity(); @@ -202,11 +203,65 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { getContext().binder.restoreCallingIdentity(ident); } + assertThat(readVersionFromXml()).isEqualTo(DevicePolicyManagerService.DPMS_VERSION); + // DO should be marked as able to grant sensors permission during upgrade and should be // reported as such via the API. assertThat(dpms.canAdminGrantSensorsPermissionsForUser(ownerUser)).isTrue(); } + /** + * Up to Android R DO protected packages were stored in DevicePolicyData, verify that they are + * moved to ActiveAdmin. + */ + @Test + public void testUserControlDisabledPackagesFromR() throws Exception { + final String oldTag = "protected-packages"; + final String newTag = "protected_packages"; + final int ownerUser = 0; + mProvider.mUsers = new int[]{0}; + getServices().addUser(ownerUser, FLAG_PRIMARY, USER_TYPE_FULL_SYSTEM); + writeVersionToXml(2); + preparePoliciesFile(ownerUser, "protected_packages_device_policies.xml"); + prepareDeviceOwnerFile(ownerUser, "device_owner_2.xml"); + + // Validate the setup. + assertThat(isTagPresent(readPoliciesFileToStream(ownerUser), oldTag)).isTrue(); + assertThat(isTagPresent(readPoliciesFileToStream(ownerUser), newTag)).isFalse(); + + mUpgrader.upgradePolicy(3); + + assertThat(readVersionFromXml()).isAtLeast(3); + assertThat(isTagPresent(readPoliciesFileToStream(ownerUser), oldTag)).isFalse(); + assertThat(isTagPresent(readPoliciesFileToStream(ownerUser), newTag)).isTrue(); + } + + /** + * In Android S DO protected packages were stored in Owners, verify that they are moved to + * ActiveAdmin. + */ + @Test + public void testUserControlDisabledPackagesFromS() throws Exception { + final String oldTag = "device-owner-protected-packages"; + final String newTag = "protected_packages"; + final int ownerUser = 0; + mProvider.mUsers = new int[]{0}; + getServices().addUser(ownerUser, FLAG_PRIMARY, USER_TYPE_FULL_SYSTEM); + writeVersionToXml(2); + preparePoliciesFile(ownerUser, "device_policies.xml"); + prepareDeviceOwnerFile(ownerUser, "protected_packages_device_owner_2.xml"); + + // Validate the setup. + assertThat(isTagPresent(readDoToStream(), oldTag)).isTrue(); + assertThat(isTagPresent(readPoliciesFileToStream(ownerUser), newTag)).isFalse(); + + mUpgrader.upgradePolicy(3); + + assertThat(readVersionFromXml()).isAtLeast(3); + assertThat(isTagPresent(readDoToStream(), oldTag)).isFalse(); + assertThat(isTagPresent(readPoliciesFileToStream(ownerUser), newTag)).isTrue(); + } + @Test public void isLatestVersionTested() { assertThat(DevicePolicyManagerService.DPMS_VERSION).isEqualTo(LATEST_TESTED_VERSION); @@ -226,32 +281,27 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { return Integer.parseInt(versionString); } - private void preparePoliciesFile(int userId) throws IOException { + private void preparePoliciesFile(int userId, String assetFile) throws IOException { JournaledFile policiesFile = mProvider.makeDevicePoliciesJournaledFile(userId); DpmTestUtils.writeToFile( policiesFile.chooseForWrite(), - DpmTestUtils.readAsset(mRealTestContext, - "PolicyVersionUpgraderTest/device_policies.xml")); + DpmTestUtils.readAsset(mRealTestContext, "PolicyVersionUpgraderTest/" + assetFile)); policiesFile.commit(); } - private void prepareDeviceOwnerFile(int userId) throws IOException { - File parentDir = getServices().pathProvider.getDataSystemDirectory(); - File doFilePath = (new File(parentDir, "device_owner_2.xml")).getAbsoluteFile(); - android.util.Log.i("YYYYYY", "DO paath: " + doFilePath); + private void prepareDeviceOwnerFile(int userId, String assetFile) throws IOException { + File doFilePath = getDoFilePath(); String doFileContent = DpmTestUtils.readAsset(mRealTestContext, - "PolicyVersionUpgraderTest/device_owner_2.xml") + "PolicyVersionUpgraderTest/" + assetFile) // Substitute the right DO userId, XML in resources has 0 .replace("userId=\"0\"", "userId=\"" + userId + "\""); DpmTestUtils.writeToFile(doFilePath, doFileContent); } - private void prepareProfileOwnerFile(int userId) throws IOException { - File parentDir = getServices().pathProvider.getUserSystemDirectory(userId); - DpmTestUtils.writeToFile( - (new File(parentDir, "profile_owner.xml")).getAbsoluteFile(), - DpmTestUtils.readAsset(mRealTestContext, - "PolicyVersionUpgraderTest/profile_owner.xml")); + private File getDoFilePath() { + File parentDir = getServices().pathProvider.getDataSystemDirectory(); + File doFilePath = (new File(parentDir, DEVICE_OWNER_XML)).getAbsoluteFile(); + return doFilePath; } private String readPoliciesFile(int userId) throws IOException { @@ -259,6 +309,10 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { return new String(Files.asByteSource(policiesFile).read(), Charset.defaultCharset()); } + private InputStream readDoToStream() throws IOException { + return new FileInputStream(getDoFilePath()); + } + private InputStream readPoliciesFileToStream(int userId) throws IOException { File policiesFile = mProvider.makeDevicePoliciesJournaledFile(userId).chooseForRead(); return new FileInputStream(policiesFile);