New cmd to temporarily set safety operations.
Test: adb shell cmd device_policy set-operation-safe 1 false Test: adb shell cmd device_policy is-operation-safe 1 Bug: 172376923 Change-Id: I877cd948b51032d0581cd41512a27a9a3a98a333
This commit is contained in:
@@ -983,10 +983,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
|
||||
@Override
|
||||
public void setDevicePolicySafetyChecker(DevicePolicySafetyChecker safetyChecker) {
|
||||
Slog.i(LOG_TAG, "Setting DevicePolicySafetyChecker as " + safetyChecker.getClass());
|
||||
Slog.i(LOG_TAG, "Setting DevicePolicySafetyChecker as " + safetyChecker);
|
||||
mSafetyChecker = safetyChecker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by {@link OneTimeSafetyChecker} only.
|
||||
*/
|
||||
DevicePolicySafetyChecker getDevicePolicySafetyChecker() {
|
||||
return mSafetyChecker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if it's safe to execute the given {@code operation}.
|
||||
*
|
||||
@@ -994,6 +1001,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
*/
|
||||
private void checkCanExecuteOrThrowUnsafe(@DevicePolicyOperation int operation) {
|
||||
if (!canExecute(operation)) {
|
||||
if (mSafetyChecker == null) {
|
||||
// Happens on CTS after it's set just once (by OneTimeSafetyChecker)
|
||||
throw new UnsafeStateException(operation);
|
||||
}
|
||||
// Let mSafetyChecker customize it (for example, by explaining how to retry)
|
||||
throw mSafetyChecker.newUnsafeStateException(operation);
|
||||
}
|
||||
}
|
||||
@@ -1005,6 +1017,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
return mSafetyChecker == null || mSafetyChecker.isDevicePolicyOperationSafe(operation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by {@code cmd device_policy} to set the result of the next safety operation check.
|
||||
*/
|
||||
void setNextOperationSafety(@DevicePolicyOperation int operation, boolean safe) {
|
||||
Preconditions.checkCallAuthorization(
|
||||
hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS));
|
||||
Slog.i(LOG_TAG, "setNextOperationSafety(" + DevicePolicyManager.operationToString(operation)
|
||||
+ ", " + safe + ")");
|
||||
mSafetyChecker = new OneTimeSafetyChecker(this, operation, safe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit test will subclass it to inject mocks.
|
||||
*/
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.Objects;
|
||||
final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
|
||||
|
||||
private static final String CMD_IS_SAFE_OPERATION = "is-operation-safe";
|
||||
private static final String CMD_SET_SAFE_OPERATION = "set-operation-safe";
|
||||
|
||||
private final DevicePolicyManagerService mService;
|
||||
|
||||
@@ -48,6 +49,8 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
|
||||
switch (cmd) {
|
||||
case CMD_IS_SAFE_OPERATION:
|
||||
return runIsSafeOperation(pw);
|
||||
case CMD_SET_SAFE_OPERATION:
|
||||
return runSetSafeOperation(pw);
|
||||
default:
|
||||
return onInvalidCommand(pw, cmd);
|
||||
}
|
||||
@@ -70,6 +73,9 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
|
||||
pw.printf(" Prints this help text.\n\n");
|
||||
pw.printf(" %s <OPERATION_ID>\n", CMD_IS_SAFE_OPERATION);
|
||||
pw.printf(" Checks if the give operation is safe \n\n");
|
||||
pw.printf(" %s <OPERATION_ID> <true|false>\n", CMD_SET_SAFE_OPERATION);
|
||||
pw.printf(" Emulates the result of the next call to check if the given operation is safe"
|
||||
+ " \n\n");
|
||||
}
|
||||
|
||||
private int runIsSafeOperation(PrintWriter pw) {
|
||||
@@ -79,4 +85,13 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
|
||||
safe ? "SAFE" : "UNSAFE");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int runSetSafeOperation(PrintWriter pw) {
|
||||
int operation = Integer.parseInt(getNextArgRequired());
|
||||
boolean safe = getNextArg().equals("true");
|
||||
mService.setNextOperationSafety(operation, safe);
|
||||
pw.printf("Next call to check operation %s will return %s\n",
|
||||
DevicePolicyManager.operationToString(operation), safe ? "SAFE" : "UNSAFE");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.operationToString;
|
||||
|
||||
import android.app.admin.DevicePolicyManager.DevicePolicyOperation;
|
||||
import android.app.admin.DevicePolicySafetyChecker;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
//TODO(b/172376923): add unit tests
|
||||
|
||||
/**
|
||||
* {@code DevicePolicySafetyChecker} implementation that overrides the real checker for just
|
||||
* one command.
|
||||
*
|
||||
* <p>Used only for debugging and CTS tests.
|
||||
*/
|
||||
final class OneTimeSafetyChecker implements DevicePolicySafetyChecker {
|
||||
|
||||
private static final String TAG = OneTimeSafetyChecker.class.getSimpleName();
|
||||
|
||||
private final DevicePolicyManagerService mService;
|
||||
private final DevicePolicySafetyChecker mRealSafetyChecker;
|
||||
private final @DevicePolicyOperation int mOperation;
|
||||
private final boolean mSafe;
|
||||
|
||||
OneTimeSafetyChecker(DevicePolicyManagerService service,
|
||||
@DevicePolicyOperation int operation, boolean safe) {
|
||||
mService = Objects.requireNonNull(service);
|
||||
mOperation = operation;
|
||||
mSafe = safe;
|
||||
mRealSafetyChecker = service.getDevicePolicySafetyChecker();
|
||||
Slog.i(TAG, "Saving real DevicePolicySafetyChecker as " + mRealSafetyChecker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDevicePolicyOperationSafe(@DevicePolicyOperation int operation) {
|
||||
String name = operationToString(operation);
|
||||
boolean safe = true;
|
||||
if (operation == mOperation) {
|
||||
safe = mSafe;
|
||||
} else {
|
||||
Slog.wtf(TAG, "invalid call to isDevicePolicyOperationSafe(): asked for " + name
|
||||
+ ", should be " + operationToString(mOperation));
|
||||
}
|
||||
Slog.i(TAG, "isDevicePolicyOperationSafe(" + name + "): returning " + safe
|
||||
+ " and restoring DevicePolicySafetyChecker to " + mRealSafetyChecker);
|
||||
mService.setDevicePolicySafetyChecker(mRealSafetyChecker);
|
||||
return safe;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user