diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 0a426eb80c543..8a7134e24cf86 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -279,7 +279,6 @@ import android.net.wifi.WifiManager; import android.os.Binder; import android.os.Build; import android.os.Bundle; -import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -679,6 +678,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final Context mContext; final Injector mInjector; + final PolicyPathProvider mPathProvider; final IPackageManager mIPackageManager; final IPermissionManager mIPermissionManager; final UserManager mUserManager; @@ -890,7 +890,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @GuardedBy("getLockObject()") - final SparseArray mUserData = new SparseArray<>(); + final SparseArray mUserData; @GuardedBy("getLockObject()") @@ -1365,7 +1365,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { public final Context mContext; - private @Nullable DevicePolicySafetyChecker mSafetyChecker; + @Nullable private DevicePolicySafetyChecker mSafetyChecker; Injector(Context context) { mContext = context; @@ -1384,12 +1384,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return mContext.getResources(); } - Owners newOwners() { - return new Owners(getUserManager(), getUserManagerInternal(), - getPackageManagerInternal(), getActivityTaskManagerInternal(), - getActivityManagerInternal()); - } - UserManager getUserManager() { return UserManager.get(mContext); } @@ -1595,10 +1589,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return UserHandle.getUserId(binderGetCallingUid()); } - File environmentGetUserSystemDirectory(int userId) { - return Environment.getUserSystemDirectory(userId); - } - void powerManagerGoToSleep(long time, int reason, int flags) { mContext.getSystemService(PowerManager.class).goToSleep(time, reason, flags); } @@ -1641,10 +1631,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return UserManager.isHeadlessSystemUserMode(); } - String getDevicePolicyFilePathForSystemUser() { - return "/data/system/"; - } - @SuppressWarnings("AndroidFrameworkPendingIntentMutability") PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode, @NonNull Intent intent, int flags, Bundle options, UserHandle user) { @@ -1777,14 +1763,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * Instantiates the service. */ public DevicePolicyManagerService(Context context) { - this(new Injector(context.createAttributionContext(ATTRIBUTION_TAG))); + this(new Injector( + context.createAttributionContext(ATTRIBUTION_TAG)), new PolicyPathProvider() {}); } @VisibleForTesting - DevicePolicyManagerService(Injector injector) { + DevicePolicyManagerService(Injector injector, PolicyPathProvider pathProvider) { DevicePolicyManager.disableLocalCaches(); mInjector = injector; + mPathProvider = pathProvider; mContext = Objects.requireNonNull(injector.mContext); mHandler = new Handler(Objects.requireNonNull(injector.getMyLooper())); @@ -1792,8 +1780,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mConstantsObserver.register(); mConstants = loadConstants(); - mOwners = Objects.requireNonNull(injector.newOwners()); - mUserManager = Objects.requireNonNull(injector.getUserManager()); mUserManagerInternal = Objects.requireNonNull(injector.getUserManagerInternal()); mUsageStatsManagerInternal = Objects.requireNonNull( @@ -1831,12 +1817,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // "Lite" interface is available even when the device doesn't have the feature LocalServices.addService(DevicePolicyManagerLiteInternal.class, mLocalService); + + // Policy version upgrade must not depend on either mOwners or mUserData, so they are + // initialized only after performing the upgrade. + if (mHasFeature) { + performPolicyVersionUpgrade(); + } + mUserData = new SparseArray<>(); + mOwners = makeOwners(injector, pathProvider); + if (!mHasFeature) { // Skip the rest of the initialization mSetupContentObserver = null; return; } + loadOwners(); + IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BOOT_COMPLETED); filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION); @@ -1872,16 +1869,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { new RestrictionsListener(mContext, mUserManagerInternal, this)); mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener()); - loadOwners(); - - performPolicyVersionUpgrade(); - mDeviceManagementResourcesProvider.load(); // The binder caches are not enabled until the first invalidation. invalidateBinderCaches(); } + private Owners makeOwners(Injector injector, PolicyPathProvider pathProvider) { + return new Owners(injector.getUserManager(), injector.getUserManagerInternal(), + injector.getPackageManagerInternal(), + injector.getActivityTaskManagerInternal(), + injector.getActivityManagerInternal(), pathProvider); + } + /** * Invalidate the binder API caches. The invalidation itself does not require any * locking, but this specific call should be protected by getLockObject() to ensure @@ -1975,8 +1975,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mUserData.remove(userHandle); } - File policyFile = new File(mInjector.environmentGetUserSystemDirectory(userHandle), - DEVICE_POLICIES_XML); + File policyFile = + new File(mPathProvider.getUserSystemDirectory(userHandle), DEVICE_POLICIES_XML); policyFile.delete(); Slogf.i(LOG_TAG, "Removed device policy file " + policyFile.getAbsolutePath()); } @@ -2879,8 +2879,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private File getPolicyFileDirectory(@UserIdInt int userId) { return userId == UserHandle.USER_SYSTEM - ? new File(mInjector.getDevicePolicyFilePathForSystemUser()) - : mInjector.environmentGetUserSystemDirectory(userId); + ? mPathProvider.getDataSystemDirectory() + : mPathProvider.getUserSystemDirectory(userId); } private JournaledFile makeJournaledFile(@UserIdInt int userId, String fileName) { @@ -3087,13 +3087,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { updateUsbDataSignal(); } + // TODO(b/230841522) Make it static. private class DpmsUpgradeDataProvider implements PolicyUpgraderDataProvider { - @Override - public boolean isDeviceOwner(int userId, ComponentName who) { - return mOwners.isDeviceOwnerUserId(userId) - && mOwners.getDeviceOwnerComponent().equals(who); - } - @Override public boolean storageManagerIsFileBasedEncryptionEnabled() { return mInjector.storageManagerIsFileBasedEncryptionEnabled(); @@ -3109,15 +3104,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return DevicePolicyManagerService.this.makeJournaledFile(userId, POLICIES_VERSION_XML); } - @Override - public ComponentName getOwnerComponent(int userId) { - return DevicePolicyManagerService.this.getOwnerComponent(userId); - } - @Override public Function getAdminInfoSupplier(int userId) { - return component -> findAdmin(component, userId, /* throwForMissingPermission= */ - false); + return component -> + findAdmin(component, userId, /* throwForMissingPermission= */ false); } @Override @@ -3128,7 +3118,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } private void performPolicyVersionUpgrade() { - PolicyVersionUpgrader upgrader = new PolicyVersionUpgrader(new DpmsUpgradeDataProvider()); + PolicyVersionUpgrader upgrader = new PolicyVersionUpgrader( + new DpmsUpgradeDataProvider(), mPathProvider); upgrader.upgradePolicy(DPMS_VERSION); } @@ -16280,7 +16271,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { synchronized (getLockObject()) { final int callingUserId = caller.getUserId(); final File bundleFile = new File( - mInjector.environmentGetUserSystemDirectory(callingUserId), + mPathProvider.getUserSystemDirectory(callingUserId), TRANSFER_OWNERSHIP_PARAMETERS_XML); if (!bundleFile.exists()) { return null; @@ -16474,7 +16465,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @VisibleForTesting void saveTransferOwnershipBundleLocked(PersistableBundle bundle, int userId) { final File parametersFile = new File( - mInjector.environmentGetUserSystemDirectory(userId), + mPathProvider.getUserSystemDirectory(userId), TRANSFER_OWNERSHIP_PARAMETERS_XML); final AtomicFile atomicFile = new AtomicFile(parametersFile); FileOutputStream stream = null; @@ -16496,7 +16487,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } void deleteTransferOwnershipBundleLocked(int userId) { - final File parametersFile = new File(mInjector.environmentGetUserSystemDirectory(userId), + final File parametersFile = new File(mPathProvider.getUserSystemDirectory(userId), TRANSFER_OWNERSHIP_PARAMETERS_XML); parametersFile.delete(); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java index 859183c801917..d1c6b3411b202 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java @@ -27,43 +27,30 @@ import android.app.admin.SystemUpdatePolicy; import android.content.ComponentName; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; -import android.content.pm.UserInfo; import android.os.Binder; -import android.os.Environment; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.AtomicFile; import android.util.IndentingPrintWriter; -import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; -import android.util.TypedXmlPullParser; -import android.util.TypedXmlSerializer; -import android.util.Xml; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; +import com.android.server.devicepolicy.OwnersData.OwnerInfo; import com.android.server.pm.UserManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; -import libcore.io.IoUtils; - -import org.xmlpull.v1.XmlPullParserException; - import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; import java.time.LocalDate; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Set; @@ -79,125 +66,51 @@ class Owners { private static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE - // XML storing device owner info, system update policy and pending OTA update information. - private static final String DEVICE_OWNER_XML = "device_owner_2.xml"; - - private static final String PROFILE_OWNER_XML = "profile_owner.xml"; - - private static final String TAG_ROOT = "root"; - - private static final String TAG_DEVICE_OWNER = "device-owner"; - private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy"; - private static final String TAG_FREEZE_PERIOD_RECORD = "freeze-record"; - private static final String TAG_PENDING_OTA_INFO = "pending-ota-info"; - private static final String TAG_PROFILE_OWNER = "profile-owner"; - // Holds "context" for device-owner, this must not be show up before device-owner. - private static final String TAG_DEVICE_OWNER_CONTEXT = "device-owner-context"; - private static final String TAG_DEVICE_OWNER_TYPE = "device-owner-type"; - private static final String TAG_DEVICE_OWNER_PROTECTED_PACKAGES = - "device-owner-protected-packages"; - - private static final String ATTR_NAME = "name"; - private static final String ATTR_PACKAGE = "package"; - private static final String ATTR_COMPONENT_NAME = "component"; - private static final String ATTR_SIZE = "size"; - private static final String ATTR_REMOTE_BUGREPORT_URI = "remoteBugreportUri"; - private static final String ATTR_REMOTE_BUGREPORT_HASH = "remoteBugreportHash"; - private static final String ATTR_USERID = "userId"; - private static final String ATTR_FREEZE_RECORD_START = "start"; - private static final String ATTR_FREEZE_RECORD_END = "end"; - // Legacy attribute, its presence would mean the profile owner associated with it is - // managing a profile on an organization-owned device. - private static final String ATTR_CAN_ACCESS_DEVICE_IDS = "canAccessDeviceIds"; - // New attribute for profile owner of organization-owned device. - private static final String ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE = - "isPoOrganizationOwnedDevice"; - private static final String ATTR_DEVICE_OWNER_TYPE_VALUE = "value"; - private final UserManager mUserManager; private final UserManagerInternal mUserManagerInternal; private final PackageManagerInternal mPackageManagerInternal; private final ActivityTaskManagerInternal mActivityTaskManagerInternal; private final ActivityManagerInternal mActivityManagerInternal; + @GuardedBy("mData") + private final OwnersData mData; + private boolean mSystemReady; - // Internal state for the device owner package. - private OwnerInfo mDeviceOwner; - - // Device owner type for a managed device. - private final ArrayMap mDeviceOwnerTypes = new ArrayMap<>(); - - private final ArrayMap> mDeviceOwnerProtectedPackages = new ArrayMap<>(); - - private int mDeviceOwnerUserId = UserHandle.USER_NULL; - - // Internal state for the profile owner packages. - private final ArrayMap mProfileOwners = new ArrayMap<>(); - - // Local system update policy controllable by device owner. - private SystemUpdatePolicy mSystemUpdatePolicy; - private LocalDate mSystemUpdateFreezeStart; - private LocalDate mSystemUpdateFreezeEnd; - - // Pending OTA info if there is one. - @Nullable - private SystemUpdateInfo mSystemUpdateInfo; - - private final Object mLock = new Object(); - private final Injector mInjector; - - public Owners(UserManager userManager, - UserManagerInternal userManagerInternal, - PackageManagerInternal packageManagerInternal, - ActivityTaskManagerInternal activityTaskManagerInternal, - ActivityManagerInternal activitykManagerInternal) { - this(userManager, userManagerInternal, packageManagerInternal, - activityTaskManagerInternal, activitykManagerInternal, new Injector()); - } - @VisibleForTesting Owners(UserManager userManager, UserManagerInternal userManagerInternal, PackageManagerInternal packageManagerInternal, ActivityTaskManagerInternal activityTaskManagerInternal, ActivityManagerInternal activityManagerInternal, - Injector injector) { + PolicyPathProvider pathProvider) { mUserManager = userManager; mUserManagerInternal = userManagerInternal; mPackageManagerInternal = packageManagerInternal; mActivityTaskManagerInternal = activityTaskManagerInternal; mActivityManagerInternal = activityManagerInternal; - mInjector = injector; + mData = new OwnersData(pathProvider); } /** * Load configuration from the disk. */ void load() { - synchronized (mLock) { - final List users = mUserManager.getAliveUsers(); - - new DeviceOwnerReadWriter().readFromFileLocked(); - - for (UserInfo ui : users) { - new ProfileOwnerReadWriter(ui.id).readFromFileLocked(); - } + synchronized (mData) { + int[] usersIds = + mUserManager.getAliveUsers().stream().mapToInt(u -> u.id).toArray(); + mData.load(usersIds); mUserManagerInternal.setDeviceManaged(hasDeviceOwner()); - for (UserInfo ui : users) { - mUserManagerInternal.setUserManaged(ui.id, hasProfileOwner(ui.id)); - } - if (hasDeviceOwner() && hasProfileOwner(getDeviceOwnerUserId())) { - Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported", - getDeviceOwnerUserId())); + for (int userId : usersIds) { + mUserManagerInternal.setUserManaged(userId, hasProfileOwner(userId)); } notifyChangeLocked(); pushToActivityTaskManagerLocked(); for (ArrayMap.Entry> entry : - mDeviceOwnerProtectedPackages.entrySet()) { + mData.mDeviceOwnerProtectedPackages.entrySet()) { mPackageManagerInternal.setDeviceOwnerProtectedPackages( entry.getKey(), entry.getValue()); } @@ -206,6 +119,7 @@ class Owners { // Notify interested parties that things have changed. This does not notify the // ActivityTaskManager. + @GuardedBy("mData") private void notifyChangeLocked() { pushToDevicePolicyManager(); pushToPackageManagerLocked(); @@ -219,28 +133,31 @@ class Owners { DevicePolicyManagerService.invalidateBinderCaches(); } + @GuardedBy("mData") private void pushToPackageManagerLocked() { final SparseArray po = new SparseArray<>(); - for (int i = mProfileOwners.size() - 1; i >= 0; i--) { - po.put(mProfileOwners.keyAt(i), mProfileOwners.valueAt(i).packageName); + for (int i = mData.mProfileOwners.size() - 1; i >= 0; i--) { + po.put(mData.mProfileOwners.keyAt(i), mData.mProfileOwners.valueAt(i).packageName); } + final String doPackage = mData.mDeviceOwner != null ? mData.mDeviceOwner.packageName : null; mPackageManagerInternal.setDeviceAndProfileOwnerPackages( - mDeviceOwnerUserId, (mDeviceOwner != null ? mDeviceOwner.packageName : null), - po); + mData.mDeviceOwnerUserId, doPackage, po); } + @GuardedBy("mData") private void pushToActivityTaskManagerLocked() { mActivityTaskManagerInternal.setDeviceOwnerUid(getDeviceOwnerUidLocked()); } + @GuardedBy("mData") private void pushToActivityManagerLocked() { mActivityManagerInternal.setDeviceOwnerUid(getDeviceOwnerUidLocked()); final ArraySet profileOwners = new ArraySet<>(); - for (int poi = mProfileOwners.size() - 1; poi >= 0; poi--) { - final int userId = mProfileOwners.keyAt(poi); + for (int poi = mData.mProfileOwners.size() - 1; poi >= 0; poi--) { + final int userId = mData.mProfileOwners.keyAt(poi); final int profileOwnerUid = mPackageManagerInternal.getPackageUid( - mProfileOwners.valueAt(poi).packageName, + mData.mProfileOwners.valueAt(poi).packageName, PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES, userId); if (profileOwnerUid >= 0) { @@ -250,60 +167,61 @@ class Owners { mActivityManagerInternal.setProfileOwnerUid(profileOwners); } + @GuardedBy("mData") int getDeviceOwnerUidLocked() { - if (mDeviceOwner != null) { - return mPackageManagerInternal.getPackageUid(mDeviceOwner.packageName, + if (mData.mDeviceOwner != null) { + return mPackageManagerInternal.getPackageUid(mData.mDeviceOwner.packageName, PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES, - mDeviceOwnerUserId); + mData.mDeviceOwnerUserId); } else { return Process.INVALID_UID; } } String getDeviceOwnerPackageName() { - synchronized (mLock) { - return mDeviceOwner != null ? mDeviceOwner.packageName : null; + synchronized (mData) { + return mData.mDeviceOwner != null ? mData.mDeviceOwner.packageName : null; } } int getDeviceOwnerUserId() { - synchronized (mLock) { - return mDeviceOwnerUserId; + synchronized (mData) { + return mData.mDeviceOwnerUserId; } } @Nullable Pair getDeviceOwnerUserIdAndComponent() { - synchronized (mLock) { - if (mDeviceOwner == null) { + synchronized (mData) { + if (mData.mDeviceOwner == null) { return null; } else { - return Pair.create(mDeviceOwnerUserId, mDeviceOwner.admin); + return Pair.create(mData.mDeviceOwnerUserId, mData.mDeviceOwner.admin); } } } String getDeviceOwnerName() { - synchronized (mLock) { - return mDeviceOwner != null ? mDeviceOwner.name : null; + synchronized (mData) { + return mData.mDeviceOwner != null ? mData.mDeviceOwner.name : null; } } ComponentName getDeviceOwnerComponent() { - synchronized (mLock) { - return mDeviceOwner != null ? mDeviceOwner.admin : null; + synchronized (mData) { + return mData.mDeviceOwner != null ? mData.mDeviceOwner.admin : null; } } String getDeviceOwnerRemoteBugreportUri() { - synchronized (mLock) { - return mDeviceOwner != null ? mDeviceOwner.remoteBugreportUri : null; + synchronized (mData) { + return mData.mDeviceOwner != null ? mData.mDeviceOwner.remoteBugreportUri : null; } } String getDeviceOwnerRemoteBugreportHash() { - synchronized (mLock) { - return mDeviceOwner != null ? mDeviceOwner.remoteBugreportHash : null; + synchronized (mData) { + return mData.mDeviceOwner != null ? mData.mDeviceOwner.remoteBugreportHash : null; } } @@ -312,13 +230,13 @@ class Owners { Slog.e(TAG, "Invalid user id for device owner user: " + userId); return; } - synchronized (mLock) { + synchronized (mData) { // A device owner is allowed to access device identifiers. Even though this flag // is not currently checked for device owner, it is set to true here so that it is // semantically compatible with the meaning of this flag. - mDeviceOwner = new OwnerInfo(ownerName, admin, /* remoteBugreportUri =*/ null, + mData.mDeviceOwner = new OwnerInfo(ownerName, admin, /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ null, /* isOrganizationOwnedDevice =*/ true); - mDeviceOwnerUserId = userId; + mData.mDeviceOwnerUserId = userId; mUserManagerInternal.setDeviceManaged(true); notifyChangeLocked(); @@ -327,16 +245,16 @@ class Owners { } void clearDeviceOwner() { - synchronized (mLock) { - mDeviceOwnerTypes.remove(mDeviceOwner.packageName); + synchronized (mData) { + mData.mDeviceOwnerTypes.remove(mData.mDeviceOwner.packageName); List protectedPackages = - mDeviceOwnerProtectedPackages.remove(mDeviceOwner.packageName); + mData.mDeviceOwnerProtectedPackages.remove(mData.mDeviceOwner.packageName); if (protectedPackages != null) { mPackageManagerInternal.setDeviceOwnerProtectedPackages( - mDeviceOwner.packageName, new ArrayList<>()); + mData.mDeviceOwner.packageName, new ArrayList<>()); } - mDeviceOwner = null; - mDeviceOwnerUserId = UserHandle.USER_NULL; + mData.mDeviceOwner = null; + mData.mDeviceOwnerUserId = UserHandle.USER_NULL; mUserManagerInternal.setDeviceManaged(false); notifyChangeLocked(); @@ -345,9 +263,9 @@ class Owners { } void setProfileOwner(ComponentName admin, String ownerName, int userId) { - synchronized (mLock) { + synchronized (mData) { // For a newly set PO, there's no need for migration. - mProfileOwners.put(userId, new OwnerInfo(ownerName, admin, + mData.mProfileOwners.put(userId, new OwnerInfo(ownerName, admin, /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ null, /* isOrganizationOwnedDevice =*/ false)); mUserManagerInternal.setUserManaged(userId, true); @@ -356,43 +274,48 @@ class Owners { } void removeProfileOwner(int userId) { - synchronized (mLock) { - mProfileOwners.remove(userId); + synchronized (mData) { + mData.mProfileOwners.remove(userId); mUserManagerInternal.setUserManaged(userId, false); notifyChangeLocked(); } } void transferProfileOwner(ComponentName target, int userId) { - synchronized (mLock) { - final OwnerInfo ownerInfo = mProfileOwners.get(userId); + synchronized (mData) { + final OwnerInfo ownerInfo = mData.mProfileOwners.get(userId); final OwnerInfo newOwnerInfo = new OwnerInfo(target.getPackageName(), target, ownerInfo.remoteBugreportUri, ownerInfo.remoteBugreportHash, ownerInfo.isOrganizationOwnedDevice); - mProfileOwners.put(userId, newOwnerInfo); + mData.mProfileOwners.put(userId, newOwnerInfo); notifyChangeLocked(); } } void transferDeviceOwnership(ComponentName target) { - synchronized (mLock) { - Integer previousDeviceOwnerType = mDeviceOwnerTypes.remove(mDeviceOwner.packageName); + synchronized (mData) { + Integer previousDeviceOwnerType = mData.mDeviceOwnerTypes.remove( + mData.mDeviceOwner.packageName); List previousProtectedPackages = - mDeviceOwnerProtectedPackages.remove(mDeviceOwner.packageName); + mData.mDeviceOwnerProtectedPackages.remove(mData.mDeviceOwner.packageName); if (previousProtectedPackages != null) { mPackageManagerInternal.setDeviceOwnerProtectedPackages( - mDeviceOwner.packageName, new ArrayList<>()); + mData.mDeviceOwner.packageName, new ArrayList<>()); } // We don't set a name because it's not used anyway. // See DevicePolicyManagerService#getDeviceOwnerName - mDeviceOwner = new OwnerInfo(null, target, mDeviceOwner.remoteBugreportUri, - mDeviceOwner.remoteBugreportHash, mDeviceOwner.isOrganizationOwnedDevice); + mData.mDeviceOwner = new OwnerInfo(null, target, + mData.mDeviceOwner.remoteBugreportUri, + mData.mDeviceOwner.remoteBugreportHash, + mData.mDeviceOwner.isOrganizationOwnedDevice); + if (previousDeviceOwnerType != null) { - mDeviceOwnerTypes.put(mDeviceOwner.packageName, previousDeviceOwnerType); + mData.mDeviceOwnerTypes.put( + mData.mDeviceOwner.packageName, previousDeviceOwnerType); } if (previousProtectedPackages != null) { - mDeviceOwnerProtectedPackages.put( - mDeviceOwner.packageName, previousProtectedPackages); + mData.mDeviceOwnerProtectedPackages.put( + mData.mDeviceOwner.packageName, previousProtectedPackages); } notifyChangeLocked(); pushToActivityTaskManagerLocked(); @@ -400,22 +323,22 @@ class Owners { } ComponentName getProfileOwnerComponent(int userId) { - synchronized (mLock) { - OwnerInfo profileOwner = mProfileOwners.get(userId); + synchronized (mData) { + OwnerInfo profileOwner = mData.mProfileOwners.get(userId); return profileOwner != null ? profileOwner.admin : null; } } String getProfileOwnerName(int userId) { - synchronized (mLock) { - OwnerInfo profileOwner = mProfileOwners.get(userId); + synchronized (mData) { + OwnerInfo profileOwner = mData.mProfileOwners.get(userId); return profileOwner != null ? profileOwner.name : null; } } String getProfileOwnerPackage(int userId) { - synchronized (mLock) { - OwnerInfo profileOwner = mProfileOwners.get(userId); + synchronized (mData) { + OwnerInfo profileOwner = mData.mProfileOwners.get(userId); return profileOwner != null ? profileOwner.packageName : null; } } @@ -425,27 +348,28 @@ class Owners { * organization-owned device, as indicated by the provisioning flow. */ boolean isProfileOwnerOfOrganizationOwnedDevice(int userId) { - synchronized (mLock) { - OwnerInfo profileOwner = mProfileOwners.get(userId); + synchronized (mData) { + OwnerInfo profileOwner = mData.mProfileOwners.get(userId); return profileOwner != null ? profileOwner.isOrganizationOwnedDevice : false; } } Set getProfileOwnerKeys() { - synchronized (mLock) { - return mProfileOwners.keySet(); + synchronized (mData) { + return mData.mProfileOwners.keySet(); } } List listAllOwners() { List owners = new ArrayList<>(); - synchronized (mLock) { - if (mDeviceOwner != null) { - owners.add(OwnerShellData.forDeviceOwner(mDeviceOwnerUserId, mDeviceOwner.admin)); + synchronized (mData) { + if (mData.mDeviceOwner != null) { + owners.add(OwnerShellData.forDeviceOwner(mData.mDeviceOwnerUserId, + mData.mDeviceOwner.admin)); } - for (int i = 0; i < mProfileOwners.size(); i++) { - int userId = mProfileOwners.keyAt(i); - OwnerInfo info = mProfileOwners.valueAt(i); + for (int i = 0; i < mData.mProfileOwners.size(); i++) { + int userId = mData.mProfileOwners.keyAt(i); + OwnerInfo info = mData.mProfileOwners.valueAt(i); owners.add(OwnerShellData.forUserProfileOwner(userId, info.admin)); } } @@ -454,44 +378,34 @@ class Owners { SystemUpdatePolicy getSystemUpdatePolicy() { - synchronized (mLock) { - return mSystemUpdatePolicy; + synchronized (mData) { + return mData.mSystemUpdatePolicy; } } void setSystemUpdatePolicy(SystemUpdatePolicy systemUpdatePolicy) { - synchronized (mLock) { - mSystemUpdatePolicy = systemUpdatePolicy; + synchronized (mData) { + mData.mSystemUpdatePolicy = systemUpdatePolicy; } } void clearSystemUpdatePolicy() { - synchronized (mLock) { - mSystemUpdatePolicy = null; + synchronized (mData) { + mData.mSystemUpdatePolicy = null; } } Pair getSystemUpdateFreezePeriodRecord() { - synchronized (mLock) { - return new Pair<>(mSystemUpdateFreezeStart, mSystemUpdateFreezeEnd); + synchronized (mData) { + return new Pair<>(mData.mSystemUpdateFreezeStart, + mData.mSystemUpdateFreezeEnd); } } String getSystemUpdateFreezePeriodRecordAsString() { - StringBuilder freezePeriodRecord = new StringBuilder(); - freezePeriodRecord.append("start: "); - if (mSystemUpdateFreezeStart != null) { - freezePeriodRecord.append(mSystemUpdateFreezeStart.toString()); - } else { - freezePeriodRecord.append("null"); + synchronized (mData) { + return mData.getSystemUpdateFreezePeriodRecordAsString(); } - freezePeriodRecord.append("; end: "); - if (mSystemUpdateFreezeEnd != null) { - freezePeriodRecord.append(mSystemUpdateFreezeEnd.toString()); - } else { - freezePeriodRecord.append("null"); - } - return freezePeriodRecord.toString(); } /** @@ -499,13 +413,13 @@ class Owners { */ boolean setSystemUpdateFreezePeriodRecord(LocalDate start, LocalDate end) { boolean changed = false; - synchronized (mLock) { - if (!Objects.equals(mSystemUpdateFreezeStart, start)) { - mSystemUpdateFreezeStart = start; + synchronized (mData) { + if (!Objects.equals(mData.mSystemUpdateFreezeStart, start)) { + mData.mSystemUpdateFreezeStart = start; changed = true; } - if (!Objects.equals(mSystemUpdateFreezeEnd, end)) { - mSystemUpdateFreezeEnd = end; + if (!Objects.equals(mData.mSystemUpdateFreezeEnd, end)) { + mData.mSystemUpdateFreezeEnd = end; changed = true; } } @@ -513,19 +427,19 @@ class Owners { } boolean hasDeviceOwner() { - synchronized (mLock) { - return mDeviceOwner != null; + synchronized (mData) { + return mData.mDeviceOwner != null; } } boolean isDeviceOwnerUserId(int userId) { - synchronized (mLock) { - return mDeviceOwner != null && mDeviceOwnerUserId == userId; + synchronized (mData) { + return mData.mDeviceOwner != null && mData.mDeviceOwnerUserId == userId; } } boolean hasProfileOwner(int userId) { - synchronized (mLock) { + synchronized (mData) { return getProfileOwnerComponent(userId) != null; } } @@ -533,10 +447,10 @@ class Owners { /** Sets the remote bugreport uri and hash, and also writes to the file. */ void setDeviceOwnerRemoteBugreportUriAndHash(String remoteBugreportUri, String remoteBugreportHash) { - synchronized (mLock) { - if (mDeviceOwner != null) { - mDeviceOwner.remoteBugreportUri = remoteBugreportUri; - mDeviceOwner.remoteBugreportHash = remoteBugreportHash; + synchronized (mData) { + if (mData.mDeviceOwner != null) { + mData.mDeviceOwner.remoteBugreportUri = remoteBugreportUri; + mData.mDeviceOwner.remoteBugreportHash = remoteBugreportHash; } writeDeviceOwner(); } @@ -544,8 +458,8 @@ class Owners { /** Set whether the profile owner manages an organization-owned device, then write to file. */ void setProfileOwnerOfOrganizationOwnedDevice(int userId, boolean isOrganizationOwnedDevice) { - synchronized (mLock) { - OwnerInfo profileOwner = mProfileOwners.get(userId); + synchronized (mData) { + OwnerInfo profileOwner = mData.mProfileOwners.get(userId); if (profileOwner != null) { profileOwner.isOrganizationOwnedDevice = isOrganizationOwnedDevice; } else { @@ -558,7 +472,7 @@ class Owners { void setDeviceOwnerType(String packageName, @DeviceOwnerType int deviceOwnerType, boolean isAdminTestOnly) { - synchronized (mLock) { + synchronized (mData) { if (!hasDeviceOwner()) { Slog.e(TAG, "Attempting to set a device owner type when there is no device owner"); return; @@ -568,71 +482,67 @@ class Owners { return; } - mDeviceOwnerTypes.put(packageName, deviceOwnerType); + mData.mDeviceOwnerTypes.put(packageName, deviceOwnerType); writeDeviceOwner(); } } @DeviceOwnerType int getDeviceOwnerType(String packageName) { - synchronized (mLock) { + synchronized (mData) { if (isDeviceOwnerTypeSetForDeviceOwner(packageName)) { - return mDeviceOwnerTypes.get(packageName); + return mData.mDeviceOwnerTypes.get(packageName); } return DEVICE_OWNER_TYPE_DEFAULT; } } boolean isDeviceOwnerTypeSetForDeviceOwner(String packageName) { - synchronized (mLock) { - return !mDeviceOwnerTypes.isEmpty() && mDeviceOwnerTypes.containsKey(packageName); + synchronized (mData) { + return !mData.mDeviceOwnerTypes.isEmpty() + && mData.mDeviceOwnerTypes.containsKey(packageName); } } void setDeviceOwnerProtectedPackages(String packageName, List protectedPackages) { - synchronized (mLock) { + synchronized (mData) { if (!hasDeviceOwner()) { Slog.e(TAG, "Attempting to set device owner protected packages when there is no " + "device owner"); return; - } else if (!mDeviceOwner.packageName.equals(packageName)) { + } 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; } - mDeviceOwnerProtectedPackages.put(packageName, protectedPackages); + mData.mDeviceOwnerProtectedPackages.put(packageName, protectedPackages); mPackageManagerInternal.setDeviceOwnerProtectedPackages(packageName, protectedPackages); writeDeviceOwner(); } } List getDeviceOwnerProtectedPackages(String packageName) { - synchronized (mLock) { - return mDeviceOwnerProtectedPackages.containsKey(packageName) - ? mDeviceOwnerProtectedPackages.get(packageName) : Collections.emptyList(); + synchronized (mData) { + return mData.mDeviceOwnerProtectedPackages.containsKey(packageName) + ? mData.mDeviceOwnerProtectedPackages.get(packageName) + : Collections.emptyList(); } } void writeDeviceOwner() { - synchronized (mLock) { - if (DEBUG) { - Log.d(TAG, "Writing to device owner file"); - } + synchronized (mData) { pushToDevicePolicyManager(); - new DeviceOwnerReadWriter().writeToFileLocked(); + mData.writeDeviceOwner(); } } void writeProfileOwner(int userId) { - synchronized (mLock) { - if (DEBUG) { - Log.d(TAG, "Writing to profile owner file for user " + userId); - } + synchronized (mData) { pushToDevicePolicyManager(); - new ProfileOwnerReadWriter(userId).writeToFileLocked(); + mData.writeProfileOwner(userId); } } @@ -643,25 +553,26 @@ class Owners { * @return Whether the saved system update information has changed. */ boolean saveSystemUpdateInfo(@Nullable SystemUpdateInfo newInfo) { - synchronized (mLock) { + synchronized (mData) { // Check if we already have the same update information. - if (Objects.equals(newInfo, mSystemUpdateInfo)) { + if (Objects.equals(newInfo, mData.mSystemUpdateInfo)) { return false; } - mSystemUpdateInfo = newInfo; - new DeviceOwnerReadWriter().writeToFileLocked(); + mData.mSystemUpdateInfo = newInfo; + mData.writeDeviceOwner(); return true; } } @Nullable public SystemUpdateInfo getSystemUpdateInfo() { - synchronized (mLock) { - return mSystemUpdateInfo; + synchronized (mData) { + return mData.mSystemUpdateInfo; } } + @GuardedBy("mData") void pushToAppOpsLocked() { if (!mSystemReady) { return; @@ -669,20 +580,20 @@ class Owners { final long ident = Binder.clearCallingIdentity(); try { final SparseIntArray owners = new SparseIntArray(); - if (mDeviceOwner != null) { + if (mData.mDeviceOwner != null) { final int uid = getDeviceOwnerUidLocked(); if (uid >= 0) { - owners.put(mDeviceOwnerUserId, uid); + owners.put(mData.mDeviceOwnerUserId, uid); } } - if (mProfileOwners != null) { - for (int poi = mProfileOwners.size() - 1; poi >= 0; poi--) { + if (mData.mProfileOwners != null) { + for (int poi = mData.mProfileOwners.size() - 1; poi >= 0; poi--) { final int uid = mPackageManagerInternal.getPackageUid( - mProfileOwners.valueAt(poi).packageName, + mData.mProfileOwners.valueAt(poi).packageName, PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES, - mProfileOwners.keyAt(poi)); + mData.mProfileOwners.keyAt(poi)); if (uid >= 0) { - owners.put(mProfileOwners.keyAt(poi), uid); + owners.put(mData.mProfileOwners.keyAt(poi), uid); } } } @@ -696,435 +607,26 @@ class Owners { } public void systemReady() { - synchronized (mLock) { + synchronized (mData) { mSystemReady = true; pushToActivityManagerLocked(); pushToAppOpsLocked(); } } - private abstract static class FileReadWriter { - private final File mFile; - - protected FileReadWriter(File file) { - mFile = file; - } - - abstract boolean shouldWrite(); - - void writeToFileLocked() { - if (!shouldWrite()) { - if (DEBUG) { - Log.d(TAG, "No need to write to " + mFile); - } - // No contents, remove the file. - if (mFile.exists()) { - if (DEBUG) { - Log.d(TAG, "Deleting existing " + mFile); - } - if (!mFile.delete()) { - Slog.e(TAG, "Failed to remove " + mFile.getPath()); - } - } - return; - } - if (DEBUG) { - Log.d(TAG, "Writing to " + mFile); - } - - final AtomicFile f = new AtomicFile(mFile); - FileOutputStream outputStream = null; - try { - outputStream = f.startWrite(); - final TypedXmlSerializer out = Xml.resolveSerializer(outputStream); - - // Root tag - out.startDocument(null, true); - out.startTag(null, TAG_ROOT); - - // Actual content - writeInner(out); - - // Close root - out.endTag(null, TAG_ROOT); - out.endDocument(); - out.flush(); - - // Commit the content. - f.finishWrite(outputStream); - outputStream = null; - - } catch (IOException e) { - Slog.e(TAG, "Exception when writing", e); - if (outputStream != null) { - f.failWrite(outputStream); - } - } - } - - void readFromFileLocked() { - if (!mFile.exists()) { - if (DEBUG) { - Log.d(TAG, "" + mFile + " doesn't exist"); - } - return; - } - if (DEBUG) { - Log.d(TAG, "Reading from " + mFile); - } - final AtomicFile f = new AtomicFile(mFile); - InputStream input = null; - try { - input = f.openRead(); - final TypedXmlPullParser parser = Xml.resolvePullParser(input); - - int type; - int depth = 0; - while ((type = parser.next()) != TypedXmlPullParser.END_DOCUMENT) { - switch (type) { - case TypedXmlPullParser.START_TAG: - depth++; - break; - case TypedXmlPullParser.END_TAG: - depth--; - // fallthrough - default: - continue; - } - // Check the root tag - final String tag = parser.getName(); - if (depth == 1) { - if (!TAG_ROOT.equals(tag)) { - Slog.e(TAG, "Invalid root tag: " + tag); - return; - } - continue; - } - // readInner() will only see START_TAG at depth >= 2. - if (!readInner(parser, depth, tag)) { - return; // Error - } - } - } catch (XmlPullParserException | IOException e) { - Slog.e(TAG, "Error parsing owners information file", e); - } finally { - IoUtils.closeQuietly(input); - } - } - - abstract void writeInner(TypedXmlSerializer out) throws IOException; - - abstract boolean readInner(TypedXmlPullParser parser, int depth, String tag); - } - - private class DeviceOwnerReadWriter extends FileReadWriter { - - protected DeviceOwnerReadWriter() { - super(getDeviceOwnerFile()); - } - - @Override - boolean shouldWrite() { - return (mDeviceOwner != null) || (mSystemUpdatePolicy != null) - || (mSystemUpdateInfo != null); - } - - @Override - void writeInner(TypedXmlSerializer out) throws IOException { - if (mDeviceOwner != null) { - mDeviceOwner.writeToXml(out, TAG_DEVICE_OWNER); - out.startTag(null, TAG_DEVICE_OWNER_CONTEXT); - out.attributeInt(null, ATTR_USERID, mDeviceOwnerUserId); - out.endTag(null, TAG_DEVICE_OWNER_CONTEXT); - - } - - if (!mDeviceOwnerTypes.isEmpty()) { - for (ArrayMap.Entry entry : mDeviceOwnerTypes.entrySet()) { - out.startTag(null, TAG_DEVICE_OWNER_TYPE); - out.attribute(null, ATTR_PACKAGE, entry.getKey()); - out.attributeInt(null, ATTR_DEVICE_OWNER_TYPE_VALUE, entry.getValue()); - out.endTag(null, TAG_DEVICE_OWNER_TYPE); - } - } - - 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); - out.endTag(null, TAG_SYSTEM_UPDATE_POLICY); - } - - if (mSystemUpdateInfo != null) { - mSystemUpdateInfo.writeToXml(out, TAG_PENDING_OTA_INFO); - } - - if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) { - out.startTag(null, TAG_FREEZE_PERIOD_RECORD); - if (mSystemUpdateFreezeStart != null) { - out.attribute(null, ATTR_FREEZE_RECORD_START, - mSystemUpdateFreezeStart.toString()); - } - if (mSystemUpdateFreezeEnd != null) { - out.attribute(null, ATTR_FREEZE_RECORD_END, mSystemUpdateFreezeEnd.toString()); - } - out.endTag(null, TAG_FREEZE_PERIOD_RECORD); - } - } - - @Override - boolean readInner(TypedXmlPullParser parser, int depth, String tag) { - if (depth > 2) { - return true; // Ignore - } - switch (tag) { - case TAG_DEVICE_OWNER: - mDeviceOwner = OwnerInfo.readFromXml(parser); - mDeviceOwnerUserId = UserHandle.USER_SYSTEM; // Set default - break; - case TAG_DEVICE_OWNER_CONTEXT: { - mDeviceOwnerUserId = parser.getAttributeInt(null, ATTR_USERID, - mDeviceOwnerUserId); - break; - } - case TAG_SYSTEM_UPDATE_POLICY: - mSystemUpdatePolicy = SystemUpdatePolicy.restoreFromXml(parser); - break; - case TAG_PENDING_OTA_INFO: - mSystemUpdateInfo = SystemUpdateInfo.readFromXml(parser); - break; - case TAG_FREEZE_PERIOD_RECORD: - String startDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_START); - String endDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_END); - if (startDate != null && endDate != null) { - mSystemUpdateFreezeStart = LocalDate.parse(startDate); - mSystemUpdateFreezeEnd = LocalDate.parse(endDate); - if (mSystemUpdateFreezeStart.isAfter(mSystemUpdateFreezeEnd)) { - Slog.e(TAG, "Invalid system update freeze record loaded"); - mSystemUpdateFreezeStart = null; - mSystemUpdateFreezeEnd = null; - } - } - break; - case TAG_DEVICE_OWNER_TYPE: - String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); - int deviceOwnerType = parser.getAttributeInt(null, ATTR_DEVICE_OWNER_TYPE_VALUE, - DEVICE_OWNER_TYPE_DEFAULT); - mDeviceOwnerTypes.put(packageName, deviceOwnerType); - break; - case TAG_DEVICE_OWNER_PROTECTED_PACKAGES: - packageName = parser.getAttributeValue(null, ATTR_PACKAGE); - int protectedPackagesSize = parser.getAttributeInt(null, ATTR_SIZE, 0); - List protectedPackages = new ArrayList<>(); - for (int i = 0; i < protectedPackagesSize; i++) { - protectedPackages.add(parser.getAttributeValue(null, ATTR_NAME + i)); - } - mDeviceOwnerProtectedPackages.put(packageName, protectedPackages); - break; - default: - Slog.e(TAG, "Unexpected tag: " + tag); - return false; - } - return true; - } - } - - private class ProfileOwnerReadWriter extends FileReadWriter { - private final int mUserId; - - ProfileOwnerReadWriter(int userId) { - super(getProfileOwnerFile(userId)); - mUserId = userId; - } - - @Override - boolean shouldWrite() { - return mProfileOwners.get(mUserId) != null; - } - - @Override - void writeInner(TypedXmlSerializer out) throws IOException { - final OwnerInfo profileOwner = mProfileOwners.get(mUserId); - if (profileOwner != null) { - profileOwner.writeToXml(out, TAG_PROFILE_OWNER); - } - } - - @Override - boolean readInner(TypedXmlPullParser parser, int depth, String tag) { - if (depth > 2) { - return true; // Ignore - } - switch (tag) { - case TAG_PROFILE_OWNER: - mProfileOwners.put(mUserId, OwnerInfo.readFromXml(parser)); - break; - default: - Slog.e(TAG, "Unexpected tag: " + tag); - return false; - - } - return true; - } - } - - static class OwnerInfo { - public final String name; - public final String packageName; - public final ComponentName admin; - public String remoteBugreportUri; - public String remoteBugreportHash; - public boolean isOrganizationOwnedDevice; - - OwnerInfo(String name, ComponentName admin, - String remoteBugreportUri, String remoteBugreportHash, - boolean isOrganizationOwnedDevice) { - this.name = name; - this.admin = admin; - this.packageName = admin.getPackageName(); - this.remoteBugreportUri = remoteBugreportUri; - this.remoteBugreportHash = remoteBugreportHash; - this.isOrganizationOwnedDevice = isOrganizationOwnedDevice; - } - - public void writeToXml(TypedXmlSerializer out, String tag) throws IOException { - out.startTag(null, tag); - if (name != null) { - out.attribute(null, ATTR_NAME, name); - } - if (admin != null) { - out.attribute(null, ATTR_COMPONENT_NAME, admin.flattenToString()); - } - if (remoteBugreportUri != null) { - out.attribute(null, ATTR_REMOTE_BUGREPORT_URI, remoteBugreportUri); - } - if (remoteBugreportHash != null) { - out.attribute(null, ATTR_REMOTE_BUGREPORT_HASH, remoteBugreportHash); - } - if (isOrganizationOwnedDevice) { - out.attributeBoolean(null, ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE, - isOrganizationOwnedDevice); - } - out.endTag(null, tag); - } - - public static OwnerInfo readFromXml(TypedXmlPullParser parser) { - final String name = parser.getAttributeValue(null, ATTR_NAME); - final String componentName = - parser.getAttributeValue(null, ATTR_COMPONENT_NAME); - final String remoteBugreportUri = parser.getAttributeValue(null, - ATTR_REMOTE_BUGREPORT_URI); - final String remoteBugreportHash = parser.getAttributeValue(null, - ATTR_REMOTE_BUGREPORT_HASH); - final String canAccessDeviceIdsStr = - parser.getAttributeValue(null, ATTR_CAN_ACCESS_DEVICE_IDS); - final boolean canAccessDeviceIds = - ("true".equals(canAccessDeviceIdsStr)); - final String isOrgOwnedDeviceStr = - parser.getAttributeValue(null, ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE); - final boolean isOrgOwnedDevice = - ("true".equals(isOrgOwnedDeviceStr)) | canAccessDeviceIds; - - if (componentName == null) { - Slog.e(TAG, "Owner component not found"); - return null; - } - final ComponentName admin = ComponentName.unflattenFromString(componentName); - if (admin == null) { - Slog.e(TAG, "Owner component not parsable: " + componentName); - return null; - } - - return new OwnerInfo( - name, admin, remoteBugreportUri, remoteBugreportHash, isOrgOwnedDevice); - } - - public void dump(IndentingPrintWriter pw) { - pw.println("admin=" + admin); - pw.println("name=" + name); - pw.println("package=" + packageName); - pw.println("isOrganizationOwnedDevice=" + isOrganizationOwnedDevice); - } - } - public void dump(IndentingPrintWriter pw) { - boolean needBlank = false; - if (mDeviceOwner != null) { - pw.println("Device Owner: "); - pw.increaseIndent(); - mDeviceOwner.dump(pw); - pw.println("User ID: " + mDeviceOwnerUserId); - pw.decreaseIndent(); - needBlank = true; - } - if (mSystemUpdatePolicy != null) { - if (needBlank) { - pw.println(); - } - pw.println("System Update Policy: " + mSystemUpdatePolicy); - needBlank = true; - } - if (mProfileOwners != null) { - for (Map.Entry entry : mProfileOwners.entrySet()) { - if (needBlank) { - pw.println(); - } - pw.println("Profile Owner (User " + entry.getKey() + "): "); - pw.increaseIndent(); - entry.getValue().dump(pw); - pw.decreaseIndent(); - needBlank = true; - } - } - if (mSystemUpdateInfo != null) { - if (needBlank) { - pw.println(); - } - pw.println("Pending System Update: " + mSystemUpdateInfo); - needBlank = true; - } - if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) { - if (needBlank) { - pw.println(); - } - pw.println("System update freeze record: " - + getSystemUpdateFreezePeriodRecordAsString()); - needBlank = true; + synchronized (mData) { + mData.dump(pw); } } @VisibleForTesting File getDeviceOwnerFile() { - return new File(mInjector.environmentGetDataSystemDirectory(), DEVICE_OWNER_XML); + return mData.getDeviceOwnerFile(); } @VisibleForTesting File getProfileOwnerFile(int userId) { - return new File(mInjector.environmentGetUserSystemDirectory(userId), PROFILE_OWNER_XML); - } - - @VisibleForTesting - public static class Injector { - File environmentGetDataSystemDirectory() { - return Environment.getDataSystemDirectory(); - } - - File environmentGetUserSystemDirectory(int userId) { - return Environment.getUserSystemDirectory(userId); - } + return mData.getProfileOwnerFile(userId); } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java new file mode 100644 index 0000000000000..4fe4f0d83f1ae --- /dev/null +++ b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java @@ -0,0 +1,579 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.devicepolicy; + +import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT; + +import android.annotation.Nullable; +import android.app.admin.SystemUpdateInfo; +import android.app.admin.SystemUpdatePolicy; +import android.content.ComponentName; +import android.os.UserHandle; +import android.util.ArrayMap; +import android.util.AtomicFile; +import android.util.IndentingPrintWriter; +import android.util.Log; +import android.util.Slog; +import android.util.TypedXmlPullParser; +import android.util.TypedXmlSerializer; +import android.util.Xml; + +import com.android.internal.annotations.VisibleForTesting; + +import libcore.io.IoUtils; + +import org.xmlpull.v1.XmlPullParserException; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +class OwnersData { + private static final String TAG = "DevicePolicyManagerService"; + + private static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE + + // XML storing device owner info, system update policy and pending OTA update information. + private static final String DEVICE_OWNER_XML = "device_owner_2.xml"; + private static final String PROFILE_OWNER_XML = "profile_owner.xml"; + + private static final String TAG_ROOT = "root"; + private static final String TAG_DEVICE_OWNER = "device-owner"; + private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy"; + private static final String TAG_FREEZE_PERIOD_RECORD = "freeze-record"; + private static final String TAG_PENDING_OTA_INFO = "pending-ota-info"; + private static final String TAG_PROFILE_OWNER = "profile-owner"; + // Holds "context" for device-owner, this must not be show up before device-owner. + private static final String TAG_DEVICE_OWNER_CONTEXT = "device-owner-context"; + private static final String TAG_DEVICE_OWNER_TYPE = "device-owner-type"; + private static final String TAG_DEVICE_OWNER_PROTECTED_PACKAGES = + "device-owner-protected-packages"; + + private static final String ATTR_NAME = "name"; + private static final String ATTR_PACKAGE = "package"; + private static final String ATTR_COMPONENT_NAME = "component"; + private static final String ATTR_SIZE = "size"; + private static final String ATTR_REMOTE_BUGREPORT_URI = "remoteBugreportUri"; + private static final String ATTR_REMOTE_BUGREPORT_HASH = "remoteBugreportHash"; + private static final String ATTR_USERID = "userId"; + private static final String ATTR_FREEZE_RECORD_START = "start"; + private static final String ATTR_FREEZE_RECORD_END = "end"; + // Legacy attribute, its presence would mean the profile owner associated with it is + // managing a profile on an organization-owned device. + private static final String ATTR_CAN_ACCESS_DEVICE_IDS = "canAccessDeviceIds"; + // New attribute for profile owner of organization-owned device. + private static final String ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE = + "isPoOrganizationOwnedDevice"; + private static final String ATTR_DEVICE_OWNER_TYPE_VALUE = "value"; + + // Internal state for the device owner package. + OwnerInfo mDeviceOwner; + int mDeviceOwnerUserId = UserHandle.USER_NULL; + + // Device owner type for a managed device. + final ArrayMap mDeviceOwnerTypes = new ArrayMap<>(); + + final ArrayMap> mDeviceOwnerProtectedPackages = new ArrayMap<>(); + + + // Internal state for the profile owner packages. + final ArrayMap mProfileOwners = new ArrayMap<>(); + + // Local system update policy controllable by device owner. + SystemUpdatePolicy mSystemUpdatePolicy; + LocalDate mSystemUpdateFreezeStart; + LocalDate mSystemUpdateFreezeEnd; + + // Pending OTA info if there is one. + @Nullable + SystemUpdateInfo mSystemUpdateInfo; + private final PolicyPathProvider mPathProvider; + + OwnersData(PolicyPathProvider pathProvider) { + mPathProvider = pathProvider; + } + + void load(int[] allUsers) { + new DeviceOwnerReadWriter().readFromFileLocked(); + + for (int userId : allUsers) { + new ProfileOwnerReadWriter(userId).readFromFileLocked(); + } + + OwnerInfo profileOwner = mProfileOwners.get(mDeviceOwnerUserId); + ComponentName admin = profileOwner != null ? profileOwner.admin : null; + if (mDeviceOwner != null && admin != null) { + Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported", + mDeviceOwnerUserId)); + } + } + + /** + * @return true upon success, false otherwise. + */ + boolean writeDeviceOwner() { + if (DEBUG) { + Log.d(TAG, "Writing to device owner file"); + } + return new DeviceOwnerReadWriter().writeToFileLocked(); + } + + /** + * @return true upon success, false otherwise. + */ + boolean writeProfileOwner(int userId) { + if (DEBUG) { + Log.d(TAG, "Writing to profile owner file for user " + userId); + } + return new ProfileOwnerReadWriter(userId).writeToFileLocked(); + } + + void dump(IndentingPrintWriter pw) { + boolean needBlank = false; + if (mDeviceOwner != null) { + pw.println("Device Owner: "); + pw.increaseIndent(); + mDeviceOwner.dump(pw); + pw.println("User ID: " + mDeviceOwnerUserId); + pw.decreaseIndent(); + needBlank = true; + } + if (mSystemUpdatePolicy != null) { + if (needBlank) { + pw.println(); + } + pw.println("System Update Policy: " + mSystemUpdatePolicy); + needBlank = true; + } + if (mProfileOwners != null) { + for (Map.Entry entry : mProfileOwners.entrySet()) { + if (needBlank) { + pw.println(); + } + pw.println("Profile Owner (User " + entry.getKey() + "): "); + pw.increaseIndent(); + entry.getValue().dump(pw); + pw.decreaseIndent(); + needBlank = true; + } + } + if (mSystemUpdateInfo != null) { + if (needBlank) { + pw.println(); + } + pw.println("Pending System Update: " + mSystemUpdateInfo); + needBlank = true; + } + if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) { + if (needBlank) { + pw.println(); + } + pw.println("System update freeze record: " + + getSystemUpdateFreezePeriodRecordAsString()); + needBlank = true; + } + } + + String getSystemUpdateFreezePeriodRecordAsString() { + StringBuilder freezePeriodRecord = new StringBuilder(); + freezePeriodRecord.append("start: "); + if (mSystemUpdateFreezeStart != null) { + freezePeriodRecord.append(mSystemUpdateFreezeStart.toString()); + } else { + freezePeriodRecord.append("null"); + } + freezePeriodRecord.append("; end: "); + if (mSystemUpdateFreezeEnd != null) { + freezePeriodRecord.append(mSystemUpdateFreezeEnd.toString()); + } else { + freezePeriodRecord.append("null"); + } + return freezePeriodRecord.toString(); + } + + @VisibleForTesting + File getDeviceOwnerFile() { + return new File(mPathProvider.getDataSystemDirectory(), DEVICE_OWNER_XML); + } + + @VisibleForTesting + File getProfileOwnerFile(int userId) { + return new File(mPathProvider.getUserSystemDirectory(userId), PROFILE_OWNER_XML); + } + + private abstract static class FileReadWriter { + private final File mFile; + + protected FileReadWriter(File file) { + mFile = file; + } + + abstract boolean shouldWrite(); + + boolean writeToFileLocked() { + if (!shouldWrite()) { + if (DEBUG) { + Log.d(TAG, "No need to write to " + mFile); + } + // No contents, remove the file. + if (mFile.exists()) { + if (DEBUG) { + Log.d(TAG, "Deleting existing " + mFile); + } + if (!mFile.delete()) { + Slog.e(TAG, "Failed to remove " + mFile.getPath()); + } + } + return true; + } + if (DEBUG) { + Log.d(TAG, "Writing to " + mFile); + } + + final AtomicFile f = new AtomicFile(mFile); + FileOutputStream outputStream = null; + try { + outputStream = f.startWrite(); + final TypedXmlSerializer out = Xml.resolveSerializer(outputStream); + + // Root tag + out.startDocument(null, true); + out.startTag(null, TAG_ROOT); + + // Actual content + writeInner(out); + + // Close root + out.endTag(null, TAG_ROOT); + out.endDocument(); + out.flush(); + + // Commit the content. + f.finishWrite(outputStream); + outputStream = null; + + } catch (IOException e) { + Slog.e(TAG, "Exception when writing", e); + if (outputStream != null) { + f.failWrite(outputStream); + } + return false; + } + return true; + } + + void readFromFileLocked() { + if (!mFile.exists()) { + if (DEBUG) { + Log.d(TAG, "" + mFile + " doesn't exist"); + } + return; + } + if (DEBUG) { + Log.d(TAG, "Reading from " + mFile); + } + final AtomicFile f = new AtomicFile(mFile); + InputStream input = null; + try { + input = f.openRead(); + final TypedXmlPullParser parser = Xml.resolvePullParser(input); + + int type; + int depth = 0; + while ((type = parser.next()) != TypedXmlPullParser.END_DOCUMENT) { + switch (type) { + case TypedXmlPullParser.START_TAG: + depth++; + break; + case TypedXmlPullParser.END_TAG: + depth--; + // fallthrough + default: + continue; + } + // Check the root tag + final String tag = parser.getName(); + if (depth == 1) { + if (!TAG_ROOT.equals(tag)) { + Slog.e(TAG, "Invalid root tag: " + tag); + return; + } + continue; + } + // readInner() will only see START_TAG at depth >= 2. + if (!readInner(parser, depth, tag)) { + return; // Error + } + } + } catch (XmlPullParserException | IOException e) { + Slog.e(TAG, "Error parsing owners information file", e); + } finally { + IoUtils.closeQuietly(input); + } + } + + abstract void writeInner(TypedXmlSerializer out) throws IOException; + + abstract boolean readInner(TypedXmlPullParser parser, int depth, String tag); + } + + private class DeviceOwnerReadWriter extends FileReadWriter { + + protected DeviceOwnerReadWriter() { + super(getDeviceOwnerFile()); + } + + @Override + boolean shouldWrite() { + return (mDeviceOwner != null) || (mSystemUpdatePolicy != null) + || (mSystemUpdateInfo != null); + } + + @Override + void writeInner(TypedXmlSerializer out) throws IOException { + if (mDeviceOwner != null) { + mDeviceOwner.writeToXml(out, TAG_DEVICE_OWNER); + out.startTag(null, TAG_DEVICE_OWNER_CONTEXT); + out.attributeInt(null, ATTR_USERID, mDeviceOwnerUserId); + out.endTag(null, TAG_DEVICE_OWNER_CONTEXT); + + } + + if (!mDeviceOwnerTypes.isEmpty()) { + for (ArrayMap.Entry entry : mDeviceOwnerTypes.entrySet()) { + out.startTag(null, TAG_DEVICE_OWNER_TYPE); + out.attribute(null, ATTR_PACKAGE, entry.getKey()); + out.attributeInt(null, ATTR_DEVICE_OWNER_TYPE_VALUE, entry.getValue()); + out.endTag(null, TAG_DEVICE_OWNER_TYPE); + } + } + + 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); + out.endTag(null, TAG_SYSTEM_UPDATE_POLICY); + } + + if (mSystemUpdateInfo != null) { + mSystemUpdateInfo.writeToXml(out, TAG_PENDING_OTA_INFO); + } + + if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) { + out.startTag(null, TAG_FREEZE_PERIOD_RECORD); + if (mSystemUpdateFreezeStart != null) { + out.attribute( + null, ATTR_FREEZE_RECORD_START, mSystemUpdateFreezeStart.toString()); + } + if (mSystemUpdateFreezeEnd != null) { + out.attribute(null, ATTR_FREEZE_RECORD_END, mSystemUpdateFreezeEnd.toString()); + } + out.endTag(null, TAG_FREEZE_PERIOD_RECORD); + } + } + + @Override + boolean readInner(TypedXmlPullParser parser, int depth, String tag) { + if (depth > 2) { + return true; // Ignore + } + switch (tag) { + case TAG_DEVICE_OWNER: + mDeviceOwner = OwnerInfo.readFromXml(parser); + mDeviceOwnerUserId = UserHandle.USER_SYSTEM; // Set default + break; + case TAG_DEVICE_OWNER_CONTEXT: { + mDeviceOwnerUserId = + parser.getAttributeInt(null, ATTR_USERID, mDeviceOwnerUserId); + break; + } + case TAG_SYSTEM_UPDATE_POLICY: + mSystemUpdatePolicy = SystemUpdatePolicy.restoreFromXml(parser); + break; + case TAG_PENDING_OTA_INFO: + mSystemUpdateInfo = SystemUpdateInfo.readFromXml(parser); + break; + case TAG_FREEZE_PERIOD_RECORD: + String startDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_START); + String endDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_END); + if (startDate != null && endDate != null) { + mSystemUpdateFreezeStart = LocalDate.parse(startDate); + mSystemUpdateFreezeEnd = LocalDate.parse(endDate); + if (mSystemUpdateFreezeStart.isAfter(mSystemUpdateFreezeEnd)) { + Slog.e(TAG, "Invalid system update freeze record loaded"); + mSystemUpdateFreezeStart = null; + mSystemUpdateFreezeEnd = null; + } + } + break; + case TAG_DEVICE_OWNER_TYPE: + String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); + int deviceOwnerType = parser.getAttributeInt( + null, ATTR_DEVICE_OWNER_TYPE_VALUE, DEVICE_OWNER_TYPE_DEFAULT); + mDeviceOwnerTypes.put(packageName, deviceOwnerType); + break; + case TAG_DEVICE_OWNER_PROTECTED_PACKAGES: + packageName = parser.getAttributeValue(null, ATTR_PACKAGE); + int protectedPackagesSize = parser.getAttributeInt(null, ATTR_SIZE, 0); + List protectedPackages = new ArrayList<>(); + for (int i = 0; i < protectedPackagesSize; i++) { + protectedPackages.add(parser.getAttributeValue(null, ATTR_NAME + i)); + } + mDeviceOwnerProtectedPackages.put(packageName, protectedPackages); + break; + default: + Slog.e(TAG, "Unexpected tag: " + tag); + return false; + + } + return true; + } + } + + private class ProfileOwnerReadWriter extends FileReadWriter { + private final int mUserId; + + ProfileOwnerReadWriter(int userId) { + super(getProfileOwnerFile(userId)); + mUserId = userId; + } + + @Override + boolean shouldWrite() { + return mProfileOwners.get(mUserId) != null; + } + + @Override + void writeInner(TypedXmlSerializer out) throws IOException { + final OwnerInfo profileOwner = mProfileOwners.get(mUserId); + if (profileOwner != null) { + profileOwner.writeToXml(out, TAG_PROFILE_OWNER); + } + } + + @Override + boolean readInner(TypedXmlPullParser parser, int depth, String tag) { + if (depth > 2) { + return true; // Ignore + } + switch (tag) { + case TAG_PROFILE_OWNER: + mProfileOwners.put(mUserId, OwnerInfo.readFromXml(parser)); + break; + default: + Slog.e(TAG, "Unexpected tag: " + tag); + return false; + + } + return true; + } + } + + static class OwnerInfo { + public final String name; + public final String packageName; + public final ComponentName admin; + public String remoteBugreportUri; + public String remoteBugreportHash; + public boolean isOrganizationOwnedDevice; + + OwnerInfo(String name, ComponentName admin, String remoteBugreportUri, + String remoteBugreportHash, boolean isOrganizationOwnedDevice) { + this.name = name; + this.admin = admin; + this.packageName = admin.getPackageName(); + this.remoteBugreportUri = remoteBugreportUri; + this.remoteBugreportHash = remoteBugreportHash; + this.isOrganizationOwnedDevice = isOrganizationOwnedDevice; + } + + public void writeToXml(TypedXmlSerializer out, String tag) throws IOException { + out.startTag(null, tag); + if (name != null) { + out.attribute(null, ATTR_NAME, name); + } + if (admin != null) { + out.attribute(null, ATTR_COMPONENT_NAME, admin.flattenToString()); + } + if (remoteBugreportUri != null) { + out.attribute(null, ATTR_REMOTE_BUGREPORT_URI, remoteBugreportUri); + } + if (remoteBugreportHash != null) { + out.attribute(null, ATTR_REMOTE_BUGREPORT_HASH, remoteBugreportHash); + } + if (isOrganizationOwnedDevice) { + out.attributeBoolean( + null, ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE, isOrganizationOwnedDevice); + } + out.endTag(null, tag); + } + + public static OwnerInfo readFromXml(TypedXmlPullParser parser) { + final String name = parser.getAttributeValue(null, ATTR_NAME); + final String componentName = parser.getAttributeValue(null, ATTR_COMPONENT_NAME); + final String remoteBugreportUri = + parser.getAttributeValue(null, ATTR_REMOTE_BUGREPORT_URI); + final String remoteBugreportHash = + parser.getAttributeValue(null, ATTR_REMOTE_BUGREPORT_HASH); + final String canAccessDeviceIdsStr = + parser.getAttributeValue(null, ATTR_CAN_ACCESS_DEVICE_IDS); + final boolean canAccessDeviceIds = "true".equals(canAccessDeviceIdsStr); + final String isOrgOwnedDeviceStr = + parser.getAttributeValue(null, ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE); + final boolean isOrgOwnedDevice = + "true".equals(isOrgOwnedDeviceStr) | canAccessDeviceIds; + + if (componentName == null) { + Slog.e(TAG, "Owner component not found"); + return null; + } + final ComponentName admin = ComponentName.unflattenFromString(componentName); + if (admin == null) { + Slog.e(TAG, "Owner component not parsable: " + componentName); + return null; + } + + return new OwnerInfo( + name, admin, remoteBugreportUri, remoteBugreportHash, isOrgOwnedDevice); + } + + public void dump(IndentingPrintWriter pw) { + pw.println("admin=" + admin); + pw.println("name=" + name); + pw.println("package=" + packageName); + pw.println("isOrganizationOwnedDevice=" + isOrganizationOwnedDevice); + } + } +} diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyPathProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyPathProvider.java new file mode 100644 index 0000000000000..96cc0e5323efa --- /dev/null +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyPathProvider.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.devicepolicy; + +import android.os.Environment; + +import java.io.File; + +/** + * Interface providing directories for various DPMS files. + */ +public interface PolicyPathProvider { + /** + * Returns policy data directory for system user, typically /data/system + * Used for SYSTEM_USER policies, device owner file and policy version file. + */ + default File getDataSystemDirectory() { + return Environment.getDataSystemDirectory(); + } + + /** + * Returns policy data directory for a given user, typically /data/system/users/$userId + * Used for non-system user policies and profile owner files. + */ + default File getUserSystemDirectory(int userId) { + return Environment.getUserSystemDirectory(userId); + } +} diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyUpgraderDataProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyUpgraderDataProvider.java index 19a7659f4d608..7b7a454fc9454 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyUpgraderDataProvider.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyUpgraderDataProvider.java @@ -16,7 +16,6 @@ package com.android.server.devicepolicy; -import android.annotation.Nullable; import android.app.admin.DeviceAdminInfo; import android.content.ComponentName; @@ -29,12 +28,6 @@ import java.util.function.Function; * to go through the upgrade process. */ public interface PolicyUpgraderDataProvider { - /** - * Returns true if the provided {@code userId} is a device owner. May affect some policy - * defaults. - */ - boolean isDeviceOwner(int userId, ComponentName who); - /** * Returns true if the storage manager indicates file-based encryption is enabled. */ @@ -50,11 +43,6 @@ public interface PolicyUpgraderDataProvider { */ JournaledFile makePoliciesVersionJournaledFile(int userId); - /** - * Returns the {@code ComponentName} of the owner component for a user. - */ - @Nullable ComponentName getOwnerComponent(int userId); - /** * Returns a function which provides the component name and device admin info for a given * user. diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java index f0ceb311cd8b8..7556d690f6fd0 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java @@ -16,10 +16,12 @@ package com.android.server.devicepolicy; +import android.content.ComponentName; import android.os.UserHandle; import android.util.Slog; import android.util.SparseArray; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.JournaledFile; import java.io.File; @@ -50,16 +52,16 @@ public class PolicyVersionUpgrader { private static final String LOG_TAG = "DevicePolicyManager"; private static final boolean VERBOSE_LOG = DevicePolicyManagerService.VERBOSE_LOG; private final PolicyUpgraderDataProvider mProvider; + private final PolicyPathProvider mPathProvider; - public PolicyVersionUpgrader(PolicyUpgraderDataProvider provider) { + @VisibleForTesting + PolicyVersionUpgrader(PolicyUpgraderDataProvider provider, PolicyPathProvider pathProvider) { mProvider = provider; + mPathProvider = pathProvider; } - /** * Performs the upgrade steps for all users on the system. * - * @param allUsers List of all user IDs on the system, including disabled users, as well as - * managed profile user IDs. * @param dpmsVersion The version to upgrade to. */ public void upgradePolicy(int dpmsVersion) { @@ -71,11 +73,13 @@ public class PolicyVersionUpgrader { } final int[] allUsers = mProvider.getUsersForUpgrade(); + final OwnersData ownersData = loadOwners(allUsers); - //NOTE: The current version is provided in case the XML file format changes in a + // NOTE: The current version is provided in case the XML file format changes in a // non-backwards-compatible way, so that DeviceAdminData could load it with // old tags, for example. - final SparseArray allUsersData = loadAllUsersData(allUsers, oldVersion); + final SparseArray allUsersData = + loadAllUsersData(allUsers, oldVersion, ownersData); int currentVersion = oldVersion; if (currentVersion == 0) { @@ -96,7 +100,9 @@ public class PolicyVersionUpgrader { continue; } for (ActiveAdmin admin : userData.mAdminList) { - if (mProvider.isDeviceOwner(userId, admin.info.getComponent())) { + 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; @@ -106,15 +112,26 @@ public class PolicyVersionUpgrader { currentVersion = 2; } - writePoliciesAndVersion(allUsers, allUsersData, currentVersion); + writePoliciesAndVersion(allUsers, allUsersData, ownersData, currentVersion); + } + + private OwnersData loadOwners(int[] allUsers) { + OwnersData ownersData = new OwnersData(mPathProvider); + ownersData.load(allUsers); + return ownersData; } private void writePoliciesAndVersion(int[] allUsers, SparseArray allUsersData, - int currentVersion) { + OwnersData ownersData, int currentVersion) { boolean allWritesSuccessful = true; for (int user : allUsers) { - allWritesSuccessful = allWritesSuccessful && writeDataForUser(user, - allUsersData.get(user)); + allWritesSuccessful = + allWritesSuccessful && writeDataForUser(user, allUsersData.get(user)); + } + + allWritesSuccessful = allWritesSuccessful && ownersData.writeDeviceOwner(); + for (int user : allUsers) { + allWritesSuccessful = allWritesSuccessful && ownersData.writeProfileOwner(user); } if (allWritesSuccessful) { @@ -125,21 +142,29 @@ public class PolicyVersionUpgrader { } } - private SparseArray loadAllUsersData(int[] allUsers, int loadVersion) { + private SparseArray loadAllUsersData(int[] allUsers, int loadVersion, + OwnersData ownersData) { final SparseArray allUsersData = new SparseArray<>(); for (int user: allUsers) { - allUsersData.append(user, loadDataForUser(user, loadVersion)); + 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; + } + allUsersData.append(user, loadDataForUser(user, loadVersion, owner)); } return allUsersData; } - private DevicePolicyData loadDataForUser(int userId, int loadVersion) { + private DevicePolicyData loadDataForUser( + int userId, int loadVersion, ComponentName ownerComponent) { DevicePolicyData policy = new DevicePolicyData(userId); DevicePolicyData.load(policy, !mProvider.storageManagerIsFileBasedEncryptionEnabled(), mProvider.makeDevicePoliciesJournaledFile(userId), mProvider.getAdminInfoSupplier(userId), - mProvider.getOwnerComponent(userId)); + ownerComponent); return policy; } diff --git a/services/tests/servicestests/assets/PolicyVersionUpgraderTest/device_owner_2.xml b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/device_owner_2.xml new file mode 100644 index 0000000000000..fb0b02e038fee --- /dev/null +++ b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/device_owner_2.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java index 8bb619f1976a1..673b696a2f997 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java @@ -289,12 +289,11 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { private void prepareAdmin1AsDo() throws Exception { setUpPackageManagerForAdmin(admin1, UserHandle.getUid(USER_SYSTEM, COPE_ADMIN1_APP_ID)); final int xmlResource = R.raw.comp_policies_primary; + File dataSystemDirectory = getServices().pathProvider.getDataSystemDirectory(); writeInputStreamToFile(getRawStream(xmlResource), - (new File(getServices().systemUserDataDir, "device_policies.xml")) - .getAbsoluteFile()); + (new File(dataSystemDirectory, "device_policies.xml")).getAbsoluteFile()); writeInputStreamToFile(getRawStream(R.raw.comp_device_owner), - (new File(getServices().dataDir, "device_owner_2.xml")) - .getAbsoluteFile()); + (new File(dataSystemDirectory, "device_owner_2.xml")).getAbsoluteFile()); } private void prepareAdmin1AsPo(int profileUserId, int targetSdk) throws Exception { diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java index 2dbf728c577eb..c771998de8626 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java @@ -55,8 +55,8 @@ import com.android.server.LocalServices; import com.android.server.PersistentDataBlockManagerInternal; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.pm.UserManagerInternal; +import com.android.server.wm.ActivityTaskManagerInternal; -import java.io.File; import java.io.IOException; import java.util.Map; @@ -64,45 +64,16 @@ import java.util.Map; * Overrides {@link #DevicePolicyManagerService} for dependency injection. */ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerService { - /** - * Overrides {@link #Owners} for dependency injection. - */ - public static class OwnersTestable extends Owners { - - public OwnersTestable(MockSystemServices services) { - super(services.userManager, services.userManagerInternal, - services.packageManagerInternal, services.activityTaskManagerInternal, - services.activityManagerInternal, new MockInjector(services)); - } - - static class MockInjector extends Injector { - private final MockSystemServices mServices; - - private MockInjector(MockSystemServices services) { - mServices = services; - } - - @Override - File environmentGetDataSystemDirectory() { - return mServices.dataDir; - } - - @Override - File environmentGetUserSystemDirectory(int userId) { - return mServices.environment.getUserSystemDirectory(userId); - } - } - } - public final DpmMockContext context; - protected final MockInjector mMockInjector; + public final MockInjector mMockInjector; public DevicePolicyManagerServiceTestable(MockSystemServices services, DpmMockContext context) { - this(new MockInjector(services, context)); + this(new MockInjector(services, context), services.pathProvider); } - private DevicePolicyManagerServiceTestable(MockInjector injector) { - super(unregisterLocalServices(injector)); + private DevicePolicyManagerServiceTestable( + MockInjector injector, PolicyPathProvider pathProvider) { + super(unregisterLocalServices(injector), pathProvider); mMockInjector = injector; this.context = injector.context; } @@ -150,11 +121,6 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi this.context = context; } - @Override - Owners newOwners() { - return new OwnersTestable(services); - } - @Override UserManager getUserManager() { return services.userManager; @@ -215,6 +181,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi return services.activityManagerInternal; } + @Override + ActivityTaskManagerInternal getActivityTaskManagerInternal() { + return services.activityTaskManagerInternal; + } + @Override IPackageManager getIPackageManager() { return services.ipackageManager; @@ -268,11 +239,6 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi return services.storageManager.isFileBasedEncryptionEnabled(); } - @Override - String getDevicePolicyFilePathForSystemUser() { - return services.systemUserDataDir.getAbsolutePath() + "/"; - } - @Override long binderClearCallingIdentity() { return context.binder.clearCallingIdentity(); @@ -308,11 +274,6 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi return context.binder.isCallerUidMyUid(); } - @Override - File environmentGetUserSystemDirectory(int userId) { - return services.environment.getUserSystemDirectory(userId); - } - @Override void powerManagerGoToSleep(long time, int reason, int flags) { services.powerManager.goToSleep(time, reason, flags); 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 545361c934d2b..0fc201eae3d41 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -8613,8 +8613,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { } private File getProfileOwnerPoliciesFile() { - File parentDir = dpms.mMockInjector.environmentGetUserSystemDirectory( - CALLER_USER_HANDLE); + File parentDir = getServices().pathProvider.getUserSystemDirectory(CALLER_USER_HANDLE); return getPoliciesFile(parentDir); } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java index 884ffce155d7c..46cc68ffb914c 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java @@ -137,6 +137,7 @@ public class MockSystemServices { public final PackageManager packageManager; public final BuildMock buildMock = new BuildMock(); public final File dataDir; + public final PolicyPathProvider pathProvider; public MockSystemServices(Context realContext, String name) { dataDir = new File(realContext.getCacheDir(), name); @@ -217,6 +218,17 @@ public class MockSystemServices { // System user is always running. setUserRunning(UserHandle.USER_SYSTEM, true); + pathProvider = new PolicyPathProvider() { + @Override + public File getDataSystemDirectory() { + return new File(systemUserDataDir.getAbsolutePath()); + } + + @Override + public File getUserSystemDirectory(int userId) { + return environment.getUserSystemDirectory(userId); + } + }; } /** Optional mapping of other user contexts for {@link #createPackageContextAsUser} to return */ diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java index 37ba8a42da86c..f535fdac6cf69 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java @@ -28,8 +28,6 @@ import android.test.suitebuilder.annotation.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -58,7 +56,7 @@ public class OwnersTest extends DpmTestBase { public void loadProfileOwner() throws Exception { getServices().addUsers(10); - final OwnersTestable owners = new OwnersTestable(getServices()); + final Owners owners = makeOwners(); DpmTestUtils.writeToFile(owners.getProfileOwnerFile(10), DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/profile_owner_1.xml")); @@ -76,7 +74,7 @@ public class OwnersTest extends DpmTestBase { @Test public void loadDeviceOwner() throws Exception { - final OwnersTestable owners = new OwnersTestable(getServices()); + final Owners owners = makeOwners(); DpmTestUtils.writeToFile(owners.getDeviceOwnerFile(), DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/device_owner_1.xml")); @@ -95,7 +93,7 @@ public class OwnersTest extends DpmTestBase { @Test public void testDeviceOwnerType() throws Exception { - final OwnersTestable owners = new OwnersTestable(getServices()); + final Owners owners = makeOwners(); DpmTestUtils.writeToFile(owners.getDeviceOwnerFile(), DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/device_owner_1.xml")); @@ -117,4 +115,11 @@ public class OwnersTest extends DpmTestBase { assertThat(owners.getDeviceOwnerType(TESTDPC_PACKAGE)) .isEqualTo(DEVICE_OWNER_TYPE_FINANCED); } + + private Owners makeOwners() { + final MockSystemServices services = getServices(); + return new Owners(services.userManager, services.userManagerInternal, + services.packageManagerInternal, services.activityTaskManagerInternal, + services.activityManagerInternal, services.pathProvider); + } } 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 834a514b978a6..9efc10cb55ec9 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/PolicyVersionUpgraderTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/PolicyVersionUpgraderTest.java @@ -16,10 +16,12 @@ package com.android.server.devicepolicy; -import static android.os.UserHandle.USER_SYSTEM; +import static android.content.pm.UserInfo.FLAG_PRIMARY; +import static android.os.UserManager.USER_TYPE_FULL_SYSTEM; +import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED; +import static com.android.server.devicepolicy.DevicePolicyManagerService.DEVICE_POLICIES_XML; import static com.android.server.devicepolicy.DevicePolicyManagerService.POLICIES_VERSION_XML; -import static com.android.server.devicepolicy.DpmTestUtils.writeInputStreamToFile; import static com.google.common.truth.Truth.assertThat; @@ -36,7 +38,6 @@ import android.util.Xml; import androidx.test.InstrumentationRegistry; -import com.android.frameworks.servicestests.R; import com.android.internal.util.JournaledFile; import com.android.server.SystemService; @@ -51,7 +52,6 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.File; import java.io.FileInputStream; -import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; @@ -67,30 +67,18 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { public static final String PERMISSIONS_TAG = "admin-can-grant-sensors-permissions"; private ComponentName mFakeAdmin; - private static class FakePolicyUpgraderDataProvider implements PolicyUpgraderDataProvider { - int mDeviceOwnerUserId; - ComponentName mDeviceOwnerComponent = new ComponentName("", ""); + private class FakePolicyUpgraderDataProvider implements PolicyUpgraderDataProvider { boolean mIsFileBasedEncryptionEnabled; - Map mUserToComponent = new HashMap<>(); Map mComponentToDeviceAdminInfo = new HashMap<>(); - File mDataDir; int[] mUsers; - @Override - public boolean isDeviceOwner(int userId, ComponentName who) { - return userId == mDeviceOwnerUserId && mDeviceOwnerComponent.equals(who); - } - @Override public boolean storageManagerIsFileBasedEncryptionEnabled() { return mIsFileBasedEncryptionEnabled; } private JournaledFile makeJournaledFile(int userId, String fileName) { - File parentDir = new File(mDataDir, String.format("user%d", userId)); - if (!parentDir.exists()) { - parentDir.mkdirs(); - } + File parentDir = getServices().environment.getUserSystemDirectory(userId); final String base = new File(parentDir, fileName).getAbsolutePath(); return new JournaledFile(new File(base), new File(base + ".tmp")); @@ -98,17 +86,12 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { @Override public JournaledFile makeDevicePoliciesJournaledFile(int userId) { - return makeJournaledFile(userId, DevicePolicyManagerService.DEVICE_POLICIES_XML); + return makeJournaledFile(userId, DEVICE_POLICIES_XML); } @Override public JournaledFile makePoliciesVersionJournaledFile(int userId) { - return makeJournaledFile(userId, DevicePolicyManagerService.POLICIES_VERSION_XML); - } - - @Override - public ComponentName getOwnerComponent(int userId) { - return mUserToComponent.get(userId); + return makeJournaledFile(userId, POLICIES_VERSION_XML); } @Override @@ -125,7 +108,6 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { private final Context mRealTestContext = InstrumentationRegistry.getTargetContext(); private FakePolicyUpgraderDataProvider mProvider; private PolicyVersionUpgrader mUpgrader; - private File mDataDir; @Before public void setUp() { @@ -134,11 +116,7 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { IpcDataCache.disableForTestMode(); mProvider = new FakePolicyUpgraderDataProvider(); - mUpgrader = new PolicyVersionUpgrader(mProvider); - mDataDir = new File(mRealTestContext.getCacheDir(), "test-data"); - mDataDir.getParentFile().mkdirs(); - // Prepare provider. - mProvider.mDataDir = mDataDir; + mUpgrader = new PolicyVersionUpgrader(mProvider, getServices().pathProvider); mFakeAdmin = new ComponentName( "com.android.frameworks.servicestests", "com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"); @@ -165,6 +143,7 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { public void testUpgrade0To1RemovesPasswordMetrics() throws IOException, XmlPullParserException { final String activePasswordTag = "active-password"; mProvider.mUsers = new int[] {0, 10}; + getServices().addUser(10, /* flags= */ 0, USER_TYPE_PROFILE_MANAGED); writeVersionToXml(0); for (int userId : mProvider.mUsers) { preparePoliciesFile(userId); @@ -185,13 +164,12 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { throws IOException, XmlPullParserException { final int ownerUser = 10; mProvider.mUsers = new int[] {0, ownerUser}; + getServices().addUser(ownerUser, FLAG_PRIMARY, USER_TYPE_FULL_SYSTEM); writeVersionToXml(1); for (int userId : mProvider.mUsers) { preparePoliciesFile(userId); } - mProvider.mDeviceOwnerUserId = ownerUser; - mProvider.mDeviceOwnerComponent = mFakeAdmin; - mProvider.mUserToComponent.put(ownerUser, mFakeAdmin); + prepareDeviceOwnerFile(ownerUser); mUpgrader.upgradePolicy(2); @@ -204,19 +182,12 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { @Test public void testNoStaleDataInCacheAfterUpgrade() throws Exception { - setUpPackageManagerForAdmin(admin1, UserHandle.getUid(USER_SYSTEM, 123 /* admin app ID */)); - // Reusing COPE migration policy files there, only DO on user 0 is needed. - writeInputStreamToFile(getRawStream(R.raw.comp_policies_primary), - new File(getServices().systemUserDataDir, "device_policies.xml") - .getAbsoluteFile()); - writeInputStreamToFile(getRawStream(R.raw.comp_device_owner), - new File(getServices().dataDir, "device_owner_2.xml") - .getAbsoluteFile()); - - // Write policy version 0 - File versionFilePath = - new File(getServices().systemUserDataDir, POLICIES_VERSION_XML).getAbsoluteFile(); - DpmTestUtils.writeToFile(versionFilePath, "0\n"); + final int ownerUser = 0; + getServices().addUser(ownerUser, FLAG_PRIMARY, USER_TYPE_FULL_SYSTEM); + setUpPackageManagerForAdmin(admin1, UserHandle.getUid(ownerUser, 123 /* admin app ID */)); + writeVersionToXml(0); + preparePoliciesFile(ownerUser); + prepareDeviceOwnerFile(ownerUser); DevicePolicyManagerServiceTestable dpms; final long ident = getContext().binder.clearCallingIdentity(); @@ -233,7 +204,7 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { // DO should be marked as able to grant sensors permission during upgrade and should be // reported as such via the API. - assertThat(dpms.canAdminGrantSensorsPermissionsForUser(/* userId= */0)).isTrue(); + assertThat(dpms.canAdminGrantSensorsPermissionsForUser(ownerUser)).isTrue(); } @Test @@ -264,9 +235,27 @@ public class PolicyVersionUpgraderTest extends DpmTestBase { 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); + String doFileContent = DpmTestUtils.readAsset(mRealTestContext, + "PolicyVersionUpgraderTest/device_owner_2.xml") + // 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 String readPoliciesFile(int userId) throws IOException { File policiesFile = mProvider.makeDevicePoliciesJournaledFile(userId).chooseForRead(); - FileReader reader = new FileReader(policiesFile); return new String(Files.asByteSource(policiesFile).read(), Charset.defaultCharset()); }