1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server.devicepolicy; 17 18 import android.app.ActivityManager; 19 import android.app.admin.DevicePolicyManager; 20 import android.content.ComponentName; 21 import android.os.ShellCommand; 22 import android.os.SystemClock; 23 import android.os.UserHandle; 24 25 import java.io.PrintWriter; 26 import java.util.Collection; 27 import java.util.List; 28 import java.util.Objects; 29 30 final class DevicePolicyManagerServiceShellCommand extends ShellCommand { 31 32 private static final String CMD_IS_SAFE_OPERATION = "is-operation-safe"; 33 private static final String CMD_IS_SAFE_OPERATION_BY_REASON = "is-operation-safe-by-reason"; 34 private static final String CMD_SET_SAFE_OPERATION = "set-operation-safe"; 35 private static final String CMD_LIST_OWNERS = "list-owners"; 36 private static final String CMD_LIST_POLICY_EXEMPT_APPS = "list-policy-exempt-apps"; 37 private static final String CMD_SET_ACTIVE_ADMIN = "set-active-admin"; 38 private static final String CMD_SET_DEVICE_OWNER = "set-device-owner"; 39 private static final String CMD_SET_PROFILE_OWNER = "set-profile-owner"; 40 private static final String CMD_REMOVE_ACTIVE_ADMIN = "remove-active-admin"; 41 private static final String CMD_CLEAR_FREEZE_PERIOD_RECORD = "clear-freeze-period-record"; 42 private static final String CMD_FORCE_NETWORK_LOGS = "force-network-logs"; 43 private static final String CMD_FORCE_SECURITY_LOGS = "force-security-logs"; 44 private static final String CMD_MARK_PO_ON_ORG_OWNED_DEVICE = 45 "mark-profile-owner-on-organization-owned-device"; 46 47 private static final String USER_OPTION = "--user"; 48 private static final String DO_ONLY_OPTION = "--device-owner-only"; 49 50 private final DevicePolicyManagerService mService; 51 private int mUserId = UserHandle.USER_SYSTEM; 52 private ComponentName mComponent; 53 private boolean mSetDoOnly; 54 DevicePolicyManagerServiceShellCommand(DevicePolicyManagerService service)55 DevicePolicyManagerServiceShellCommand(DevicePolicyManagerService service) { 56 mService = Objects.requireNonNull(service); 57 } 58 59 @Override onHelp()60 public void onHelp() { 61 try (PrintWriter pw = getOutPrintWriter()) { 62 pw.printf("DevicePolicyManager Service (device_policy) commands:\n\n"); 63 showHelp(pw); 64 } 65 } 66 67 @Override onCommand(String cmd)68 public int onCommand(String cmd) { 69 if (cmd == null) { 70 return handleDefaultCommands(cmd); 71 } 72 try (PrintWriter pw = getOutPrintWriter()) { 73 switch (cmd) { 74 case CMD_IS_SAFE_OPERATION: 75 return runIsSafeOperation(pw); 76 case CMD_IS_SAFE_OPERATION_BY_REASON: 77 return runIsSafeOperationByReason(pw); 78 case CMD_SET_SAFE_OPERATION: 79 return runSetSafeOperation(pw); 80 case CMD_LIST_OWNERS: 81 return runListOwners(pw); 82 case CMD_LIST_POLICY_EXEMPT_APPS: 83 return runListPolicyExemptApps(pw); 84 case CMD_SET_ACTIVE_ADMIN: 85 return runSetActiveAdmin(pw); 86 case CMD_SET_DEVICE_OWNER: 87 return runSetDeviceOwner(pw); 88 case CMD_SET_PROFILE_OWNER: 89 return runSetProfileOwner(pw); 90 case CMD_REMOVE_ACTIVE_ADMIN: 91 return runRemoveActiveAdmin(pw); 92 case CMD_CLEAR_FREEZE_PERIOD_RECORD: 93 return runClearFreezePeriodRecord(pw); 94 case CMD_FORCE_NETWORK_LOGS: 95 return runForceNetworkLogs(pw); 96 case CMD_FORCE_SECURITY_LOGS: 97 return runForceSecurityLogs(pw); 98 case CMD_MARK_PO_ON_ORG_OWNED_DEVICE: 99 return runMarkProfileOwnerOnOrganizationOwnedDevice(pw); 100 default: 101 return onInvalidCommand(pw, cmd); 102 } 103 } 104 } 105 onInvalidCommand(PrintWriter pw, String cmd)106 private int onInvalidCommand(PrintWriter pw, String cmd) { 107 if (super.handleDefaultCommands(cmd) == 0) { 108 return 0; 109 } 110 111 pw.printf("Usage: \n"); 112 showHelp(pw); 113 return -1; 114 } 115 showHelp(PrintWriter pw)116 private void showHelp(PrintWriter pw) { 117 pw.printf(" help\n"); 118 pw.printf(" Prints this help text.\n\n"); 119 pw.printf(" %s <OPERATION_ID>\n", CMD_IS_SAFE_OPERATION); 120 pw.printf(" Checks if the give operation is safe \n\n"); 121 pw.printf(" %s <REASON_ID>\n", CMD_IS_SAFE_OPERATION_BY_REASON); 122 pw.printf(" Checks if the operations are safe for the given reason\n\n"); 123 pw.printf(" %s <OPERATION_ID> <REASON_ID>\n", CMD_SET_SAFE_OPERATION); 124 pw.printf(" Emulates the result of the next call to check if the given operation is safe" 125 + " \n\n"); 126 pw.printf(" %s\n", CMD_LIST_OWNERS); 127 pw.printf(" Lists the device / profile owners per user \n\n"); 128 pw.printf(" %s\n", CMD_LIST_POLICY_EXEMPT_APPS); 129 pw.printf(" Lists the apps that are exempt from policies\n\n"); 130 pw.printf(" %s [ %s <USER_ID> | current ] <COMPONENT>\n", 131 CMD_SET_ACTIVE_ADMIN, USER_OPTION); 132 pw.printf(" Sets the given component as active admin for an existing user.\n\n"); 133 pw.printf(" %s [ %s <USER_ID> | current *EXPERIMENTAL* ] [ %s ]" 134 + "<COMPONENT>\n", CMD_SET_DEVICE_OWNER, USER_OPTION, DO_ONLY_OPTION); 135 pw.printf(" Sets the given component as active admin, and its package as device owner." 136 + "\n\n"); 137 pw.printf(" %s [ %s <USER_ID> | current ] <COMPONENT>\n", 138 CMD_SET_PROFILE_OWNER, USER_OPTION); 139 pw.printf(" Sets the given component as active admin and profile owner for an existing " 140 + "user.\n\n"); 141 pw.printf(" %s [ %s <USER_ID> | current ] <COMPONENT>\n", 142 CMD_REMOVE_ACTIVE_ADMIN, USER_OPTION); 143 pw.printf(" Disables an active admin, the admin must have declared android:testOnly in " 144 + "the application in its manifest. This will also remove device and profile " 145 + "owners.\n\n"); 146 pw.printf(" %s\n", CMD_CLEAR_FREEZE_PERIOD_RECORD); 147 pw.printf(" Clears framework-maintained record of past freeze periods that the device " 148 + "went through. For use during feature development to prevent triggering " 149 + "restriction on setting freeze periods.\n\n"); 150 pw.printf(" %s\n", CMD_FORCE_NETWORK_LOGS); 151 pw.printf(" Makes all network logs available to the DPC and triggers " 152 + "DeviceAdminReceiver.onNetworkLogsAvailable() if needed.\n\n"); 153 pw.printf(" %s\n", CMD_FORCE_SECURITY_LOGS); 154 pw.printf(" Makes all security logs available to the DPC and triggers " 155 + "DeviceAdminReceiver.onSecurityLogsAvailable() if needed.\n\n"); 156 pw.printf(" %s [ %s <USER_ID> | current ] <COMPONENT>\n", 157 CMD_MARK_PO_ON_ORG_OWNED_DEVICE, USER_OPTION); 158 pw.printf(" Marks the profile owner of the given user as managing an organization-owned" 159 + "device. That will give it access to device identifiers (such as serial number, " 160 + "IMEI and MEID), as well as other privileges.\n\n"); 161 } 162 runIsSafeOperation(PrintWriter pw)163 private int runIsSafeOperation(PrintWriter pw) { 164 int operation = Integer.parseInt(getNextArgRequired()); 165 int reason = mService.getUnsafeOperationReason(operation); 166 boolean safe = reason == DevicePolicyManager.OPERATION_SAFETY_REASON_NONE; 167 pw.printf("Operation %s is %s. Reason: %s\n", 168 DevicePolicyManager.operationToString(operation), safeToString(safe), 169 DevicePolicyManager.operationSafetyReasonToString(reason)); 170 return 0; 171 } 172 runIsSafeOperationByReason(PrintWriter pw)173 private int runIsSafeOperationByReason(PrintWriter pw) { 174 int reason = Integer.parseInt(getNextArgRequired()); 175 boolean safe = mService.isSafeOperation(reason); 176 pw.printf("Operations affected by %s are %s\n", 177 DevicePolicyManager.operationSafetyReasonToString(reason), safeToString(safe)); 178 return 0; 179 } 180 safeToString(boolean safe)181 private static String safeToString(boolean safe) { 182 return safe ? "SAFE" : "UNSAFE"; 183 } 184 runSetSafeOperation(PrintWriter pw)185 private int runSetSafeOperation(PrintWriter pw) { 186 int operation = Integer.parseInt(getNextArgRequired()); 187 int reason = Integer.parseInt(getNextArgRequired()); 188 mService.setNextOperationSafety(operation, reason); 189 pw.printf("Next call to check operation %s will return %s\n", 190 DevicePolicyManager.operationToString(operation), 191 DevicePolicyManager.operationSafetyReasonToString(reason)); 192 return 0; 193 } 194 printAndGetSize(PrintWriter pw, Collection<?> collection, String nameOnSingular)195 private int printAndGetSize(PrintWriter pw, Collection<?> collection, String nameOnSingular) { 196 if (collection.isEmpty()) { 197 pw.printf("no %ss\n", nameOnSingular); 198 return 0; 199 } 200 int size = collection.size(); 201 pw.printf("%d %s%s:\n", size, nameOnSingular, (size == 1 ? "" : "s")); 202 return size; 203 } 204 runListOwners(PrintWriter pw)205 private int runListOwners(PrintWriter pw) { 206 List<OwnerShellData> owners = mService.listAllOwners(); 207 int size = printAndGetSize(pw, owners, "owner"); 208 if (size == 0) return 0; 209 210 for (int i = 0; i < size; i++) { 211 OwnerShellData owner = owners.get(i); 212 pw.printf("User %2d: admin=%s", owner.userId, owner.admin.flattenToShortString()); 213 if (owner.isDeviceOwner) { 214 pw.print(",DeviceOwner"); 215 } 216 if (owner.isProfileOwner) { 217 pw.print(",ProfileOwner"); 218 } 219 if (owner.isManagedProfileOwner) { 220 pw.printf(",ManagedProfileOwner(parentUserId=%d)", owner.parentUserId); 221 } 222 if (owner.isAffiliated) { 223 pw.print(",Affiliated"); 224 } 225 pw.println(); 226 } 227 228 return 0; 229 } 230 runListPolicyExemptApps(PrintWriter pw)231 private int runListPolicyExemptApps(PrintWriter pw) { 232 List<String> apps = mService.listPolicyExemptApps(); 233 int size = printAndGetSize(pw, apps, "policy exempt app"); 234 235 if (size == 0) return 0; 236 237 for (int i = 0; i < size; i++) { 238 String app = apps.get(i); 239 pw.printf(" %d: %s\n", i, app); 240 } 241 return 0; 242 } 243 runSetActiveAdmin(PrintWriter pw)244 private int runSetActiveAdmin(PrintWriter pw) { 245 parseArgs(); 246 mService.setActiveAdmin(mComponent, /* refreshing= */ true, mUserId); 247 248 pw.printf("Success: Active admin set to component %s\n", mComponent.flattenToShortString()); 249 return 0; 250 } 251 runSetDeviceOwner(PrintWriter pw)252 private int runSetDeviceOwner(PrintWriter pw) { 253 parseArgs(); 254 mService.setActiveAdmin(mComponent, /* refreshing= */ true, mUserId); 255 256 try { 257 if (!mService.setDeviceOwner(mComponent, mUserId, 258 /* setProfileOwnerOnCurrentUserIfNecessary= */ !mSetDoOnly)) { 259 throw new RuntimeException( 260 "Can't set package " + mComponent + " as device owner."); 261 } 262 } catch (Exception e) { 263 // Need to remove the admin that we just added. 264 mService.removeActiveAdmin(mComponent, UserHandle.USER_SYSTEM); 265 throw e; 266 } 267 268 mService.setUserProvisioningState( 269 DevicePolicyManager.STATE_USER_SETUP_FINALIZED, mUserId); 270 271 pw.printf("Success: Device owner set to package %s\n", mComponent.flattenToShortString()); 272 pw.printf("Active admin set to component %s\n", mComponent.flattenToShortString()); 273 return 0; 274 } 275 runRemoveActiveAdmin(PrintWriter pw)276 private int runRemoveActiveAdmin(PrintWriter pw) { 277 parseArgs(); 278 mService.forceRemoveActiveAdmin(mComponent, mUserId); 279 pw.printf("Success: Admin removed %s\n", mComponent); 280 return 0; 281 } 282 runSetProfileOwner(PrintWriter pw)283 private int runSetProfileOwner(PrintWriter pw) { 284 parseArgs(); 285 mService.setActiveAdmin(mComponent, /* refreshing= */ true, mUserId); 286 287 try { 288 if (!mService.setProfileOwner(mComponent, mUserId)) { 289 throw new RuntimeException("Can't set component " 290 + mComponent.flattenToShortString() + " as profile owner for user " 291 + mUserId); 292 } 293 } catch (Exception e) { 294 // Need to remove the admin that we just added. 295 mService.removeActiveAdmin(mComponent, mUserId); 296 throw e; 297 } 298 299 mService.setUserProvisioningState( 300 DevicePolicyManager.STATE_USER_SETUP_FINALIZED, mUserId); 301 302 pw.printf("Success: Active admin and profile owner set to %s for user %d\n", 303 mComponent.flattenToShortString(), mUserId); 304 return 0; 305 } 306 runClearFreezePeriodRecord(PrintWriter pw)307 private int runClearFreezePeriodRecord(PrintWriter pw) { 308 mService.clearSystemUpdatePolicyFreezePeriodRecord(); 309 pw.printf("Success\n"); 310 return 0; 311 } 312 runForceNetworkLogs(PrintWriter pw)313 private int runForceNetworkLogs(PrintWriter pw) { 314 while (true) { 315 long toWait = mService.forceNetworkLogs(); 316 if (toWait == 0) { 317 break; 318 } 319 pw.printf("We have to wait for %d milliseconds...\n", toWait); 320 SystemClock.sleep(toWait); 321 } 322 pw.printf("Success\n"); 323 return 0; 324 } 325 runForceSecurityLogs(PrintWriter pw)326 private int runForceSecurityLogs(PrintWriter pw) { 327 while (true) { 328 long toWait = mService.forceSecurityLogs(); 329 if (toWait == 0) { 330 break; 331 } 332 pw.printf("We have to wait for %d milliseconds...\n", toWait); 333 SystemClock.sleep(toWait); 334 } 335 pw.printf("Success\n"); 336 return 0; 337 } 338 runMarkProfileOwnerOnOrganizationOwnedDevice(PrintWriter pw)339 private int runMarkProfileOwnerOnOrganizationOwnedDevice(PrintWriter pw) { 340 parseArgs(); 341 mService.setProfileOwnerOnOrganizationOwnedDevice(mComponent, mUserId, true); 342 pw.printf("Success\n"); 343 return 0; 344 } 345 parseArgs()346 private void parseArgs() { 347 String opt; 348 while ((opt = getNextOption()) != null) { 349 if (USER_OPTION.equals(opt)) { 350 String arg = getNextArgRequired(); 351 mUserId = UserHandle.parseUserArg(arg); 352 if (mUserId == UserHandle.USER_CURRENT) { 353 mUserId = ActivityManager.getCurrentUser(); 354 } 355 } else if (DO_ONLY_OPTION.equals(opt)) { 356 mSetDoOnly = true; 357 } else { 358 throw new IllegalArgumentException("Unknown option: " + opt); 359 } 360 } 361 mComponent = parseComponentName(getNextArgRequired()); 362 } 363 parseComponentName(String component)364 private ComponentName parseComponentName(String component) { 365 ComponentName cn = ComponentName.unflattenFromString(component); 366 if (cn == null) { 367 throw new IllegalArgumentException("Invalid component " + component); 368 } 369 return cn; 370 } 371 } 372