Merge changes from topics "presubmit-am-18cfee8fd4a246488709515ab35ce4dd", "presubmit-am-909842e21190489984382774e830cfd7" into tm-dev am: 9f4d4e7352
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17730694 Change-Id: I325c45ceb6bd73d9dbbe8e61d922c5249941407e Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -279,7 +279,6 @@ import android.net.wifi.WifiManager;
|
|||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -679,6 +678,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
|
|
||||||
final Context mContext;
|
final Context mContext;
|
||||||
final Injector mInjector;
|
final Injector mInjector;
|
||||||
|
final PolicyPathProvider mPathProvider;
|
||||||
final IPackageManager mIPackageManager;
|
final IPackageManager mIPackageManager;
|
||||||
final IPermissionManager mIPermissionManager;
|
final IPermissionManager mIPermissionManager;
|
||||||
final UserManager mUserManager;
|
final UserManager mUserManager;
|
||||||
@@ -890,7 +890,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("getLockObject()")
|
@GuardedBy("getLockObject()")
|
||||||
final SparseArray<DevicePolicyData> mUserData = new SparseArray<>();
|
final SparseArray<DevicePolicyData> mUserData;
|
||||||
|
|
||||||
@GuardedBy("getLockObject()")
|
@GuardedBy("getLockObject()")
|
||||||
|
|
||||||
@@ -1365,7 +1365,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
|
|
||||||
public final Context mContext;
|
public final Context mContext;
|
||||||
|
|
||||||
private @Nullable DevicePolicySafetyChecker mSafetyChecker;
|
@Nullable private DevicePolicySafetyChecker mSafetyChecker;
|
||||||
|
|
||||||
Injector(Context context) {
|
Injector(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
@@ -1384,12 +1384,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
return mContext.getResources();
|
return mContext.getResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
Owners newOwners() {
|
|
||||||
return new Owners(getUserManager(), getUserManagerInternal(),
|
|
||||||
getPackageManagerInternal(), getActivityTaskManagerInternal(),
|
|
||||||
getActivityManagerInternal());
|
|
||||||
}
|
|
||||||
|
|
||||||
UserManager getUserManager() {
|
UserManager getUserManager() {
|
||||||
return UserManager.get(mContext);
|
return UserManager.get(mContext);
|
||||||
}
|
}
|
||||||
@@ -1595,10 +1589,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
return UserHandle.getUserId(binderGetCallingUid());
|
return UserHandle.getUserId(binderGetCallingUid());
|
||||||
}
|
}
|
||||||
|
|
||||||
File environmentGetUserSystemDirectory(int userId) {
|
|
||||||
return Environment.getUserSystemDirectory(userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerManagerGoToSleep(long time, int reason, int flags) {
|
void powerManagerGoToSleep(long time, int reason, int flags) {
|
||||||
mContext.getSystemService(PowerManager.class).goToSleep(time, reason, flags);
|
mContext.getSystemService(PowerManager.class).goToSleep(time, reason, flags);
|
||||||
}
|
}
|
||||||
@@ -1641,10 +1631,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
return UserManager.isHeadlessSystemUserMode();
|
return UserManager.isHeadlessSystemUserMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getDevicePolicyFilePathForSystemUser() {
|
|
||||||
return "/data/system/";
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("AndroidFrameworkPendingIntentMutability")
|
@SuppressWarnings("AndroidFrameworkPendingIntentMutability")
|
||||||
PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode,
|
PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode,
|
||||||
@NonNull Intent intent, int flags, Bundle options, UserHandle user) {
|
@NonNull Intent intent, int flags, Bundle options, UserHandle user) {
|
||||||
@@ -1777,14 +1763,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
* Instantiates the service.
|
* Instantiates the service.
|
||||||
*/
|
*/
|
||||||
public DevicePolicyManagerService(Context context) {
|
public DevicePolicyManagerService(Context context) {
|
||||||
this(new Injector(context.createAttributionContext(ATTRIBUTION_TAG)));
|
this(new Injector(
|
||||||
|
context.createAttributionContext(ATTRIBUTION_TAG)), new PolicyPathProvider() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
DevicePolicyManagerService(Injector injector) {
|
DevicePolicyManagerService(Injector injector, PolicyPathProvider pathProvider) {
|
||||||
DevicePolicyManager.disableLocalCaches();
|
DevicePolicyManager.disableLocalCaches();
|
||||||
|
|
||||||
mInjector = injector;
|
mInjector = injector;
|
||||||
|
mPathProvider = pathProvider;
|
||||||
mContext = Objects.requireNonNull(injector.mContext);
|
mContext = Objects.requireNonNull(injector.mContext);
|
||||||
mHandler = new Handler(Objects.requireNonNull(injector.getMyLooper()));
|
mHandler = new Handler(Objects.requireNonNull(injector.getMyLooper()));
|
||||||
|
|
||||||
@@ -1792,8 +1780,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
mConstantsObserver.register();
|
mConstantsObserver.register();
|
||||||
mConstants = loadConstants();
|
mConstants = loadConstants();
|
||||||
|
|
||||||
mOwners = Objects.requireNonNull(injector.newOwners());
|
|
||||||
|
|
||||||
mUserManager = Objects.requireNonNull(injector.getUserManager());
|
mUserManager = Objects.requireNonNull(injector.getUserManager());
|
||||||
mUserManagerInternal = Objects.requireNonNull(injector.getUserManagerInternal());
|
mUserManagerInternal = Objects.requireNonNull(injector.getUserManagerInternal());
|
||||||
mUsageStatsManagerInternal = Objects.requireNonNull(
|
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
|
// "Lite" interface is available even when the device doesn't have the feature
|
||||||
LocalServices.addService(DevicePolicyManagerLiteInternal.class, mLocalService);
|
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) {
|
if (!mHasFeature) {
|
||||||
// Skip the rest of the initialization
|
// Skip the rest of the initialization
|
||||||
mSetupContentObserver = null;
|
mSetupContentObserver = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadOwners();
|
||||||
|
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
|
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
|
||||||
filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION);
|
filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION);
|
||||||
@@ -1872,16 +1869,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
new RestrictionsListener(mContext, mUserManagerInternal, this));
|
new RestrictionsListener(mContext, mUserManagerInternal, this));
|
||||||
mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener());
|
mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener());
|
||||||
|
|
||||||
loadOwners();
|
|
||||||
|
|
||||||
performPolicyVersionUpgrade();
|
|
||||||
|
|
||||||
mDeviceManagementResourcesProvider.load();
|
mDeviceManagementResourcesProvider.load();
|
||||||
|
|
||||||
// The binder caches are not enabled until the first invalidation.
|
// The binder caches are not enabled until the first invalidation.
|
||||||
invalidateBinderCaches();
|
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
|
* Invalidate the binder API caches. The invalidation itself does not require any
|
||||||
* locking, but this specific call should be protected by getLockObject() to ensure
|
* locking, but this specific call should be protected by getLockObject() to ensure
|
||||||
@@ -1975,8 +1975,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
mUserData.remove(userHandle);
|
mUserData.remove(userHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
File policyFile = new File(mInjector.environmentGetUserSystemDirectory(userHandle),
|
File policyFile =
|
||||||
DEVICE_POLICIES_XML);
|
new File(mPathProvider.getUserSystemDirectory(userHandle), DEVICE_POLICIES_XML);
|
||||||
policyFile.delete();
|
policyFile.delete();
|
||||||
Slogf.i(LOG_TAG, "Removed device policy file " + policyFile.getAbsolutePath());
|
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) {
|
private File getPolicyFileDirectory(@UserIdInt int userId) {
|
||||||
return userId == UserHandle.USER_SYSTEM
|
return userId == UserHandle.USER_SYSTEM
|
||||||
? new File(mInjector.getDevicePolicyFilePathForSystemUser())
|
? mPathProvider.getDataSystemDirectory()
|
||||||
: mInjector.environmentGetUserSystemDirectory(userId);
|
: mPathProvider.getUserSystemDirectory(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JournaledFile makeJournaledFile(@UserIdInt int userId, String fileName) {
|
private JournaledFile makeJournaledFile(@UserIdInt int userId, String fileName) {
|
||||||
@@ -3087,13 +3087,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
updateUsbDataSignal();
|
updateUsbDataSignal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(b/230841522) Make it static.
|
||||||
private class DpmsUpgradeDataProvider implements PolicyUpgraderDataProvider {
|
private class DpmsUpgradeDataProvider implements PolicyUpgraderDataProvider {
|
||||||
@Override
|
|
||||||
public boolean isDeviceOwner(int userId, ComponentName who) {
|
|
||||||
return mOwners.isDeviceOwnerUserId(userId)
|
|
||||||
&& mOwners.getDeviceOwnerComponent().equals(who);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean storageManagerIsFileBasedEncryptionEnabled() {
|
public boolean storageManagerIsFileBasedEncryptionEnabled() {
|
||||||
return mInjector.storageManagerIsFileBasedEncryptionEnabled();
|
return mInjector.storageManagerIsFileBasedEncryptionEnabled();
|
||||||
@@ -3109,15 +3104,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
return DevicePolicyManagerService.this.makeJournaledFile(userId, POLICIES_VERSION_XML);
|
return DevicePolicyManagerService.this.makeJournaledFile(userId, POLICIES_VERSION_XML);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ComponentName getOwnerComponent(int userId) {
|
|
||||||
return DevicePolicyManagerService.this.getOwnerComponent(userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Function<ComponentName, DeviceAdminInfo> getAdminInfoSupplier(int userId) {
|
public Function<ComponentName, DeviceAdminInfo> getAdminInfoSupplier(int userId) {
|
||||||
return component -> findAdmin(component, userId, /* throwForMissingPermission= */
|
return component ->
|
||||||
false);
|
findAdmin(component, userId, /* throwForMissingPermission= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -3128,7 +3118,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void performPolicyVersionUpgrade() {
|
private void performPolicyVersionUpgrade() {
|
||||||
PolicyVersionUpgrader upgrader = new PolicyVersionUpgrader(new DpmsUpgradeDataProvider());
|
PolicyVersionUpgrader upgrader = new PolicyVersionUpgrader(
|
||||||
|
new DpmsUpgradeDataProvider(), mPathProvider);
|
||||||
upgrader.upgradePolicy(DPMS_VERSION);
|
upgrader.upgradePolicy(DPMS_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16280,7 +16271,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
synchronized (getLockObject()) {
|
synchronized (getLockObject()) {
|
||||||
final int callingUserId = caller.getUserId();
|
final int callingUserId = caller.getUserId();
|
||||||
final File bundleFile = new File(
|
final File bundleFile = new File(
|
||||||
mInjector.environmentGetUserSystemDirectory(callingUserId),
|
mPathProvider.getUserSystemDirectory(callingUserId),
|
||||||
TRANSFER_OWNERSHIP_PARAMETERS_XML);
|
TRANSFER_OWNERSHIP_PARAMETERS_XML);
|
||||||
if (!bundleFile.exists()) {
|
if (!bundleFile.exists()) {
|
||||||
return null;
|
return null;
|
||||||
@@ -16474,7 +16465,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void saveTransferOwnershipBundleLocked(PersistableBundle bundle, int userId) {
|
void saveTransferOwnershipBundleLocked(PersistableBundle bundle, int userId) {
|
||||||
final File parametersFile = new File(
|
final File parametersFile = new File(
|
||||||
mInjector.environmentGetUserSystemDirectory(userId),
|
mPathProvider.getUserSystemDirectory(userId),
|
||||||
TRANSFER_OWNERSHIP_PARAMETERS_XML);
|
TRANSFER_OWNERSHIP_PARAMETERS_XML);
|
||||||
final AtomicFile atomicFile = new AtomicFile(parametersFile);
|
final AtomicFile atomicFile = new AtomicFile(parametersFile);
|
||||||
FileOutputStream stream = null;
|
FileOutputStream stream = null;
|
||||||
@@ -16496,7 +16487,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void deleteTransferOwnershipBundleLocked(int userId) {
|
void deleteTransferOwnershipBundleLocked(int userId) {
|
||||||
final File parametersFile = new File(mInjector.environmentGetUserSystemDirectory(userId),
|
final File parametersFile = new File(mPathProvider.getUserSystemDirectory(userId),
|
||||||
TRANSFER_OWNERSHIP_PARAMETERS_XML);
|
TRANSFER_OWNERSHIP_PARAMETERS_XML);
|
||||||
parametersFile.delete();
|
parametersFile.delete();
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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<String, Integer> mDeviceOwnerTypes = new ArrayMap<>();
|
||||||
|
|
||||||
|
final ArrayMap<String, List<String>> mDeviceOwnerProtectedPackages = new ArrayMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
// Internal state for the profile owner packages.
|
||||||
|
final ArrayMap<Integer, OwnerInfo> 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<Integer, OwnerInfo> 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<String, Integer> 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<String, List<String>> entry :
|
||||||
|
mDeviceOwnerProtectedPackages.entrySet()) {
|
||||||
|
List<String> 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<String> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.android.server.devicepolicy;
|
package com.android.server.devicepolicy;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
|
||||||
import android.app.admin.DeviceAdminInfo;
|
import android.app.admin.DeviceAdminInfo;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
|
|
||||||
@@ -29,12 +28,6 @@ import java.util.function.Function;
|
|||||||
* to go through the upgrade process.
|
* to go through the upgrade process.
|
||||||
*/
|
*/
|
||||||
public interface PolicyUpgraderDataProvider {
|
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.
|
* Returns true if the storage manager indicates file-based encryption is enabled.
|
||||||
*/
|
*/
|
||||||
@@ -50,11 +43,6 @@ public interface PolicyUpgraderDataProvider {
|
|||||||
*/
|
*/
|
||||||
JournaledFile makePoliciesVersionJournaledFile(int userId);
|
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
|
* Returns a function which provides the component name and device admin info for a given
|
||||||
* user.
|
* user.
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package com.android.server.devicepolicy;
|
package com.android.server.devicepolicy;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.util.JournaledFile;
|
import com.android.internal.util.JournaledFile;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -50,16 +52,16 @@ public class PolicyVersionUpgrader {
|
|||||||
private static final String LOG_TAG = "DevicePolicyManager";
|
private static final String LOG_TAG = "DevicePolicyManager";
|
||||||
private static final boolean VERBOSE_LOG = DevicePolicyManagerService.VERBOSE_LOG;
|
private static final boolean VERBOSE_LOG = DevicePolicyManagerService.VERBOSE_LOG;
|
||||||
private final PolicyUpgraderDataProvider mProvider;
|
private final PolicyUpgraderDataProvider mProvider;
|
||||||
|
private final PolicyPathProvider mPathProvider;
|
||||||
|
|
||||||
public PolicyVersionUpgrader(PolicyUpgraderDataProvider provider) {
|
@VisibleForTesting
|
||||||
|
PolicyVersionUpgrader(PolicyUpgraderDataProvider provider, PolicyPathProvider pathProvider) {
|
||||||
mProvider = provider;
|
mProvider = provider;
|
||||||
|
mPathProvider = pathProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the upgrade steps for all users on the system.
|
* 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.
|
* @param dpmsVersion The version to upgrade to.
|
||||||
*/
|
*/
|
||||||
public void upgradePolicy(int dpmsVersion) {
|
public void upgradePolicy(int dpmsVersion) {
|
||||||
@@ -71,11 +73,13 @@ public class PolicyVersionUpgrader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final int[] allUsers = mProvider.getUsersForUpgrade();
|
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
|
// non-backwards-compatible way, so that DeviceAdminData could load it with
|
||||||
// old tags, for example.
|
// old tags, for example.
|
||||||
final SparseArray<DevicePolicyData> allUsersData = loadAllUsersData(allUsers, oldVersion);
|
final SparseArray<DevicePolicyData> allUsersData =
|
||||||
|
loadAllUsersData(allUsers, oldVersion, ownersData);
|
||||||
|
|
||||||
int currentVersion = oldVersion;
|
int currentVersion = oldVersion;
|
||||||
if (currentVersion == 0) {
|
if (currentVersion == 0) {
|
||||||
@@ -96,7 +100,9 @@ public class PolicyVersionUpgrader {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (ActiveAdmin admin : userData.mAdminList) {
|
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(
|
Slog.i(LOG_TAG, String.format(
|
||||||
"Marking Device Owner in user %d for permission grant ", userId));
|
"Marking Device Owner in user %d for permission grant ", userId));
|
||||||
admin.mAdminCanGrantSensorsPermissions = true;
|
admin.mAdminCanGrantSensorsPermissions = true;
|
||||||
@@ -106,15 +112,26 @@ public class PolicyVersionUpgrader {
|
|||||||
currentVersion = 2;
|
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<DevicePolicyData> allUsersData,
|
private void writePoliciesAndVersion(int[] allUsers, SparseArray<DevicePolicyData> allUsersData,
|
||||||
int currentVersion) {
|
OwnersData ownersData, int currentVersion) {
|
||||||
boolean allWritesSuccessful = true;
|
boolean allWritesSuccessful = true;
|
||||||
for (int user : allUsers) {
|
for (int user : allUsers) {
|
||||||
allWritesSuccessful = allWritesSuccessful && writeDataForUser(user,
|
allWritesSuccessful =
|
||||||
allUsersData.get(user));
|
allWritesSuccessful && writeDataForUser(user, allUsersData.get(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
allWritesSuccessful = allWritesSuccessful && ownersData.writeDeviceOwner();
|
||||||
|
for (int user : allUsers) {
|
||||||
|
allWritesSuccessful = allWritesSuccessful && ownersData.writeProfileOwner(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allWritesSuccessful) {
|
if (allWritesSuccessful) {
|
||||||
@@ -125,21 +142,29 @@ public class PolicyVersionUpgrader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SparseArray<DevicePolicyData> loadAllUsersData(int[] allUsers, int loadVersion) {
|
private SparseArray<DevicePolicyData> loadAllUsersData(int[] allUsers, int loadVersion,
|
||||||
|
OwnersData ownersData) {
|
||||||
final SparseArray<DevicePolicyData> allUsersData = new SparseArray<>();
|
final SparseArray<DevicePolicyData> allUsersData = new SparseArray<>();
|
||||||
for (int user: allUsers) {
|
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;
|
return allUsersData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DevicePolicyData loadDataForUser(int userId, int loadVersion) {
|
private DevicePolicyData loadDataForUser(
|
||||||
|
int userId, int loadVersion, ComponentName ownerComponent) {
|
||||||
DevicePolicyData policy = new DevicePolicyData(userId);
|
DevicePolicyData policy = new DevicePolicyData(userId);
|
||||||
DevicePolicyData.load(policy,
|
DevicePolicyData.load(policy,
|
||||||
!mProvider.storageManagerIsFileBasedEncryptionEnabled(),
|
!mProvider.storageManagerIsFileBasedEncryptionEnabled(),
|
||||||
mProvider.makeDevicePoliciesJournaledFile(userId),
|
mProvider.makeDevicePoliciesJournaledFile(userId),
|
||||||
mProvider.getAdminInfoSupplier(userId),
|
mProvider.getAdminInfoSupplier(userId),
|
||||||
mProvider.getOwnerComponent(userId));
|
ownerComponent);
|
||||||
return policy;
|
return policy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||||
|
<root>
|
||||||
|
<device-owner name="" component="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1" isPoOrganizationOwnedDevice="true" />
|
||||||
|
<!-- userId is substituted by the test -->
|
||||||
|
<device-owner-context userId="0" />
|
||||||
|
</root>
|
||||||
@@ -289,12 +289,11 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
|
|||||||
private void prepareAdmin1AsDo() throws Exception {
|
private void prepareAdmin1AsDo() throws Exception {
|
||||||
setUpPackageManagerForAdmin(admin1, UserHandle.getUid(USER_SYSTEM, COPE_ADMIN1_APP_ID));
|
setUpPackageManagerForAdmin(admin1, UserHandle.getUid(USER_SYSTEM, COPE_ADMIN1_APP_ID));
|
||||||
final int xmlResource = R.raw.comp_policies_primary;
|
final int xmlResource = R.raw.comp_policies_primary;
|
||||||
|
File dataSystemDirectory = getServices().pathProvider.getDataSystemDirectory();
|
||||||
writeInputStreamToFile(getRawStream(xmlResource),
|
writeInputStreamToFile(getRawStream(xmlResource),
|
||||||
(new File(getServices().systemUserDataDir, "device_policies.xml"))
|
(new File(dataSystemDirectory, "device_policies.xml")).getAbsoluteFile());
|
||||||
.getAbsoluteFile());
|
|
||||||
writeInputStreamToFile(getRawStream(R.raw.comp_device_owner),
|
writeInputStreamToFile(getRawStream(R.raw.comp_device_owner),
|
||||||
(new File(getServices().dataDir, "device_owner_2.xml"))
|
(new File(dataSystemDirectory, "device_owner_2.xml")).getAbsoluteFile());
|
||||||
.getAbsoluteFile());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareAdmin1AsPo(int profileUserId, int targetSdk) throws Exception {
|
private void prepareAdmin1AsPo(int profileUserId, int targetSdk) throws Exception {
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ import com.android.server.LocalServices;
|
|||||||
import com.android.server.PersistentDataBlockManagerInternal;
|
import com.android.server.PersistentDataBlockManagerInternal;
|
||||||
import com.android.server.net.NetworkPolicyManagerInternal;
|
import com.android.server.net.NetworkPolicyManagerInternal;
|
||||||
import com.android.server.pm.UserManagerInternal;
|
import com.android.server.pm.UserManagerInternal;
|
||||||
|
import com.android.server.wm.ActivityTaskManagerInternal;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -64,45 +64,16 @@ import java.util.Map;
|
|||||||
* Overrides {@link #DevicePolicyManagerService} for dependency injection.
|
* Overrides {@link #DevicePolicyManagerService} for dependency injection.
|
||||||
*/
|
*/
|
||||||
public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerService {
|
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;
|
public final DpmMockContext context;
|
||||||
protected final MockInjector mMockInjector;
|
public final MockInjector mMockInjector;
|
||||||
|
|
||||||
public DevicePolicyManagerServiceTestable(MockSystemServices services, DpmMockContext context) {
|
public DevicePolicyManagerServiceTestable(MockSystemServices services, DpmMockContext context) {
|
||||||
this(new MockInjector(services, context));
|
this(new MockInjector(services, context), services.pathProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DevicePolicyManagerServiceTestable(MockInjector injector) {
|
private DevicePolicyManagerServiceTestable(
|
||||||
super(unregisterLocalServices(injector));
|
MockInjector injector, PolicyPathProvider pathProvider) {
|
||||||
|
super(unregisterLocalServices(injector), pathProvider);
|
||||||
mMockInjector = injector;
|
mMockInjector = injector;
|
||||||
this.context = injector.context;
|
this.context = injector.context;
|
||||||
}
|
}
|
||||||
@@ -150,11 +121,6 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
Owners newOwners() {
|
|
||||||
return new OwnersTestable(services);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
UserManager getUserManager() {
|
UserManager getUserManager() {
|
||||||
return services.userManager;
|
return services.userManager;
|
||||||
@@ -215,6 +181,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
|
|||||||
return services.activityManagerInternal;
|
return services.activityManagerInternal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
ActivityTaskManagerInternal getActivityTaskManagerInternal() {
|
||||||
|
return services.activityTaskManagerInternal;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
IPackageManager getIPackageManager() {
|
IPackageManager getIPackageManager() {
|
||||||
return services.ipackageManager;
|
return services.ipackageManager;
|
||||||
@@ -268,11 +239,6 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
|
|||||||
return services.storageManager.isFileBasedEncryptionEnabled();
|
return services.storageManager.isFileBasedEncryptionEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
String getDevicePolicyFilePathForSystemUser() {
|
|
||||||
return services.systemUserDataDir.getAbsolutePath() + "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
long binderClearCallingIdentity() {
|
long binderClearCallingIdentity() {
|
||||||
return context.binder.clearCallingIdentity();
|
return context.binder.clearCallingIdentity();
|
||||||
@@ -308,11 +274,6 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
|
|||||||
return context.binder.isCallerUidMyUid();
|
return context.binder.isCallerUidMyUid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
File environmentGetUserSystemDirectory(int userId) {
|
|
||||||
return services.environment.getUserSystemDirectory(userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void powerManagerGoToSleep(long time, int reason, int flags) {
|
void powerManagerGoToSleep(long time, int reason, int flags) {
|
||||||
services.powerManager.goToSleep(time, reason, flags);
|
services.powerManager.goToSleep(time, reason, flags);
|
||||||
|
|||||||
@@ -8613,8 +8613,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private File getProfileOwnerPoliciesFile() {
|
private File getProfileOwnerPoliciesFile() {
|
||||||
File parentDir = dpms.mMockInjector.environmentGetUserSystemDirectory(
|
File parentDir = getServices().pathProvider.getUserSystemDirectory(CALLER_USER_HANDLE);
|
||||||
CALLER_USER_HANDLE);
|
|
||||||
return getPoliciesFile(parentDir);
|
return getPoliciesFile(parentDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ public class MockSystemServices {
|
|||||||
public final PackageManager packageManager;
|
public final PackageManager packageManager;
|
||||||
public final BuildMock buildMock = new BuildMock();
|
public final BuildMock buildMock = new BuildMock();
|
||||||
public final File dataDir;
|
public final File dataDir;
|
||||||
|
public final PolicyPathProvider pathProvider;
|
||||||
|
|
||||||
public MockSystemServices(Context realContext, String name) {
|
public MockSystemServices(Context realContext, String name) {
|
||||||
dataDir = new File(realContext.getCacheDir(), name);
|
dataDir = new File(realContext.getCacheDir(), name);
|
||||||
@@ -217,6 +218,17 @@ public class MockSystemServices {
|
|||||||
|
|
||||||
// System user is always running.
|
// System user is always running.
|
||||||
setUserRunning(UserHandle.USER_SYSTEM, true);
|
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 */
|
/** Optional mapping of other user contexts for {@link #createPackageContextAsUser} to return */
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ import android.test.suitebuilder.annotation.SmallTest;
|
|||||||
|
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -58,7 +56,7 @@ public class OwnersTest extends DpmTestBase {
|
|||||||
public void loadProfileOwner() throws Exception {
|
public void loadProfileOwner() throws Exception {
|
||||||
getServices().addUsers(10);
|
getServices().addUsers(10);
|
||||||
|
|
||||||
final OwnersTestable owners = new OwnersTestable(getServices());
|
final Owners owners = makeOwners();
|
||||||
|
|
||||||
DpmTestUtils.writeToFile(owners.getProfileOwnerFile(10),
|
DpmTestUtils.writeToFile(owners.getProfileOwnerFile(10),
|
||||||
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/profile_owner_1.xml"));
|
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/profile_owner_1.xml"));
|
||||||
@@ -76,7 +74,7 @@ public class OwnersTest extends DpmTestBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void loadDeviceOwner() throws Exception {
|
public void loadDeviceOwner() throws Exception {
|
||||||
final OwnersTestable owners = new OwnersTestable(getServices());
|
final Owners owners = makeOwners();
|
||||||
|
|
||||||
DpmTestUtils.writeToFile(owners.getDeviceOwnerFile(),
|
DpmTestUtils.writeToFile(owners.getDeviceOwnerFile(),
|
||||||
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/device_owner_1.xml"));
|
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/device_owner_1.xml"));
|
||||||
@@ -95,7 +93,7 @@ public class OwnersTest extends DpmTestBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeviceOwnerType() throws Exception {
|
public void testDeviceOwnerType() throws Exception {
|
||||||
final OwnersTestable owners = new OwnersTestable(getServices());
|
final Owners owners = makeOwners();
|
||||||
|
|
||||||
DpmTestUtils.writeToFile(owners.getDeviceOwnerFile(),
|
DpmTestUtils.writeToFile(owners.getDeviceOwnerFile(),
|
||||||
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/device_owner_1.xml"));
|
DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/device_owner_1.xml"));
|
||||||
@@ -117,4 +115,11 @@ public class OwnersTest extends DpmTestBase {
|
|||||||
assertThat(owners.getDeviceOwnerType(TESTDPC_PACKAGE))
|
assertThat(owners.getDeviceOwnerType(TESTDPC_PACKAGE))
|
||||||
.isEqualTo(DEVICE_OWNER_TYPE_FINANCED);
|
.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package com.android.server.devicepolicy;
|
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.DevicePolicyManagerService.POLICIES_VERSION_XML;
|
||||||
import static com.android.server.devicepolicy.DpmTestUtils.writeInputStreamToFile;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
@@ -36,7 +38,6 @@ import android.util.Xml;
|
|||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
|
||||||
import com.android.frameworks.servicestests.R;
|
|
||||||
import com.android.internal.util.JournaledFile;
|
import com.android.internal.util.JournaledFile;
|
||||||
import com.android.server.SystemService;
|
import com.android.server.SystemService;
|
||||||
|
|
||||||
@@ -51,7 +52,6 @@ import org.xmlpull.v1.XmlPullParserException;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.Charset;
|
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";
|
public static final String PERMISSIONS_TAG = "admin-can-grant-sensors-permissions";
|
||||||
private ComponentName mFakeAdmin;
|
private ComponentName mFakeAdmin;
|
||||||
|
|
||||||
private static class FakePolicyUpgraderDataProvider implements PolicyUpgraderDataProvider {
|
private class FakePolicyUpgraderDataProvider implements PolicyUpgraderDataProvider {
|
||||||
int mDeviceOwnerUserId;
|
|
||||||
ComponentName mDeviceOwnerComponent = new ComponentName("", "");
|
|
||||||
boolean mIsFileBasedEncryptionEnabled;
|
boolean mIsFileBasedEncryptionEnabled;
|
||||||
Map<Integer, ComponentName> mUserToComponent = new HashMap<>();
|
|
||||||
Map<ComponentName, DeviceAdminInfo> mComponentToDeviceAdminInfo = new HashMap<>();
|
Map<ComponentName, DeviceAdminInfo> mComponentToDeviceAdminInfo = new HashMap<>();
|
||||||
File mDataDir;
|
|
||||||
int[] mUsers;
|
int[] mUsers;
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDeviceOwner(int userId, ComponentName who) {
|
|
||||||
return userId == mDeviceOwnerUserId && mDeviceOwnerComponent.equals(who);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean storageManagerIsFileBasedEncryptionEnabled() {
|
public boolean storageManagerIsFileBasedEncryptionEnabled() {
|
||||||
return mIsFileBasedEncryptionEnabled;
|
return mIsFileBasedEncryptionEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JournaledFile makeJournaledFile(int userId, String fileName) {
|
private JournaledFile makeJournaledFile(int userId, String fileName) {
|
||||||
File parentDir = new File(mDataDir, String.format("user%d", userId));
|
File parentDir = getServices().environment.getUserSystemDirectory(userId);
|
||||||
if (!parentDir.exists()) {
|
|
||||||
parentDir.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
final String base = new File(parentDir, fileName).getAbsolutePath();
|
final String base = new File(parentDir, fileName).getAbsolutePath();
|
||||||
return new JournaledFile(new File(base), new File(base + ".tmp"));
|
return new JournaledFile(new File(base), new File(base + ".tmp"));
|
||||||
@@ -98,17 +86,12 @@ public class PolicyVersionUpgraderTest extends DpmTestBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JournaledFile makeDevicePoliciesJournaledFile(int userId) {
|
public JournaledFile makeDevicePoliciesJournaledFile(int userId) {
|
||||||
return makeJournaledFile(userId, DevicePolicyManagerService.DEVICE_POLICIES_XML);
|
return makeJournaledFile(userId, DEVICE_POLICIES_XML);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JournaledFile makePoliciesVersionJournaledFile(int userId) {
|
public JournaledFile makePoliciesVersionJournaledFile(int userId) {
|
||||||
return makeJournaledFile(userId, DevicePolicyManagerService.POLICIES_VERSION_XML);
|
return makeJournaledFile(userId, POLICIES_VERSION_XML);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ComponentName getOwnerComponent(int userId) {
|
|
||||||
return mUserToComponent.get(userId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -125,7 +108,6 @@ public class PolicyVersionUpgraderTest extends DpmTestBase {
|
|||||||
private final Context mRealTestContext = InstrumentationRegistry.getTargetContext();
|
private final Context mRealTestContext = InstrumentationRegistry.getTargetContext();
|
||||||
private FakePolicyUpgraderDataProvider mProvider;
|
private FakePolicyUpgraderDataProvider mProvider;
|
||||||
private PolicyVersionUpgrader mUpgrader;
|
private PolicyVersionUpgrader mUpgrader;
|
||||||
private File mDataDir;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
@@ -134,11 +116,7 @@ public class PolicyVersionUpgraderTest extends DpmTestBase {
|
|||||||
IpcDataCache.disableForTestMode();
|
IpcDataCache.disableForTestMode();
|
||||||
|
|
||||||
mProvider = new FakePolicyUpgraderDataProvider();
|
mProvider = new FakePolicyUpgraderDataProvider();
|
||||||
mUpgrader = new PolicyVersionUpgrader(mProvider);
|
mUpgrader = new PolicyVersionUpgrader(mProvider, getServices().pathProvider);
|
||||||
mDataDir = new File(mRealTestContext.getCacheDir(), "test-data");
|
|
||||||
mDataDir.getParentFile().mkdirs();
|
|
||||||
// Prepare provider.
|
|
||||||
mProvider.mDataDir = mDataDir;
|
|
||||||
mFakeAdmin = new ComponentName(
|
mFakeAdmin = new ComponentName(
|
||||||
"com.android.frameworks.servicestests",
|
"com.android.frameworks.servicestests",
|
||||||
"com.android.server.devicepolicy.DummyDeviceAdmins$Admin1");
|
"com.android.server.devicepolicy.DummyDeviceAdmins$Admin1");
|
||||||
@@ -165,6 +143,7 @@ public class PolicyVersionUpgraderTest extends DpmTestBase {
|
|||||||
public void testUpgrade0To1RemovesPasswordMetrics() throws IOException, XmlPullParserException {
|
public void testUpgrade0To1RemovesPasswordMetrics() throws IOException, XmlPullParserException {
|
||||||
final String activePasswordTag = "active-password";
|
final String activePasswordTag = "active-password";
|
||||||
mProvider.mUsers = new int[] {0, 10};
|
mProvider.mUsers = new int[] {0, 10};
|
||||||
|
getServices().addUser(10, /* flags= */ 0, USER_TYPE_PROFILE_MANAGED);
|
||||||
writeVersionToXml(0);
|
writeVersionToXml(0);
|
||||||
for (int userId : mProvider.mUsers) {
|
for (int userId : mProvider.mUsers) {
|
||||||
preparePoliciesFile(userId);
|
preparePoliciesFile(userId);
|
||||||
@@ -185,13 +164,12 @@ public class PolicyVersionUpgraderTest extends DpmTestBase {
|
|||||||
throws IOException, XmlPullParserException {
|
throws IOException, XmlPullParserException {
|
||||||
final int ownerUser = 10;
|
final int ownerUser = 10;
|
||||||
mProvider.mUsers = new int[] {0, ownerUser};
|
mProvider.mUsers = new int[] {0, ownerUser};
|
||||||
|
getServices().addUser(ownerUser, FLAG_PRIMARY, USER_TYPE_FULL_SYSTEM);
|
||||||
writeVersionToXml(1);
|
writeVersionToXml(1);
|
||||||
for (int userId : mProvider.mUsers) {
|
for (int userId : mProvider.mUsers) {
|
||||||
preparePoliciesFile(userId);
|
preparePoliciesFile(userId);
|
||||||
}
|
}
|
||||||
mProvider.mDeviceOwnerUserId = ownerUser;
|
prepareDeviceOwnerFile(ownerUser);
|
||||||
mProvider.mDeviceOwnerComponent = mFakeAdmin;
|
|
||||||
mProvider.mUserToComponent.put(ownerUser, mFakeAdmin);
|
|
||||||
|
|
||||||
mUpgrader.upgradePolicy(2);
|
mUpgrader.upgradePolicy(2);
|
||||||
|
|
||||||
@@ -204,19 +182,12 @@ public class PolicyVersionUpgraderTest extends DpmTestBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoStaleDataInCacheAfterUpgrade() throws Exception {
|
public void testNoStaleDataInCacheAfterUpgrade() throws Exception {
|
||||||
setUpPackageManagerForAdmin(admin1, UserHandle.getUid(USER_SYSTEM, 123 /* admin app ID */));
|
final int ownerUser = 0;
|
||||||
// Reusing COPE migration policy files there, only DO on user 0 is needed.
|
getServices().addUser(ownerUser, FLAG_PRIMARY, USER_TYPE_FULL_SYSTEM);
|
||||||
writeInputStreamToFile(getRawStream(R.raw.comp_policies_primary),
|
setUpPackageManagerForAdmin(admin1, UserHandle.getUid(ownerUser, 123 /* admin app ID */));
|
||||||
new File(getServices().systemUserDataDir, "device_policies.xml")
|
writeVersionToXml(0);
|
||||||
.getAbsoluteFile());
|
preparePoliciesFile(ownerUser);
|
||||||
writeInputStreamToFile(getRawStream(R.raw.comp_device_owner),
|
prepareDeviceOwnerFile(ownerUser);
|
||||||
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");
|
|
||||||
|
|
||||||
DevicePolicyManagerServiceTestable dpms;
|
DevicePolicyManagerServiceTestable dpms;
|
||||||
final long ident = getContext().binder.clearCallingIdentity();
|
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
|
// DO should be marked as able to grant sensors permission during upgrade and should be
|
||||||
// reported as such via the API.
|
// reported as such via the API.
|
||||||
assertThat(dpms.canAdminGrantSensorsPermissionsForUser(/* userId= */0)).isTrue();
|
assertThat(dpms.canAdminGrantSensorsPermissionsForUser(ownerUser)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -264,9 +235,27 @@ public class PolicyVersionUpgraderTest extends DpmTestBase {
|
|||||||
policiesFile.commit();
|
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 {
|
private String readPoliciesFile(int userId) throws IOException {
|
||||||
File policiesFile = mProvider.makeDevicePoliciesJournaledFile(userId).chooseForRead();
|
File policiesFile = mProvider.makeDevicePoliciesJournaledFile(userId).chooseForRead();
|
||||||
FileReader reader = new FileReader(policiesFile);
|
|
||||||
return new String(Files.asByteSource(policiesFile).read(), Charset.defaultCharset());
|
return new String(Files.asByteSource(policiesFile).read(), Charset.defaultCharset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user