diff options
11 files changed, 1530 insertions, 1474 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 60ec8a96f325..29433f3fc14f 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -116,9 +116,8 @@ public final class Pm { } public int run(String[] args) throws RemoteException { - boolean validCommand = false; if (args.length < 1) { - return showUsage(); + return runShellCommand("package", mArgs); } mAm = IAccountManager.Stub.asInterface(ServiceManager.getService(Context.ACCOUNT_SERVICE)); mUm = IUserManager.Stub.asInterface(ServiceManager.getService(Context.USER_SERVICE)); @@ -134,18 +133,6 @@ public final class Pm { String op = args[0]; mNextArg = 1; - if ("list".equals(op)) { - return runList(); - } - - if ("path".equals(op)) { - return runPath(); - } - - if ("dump".equals(op)) { - return runDump(); - } - if ("install".equals(op)) { return runInstall(); } @@ -166,134 +153,7 @@ public final class Pm { return runInstallAbandon(); } - if ("set-installer".equals(op)) { - return runSetInstaller(); - } - - if ("uninstall".equals(op)) { - return runUninstall(); - } - - if ("clear".equals(op)) { - return runClear(); - } - - if ("enable".equals(op)) { - return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED); - } - - if ("disable".equals(op)) { - return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); - } - - if ("disable-user".equals(op)) { - return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER); - } - - if ("disable-until-used".equals(op)) { - return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED); - } - - if ("default-state".equals(op)) { - return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT); - } - - if ("hide".equals(op)) { - return runSetHiddenSetting(true); - } - - if ("unhide".equals(op)) { - return runSetHiddenSetting(false); - } - - if ("grant".equals(op)) { - return runGrantRevokePermission(true); - } - - if ("revoke".equals(op)) { - return runGrantRevokePermission(false); - } - - if ("reset-permissions".equals(op)) { - return runResetPermissions(); - } - - if ("set-permission-enforced".equals(op)) { - return runSetPermissionEnforced(); - } - - if ("set-app-link".equals(op)) { - return runSetAppLink(); - } - - if ("get-app-link".equals(op)) { - return runGetAppLink(); - } - - if ("set-install-location".equals(op)) { - return runSetInstallLocation(); - } - - if ("get-install-location".equals(op)) { - return runGetInstallLocation(); - } - - if ("trim-caches".equals(op)) { - return runTrimCaches(); - } - - if ("create-user".equals(op)) { - return runCreateUser(); - } - - if ("remove-user".equals(op)) { - return runRemoveUser(); - } - - if ("get-max-users".equals(op)) { - return runGetMaxUsers(); - } - - if ("force-dex-opt".equals(op)) { - return runForceDexOpt(); - } - - if ("move-package".equals(op)) { - return runMovePackage(); - } - - if ("move-primary-storage".equals(op)) { - return runMovePrimaryStorage(); - } - - if ("set-user-restriction".equals(op)) { - return runSetUserRestriction(); - } - - try { - if (args.length == 1) { - if (args[0].equalsIgnoreCase("-l")) { - validCommand = true; - return runShellCommand("package", new String[] { "list", "package" }); - } else if (args[0].equalsIgnoreCase("-lf")) { - validCommand = true; - return runShellCommand("package", new String[] { "list", "package", "-f" }); - } - } else if (args.length == 2) { - if (args[0].equalsIgnoreCase("-p")) { - validCommand = true; - return displayPackageFilePath(args[1], UserHandle.USER_SYSTEM); - } - } - return 1; - } finally { - if (validCommand == false) { - if (op != null) { - System.err.println("Error: unknown command '" + op + "'"); - } - showUsage(); - } - } + return runShellCommand("package", mArgs); } static final class MyShellCallback extends ShellCallback { @@ -704,59 +564,6 @@ public final class Pm { } } - /** - * Execute the list sub-command. - * - * pm list [package | packages] - * pm list permission-groups - * pm list permissions - * pm list features - * pm list libraries - * pm list instrumentation - */ - private int runList() { - final String type = nextArg(); - if ("users".equals(type)) { - return runShellCommand("user", new String[] { "list" }); - } - return runShellCommand("package", mArgs); - } - - private int runUninstall() { - return runShellCommand("package", mArgs); - } - - private int runPath() { - int userId = UserHandle.USER_SYSTEM; - String option = nextOption(); - if (option != null && option.equals("--user")) { - String optionData = nextOptionData(); - if (optionData == null || !isNumber(optionData)) { - System.err.println("Error: no USER_ID specified"); - return showUsage(); - } else { - userId = Integer.parseInt(optionData); - } - } - - String pkg = nextArg(); - if (pkg == null) { - System.err.println("Error: no package specified"); - return 1; - } - return displayPackageFilePath(pkg, userId); - } - - private int runDump() { - String pkg = nextArg(); - if (pkg == null) { - System.err.println("Error: no package specified"); - return 1; - } - ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg); - return 0; - } - class LocalPackageInstallObserver extends PackageInstallObserver { boolean finished; int result; @@ -779,403 +586,16 @@ public final class Pm { } } - // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined} - private int runSetAppLink() { - int userId = UserHandle.USER_SYSTEM; - - String opt; - while ((opt = nextOption()) != null) { - if (opt.equals("--user")) { - userId = Integer.parseInt(nextOptionData()); - if (userId < 0) { - System.err.println("Error: user must be >= 0"); - return 1; - } - } else { - System.err.println("Error: unknown option: " + opt); - return showUsage(); - } - } - - // Package name to act on; required - final String pkg = nextArg(); - if (pkg == null) { - System.err.println("Error: no package specified."); - return showUsage(); - } - - // State to apply; {always|ask|never|undefined}, required - final String modeString = nextArg(); - if (modeString == null) { - System.err.println("Error: no app link state specified."); - return showUsage(); - } - - final int newMode; - switch (modeString.toLowerCase()) { - case "undefined": - newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; - break; - - case "always": - newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; - break; - - case "ask": - newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; - break; - - case "always-ask": - newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; - break; - - case "never": - newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; - break; - - default: - System.err.println("Error: unknown app link state '" + modeString + "'"); - return 1; - } - - try { - final PackageInfo info = mPm.getPackageInfo(pkg, 0, userId); - if (info == null) { - System.err.println("Error: package " + pkg + " not found."); - return 1; - } - - if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) { - System.err.println("Error: package " + pkg + " does not handle web links."); - return 1; - } - - if (!mPm.updateIntentVerificationStatus(pkg, newMode, userId)) { - System.err.println("Error: unable to update app link status for " + pkg); - return 1; - } - } catch (Exception e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } - - return 0; - } - - // pm get-app-link [--user USER_ID] PACKAGE - private int runGetAppLink() { - int userId = UserHandle.USER_SYSTEM; - - String opt; - while ((opt = nextOption()) != null) { - if (opt.equals("--user")) { - userId = Integer.parseInt(nextOptionData()); - if (userId < 0) { - System.err.println("Error: user must be >= 0"); - return 1; - } - } else { - System.err.println("Error: unknown option: " + opt); - return showUsage(); - } - } - - // Package name to act on; required - final String pkg = nextArg(); - if (pkg == null) { - System.err.println("Error: no package specified."); - return showUsage(); - } - - try { - final PackageInfo info = mPm.getPackageInfo(pkg, 0, userId); - if (info == null) { - System.err.println("Error: package " + pkg + " not found."); - return 1; - } - - if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) { - System.err.println("Error: package " + pkg + " does not handle web links."); - return 1; - } - - System.out.println(linkStateToString(mPm.getIntentVerificationStatus(pkg, userId))); - } catch (Exception e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } - - return 0; - } - - private String linkStateToString(int state) { - switch (state) { - case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined"; - case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask"; - case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always"; - case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never"; - case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask"; - } - return "Unknown link state: " + state; - } - - private int runSetInstallLocation() { - int loc; - - String arg = nextArg(); - if (arg == null) { - System.err.println("Error: no install location specified."); - return 1; - } - try { - loc = Integer.parseInt(arg); - } catch (NumberFormatException e) { - System.err.println("Error: install location has to be a number."); - return 1; - } - try { - if (!mPm.setInstallLocation(loc)) { - System.err.println("Error: install location has to be a number."); - return 1; - } - return 0; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } - } - - private int runGetInstallLocation() { - try { - int loc = mPm.getInstallLocation(); - String locStr = "invalid"; - if (loc == PackageHelper.APP_INSTALL_AUTO) { - locStr = "auto"; - } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) { - locStr = "internal"; - } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) { - locStr = "external"; - } - System.out.println(loc + "[" + locStr + "]"); - return 0; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } - } - - private int runSetInstaller() throws RemoteException { - final String targetPackage = nextArg(); - final String installerPackageName = nextArg(); - - if (targetPackage == null || installerPackageName == null) { - throw new IllegalArgumentException( - "must provide both target and installer package names"); - } - - mPm.setInstallerPackageName(targetPackage, installerPackageName); - System.out.println("Success"); - return 0; - } - - public int runCreateUser() { - String name; - int userId = -1; - int flags = 0; - String opt; - while ((opt = nextOption()) != null) { - if ("--profileOf".equals(opt)) { - String optionData = nextOptionData(); - if (optionData == null || !isNumber(optionData)) { - System.err.println("Error: no USER_ID specified"); - return showUsage(); - } else { - userId = Integer.parseInt(optionData); - } - } else if ("--managed".equals(opt)) { - flags |= UserInfo.FLAG_MANAGED_PROFILE; - } else if ("--restricted".equals(opt)) { - flags |= UserInfo.FLAG_RESTRICTED; - } else if ("--ephemeral".equals(opt)) { - flags |= UserInfo.FLAG_EPHEMERAL; - } else if ("--guest".equals(opt)) { - flags |= UserInfo.FLAG_GUEST; - } else if ("--demo".equals(opt)) { - flags |= UserInfo.FLAG_DEMO; - } else { - System.err.println("Error: unknown option " + opt); - return showUsage(); - } - } - String arg = nextArg(); - if (arg == null) { - System.err.println("Error: no user name specified."); - return 1; - } - name = arg; - try { - UserInfo info; - if ((flags & UserInfo.FLAG_RESTRICTED) != 0) { - // In non-split user mode, userId can only be SYSTEM - int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM; - info = mUm.createRestrictedProfile(name, parentUserId); - mAm.addSharedAccountsFromParentUser(parentUserId, userId, - (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell"); - } else if (userId < 0) { - info = mUm.createUser(name, flags); - } else { - info = mUm.createProfileForUser(name, flags, userId, null); - } - - if (info != null) { - System.out.println("Success: created user id " + info.id); - return 0; - } else { - System.err.println("Error: couldn't create User."); - return 1; - } - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } - } - - public int runRemoveUser() { - int userId; - String arg = nextArg(); - if (arg == null) { - System.err.println("Error: no user id specified."); - return 1; - } - try { - userId = Integer.parseInt(arg); - } catch (NumberFormatException e) { - System.err.println("Error: user id '" + arg + "' is not a number."); - return 1; - } - try { - if (mUm.removeUser(userId)) { - System.out.println("Success: removed user"); - return 0; - } else { - System.err.println("Error: couldn't remove user id " + userId); - return 1; - } - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } - } - - public int runGetMaxUsers() { - System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers()); - return 0; - } - - public int runForceDexOpt() { - final String packageName = nextArg(); - try { - mPm.forceDexOpt(packageName); - return 0; - } catch (RemoteException e) { - throw e.rethrowAsRuntimeException(); - } - } - - public int runMovePackage() { - final String packageName = nextArg(); - String volumeUuid = nextArg(); - if ("internal".equals(volumeUuid)) { - volumeUuid = null; - } - - try { - final int moveId = mPm.movePackage(packageName, volumeUuid); - - int status = mPm.getMoveStatus(moveId); - while (!PackageManager.isMoveStatusFinished(status)) { - SystemClock.sleep(DateUtils.SECOND_IN_MILLIS); - status = mPm.getMoveStatus(moveId); - } - - if (status == PackageManager.MOVE_SUCCEEDED) { - System.out.println("Success"); - return 0; - } else { - System.err.println("Failure [" + status + "]"); - return 1; - } - } catch (RemoteException e) { - throw e.rethrowAsRuntimeException(); - } - } - - public int runMovePrimaryStorage() { - String volumeUuid = nextArg(); - if ("internal".equals(volumeUuid)) { - volumeUuid = null; - } - - try { - final int moveId = mPm.movePrimaryStorage(volumeUuid); - - int status = mPm.getMoveStatus(moveId); - while (!PackageManager.isMoveStatusFinished(status)) { - SystemClock.sleep(DateUtils.SECOND_IN_MILLIS); - status = mPm.getMoveStatus(moveId); - } - - if (status == PackageManager.MOVE_SUCCEEDED) { - System.out.println("Success"); - return 0; - } else { - System.err.println("Failure [" + status + "]"); - return 1; - } - } catch (RemoteException e) { - throw e.rethrowAsRuntimeException(); - } - } - - public int runSetUserRestriction() { - int userId = UserHandle.USER_SYSTEM; - String opt = nextOption(); - if (opt != null && "--user".equals(opt)) { - String arg = nextArg(); - if (arg == null || !isNumber(arg)) { - System.err.println("Error: valid userId not specified"); - return 1; - } - userId = Integer.parseInt(arg); - } - - String restriction = nextArg(); - String arg = nextArg(); - boolean value; - if ("1".equals(arg)) { - value = true; - } else if ("0".equals(arg)) { - value = false; - } else { - System.err.println("Error: valid value not specified"); - return 1; - } + private static boolean isNumber(String s) { try { - mUm.setUserRestriction(restriction, value, userId); - return 0; - } catch (RemoteException e) { - System.err.println(e.toString()); - return 1; + Integer.parseInt(s); + } catch (NumberFormatException nfe) { + return false; } + return true; } - static class ClearDataObserver extends IPackageDataObserver.Stub { + static class ClearCacheObserver extends IPackageDataObserver.Stub { boolean finished; boolean result; @@ -1187,242 +607,10 @@ public final class Pm { notifyAll(); } } - } - - private int runClear() { - int userId = UserHandle.USER_SYSTEM; - String option = nextOption(); - if (option != null && option.equals("--user")) { - String optionData = nextOptionData(); - if (optionData == null || !isNumber(optionData)) { - System.err.println("Error: no USER_ID specified"); - return showUsage(); - } else { - userId = Integer.parseInt(optionData); - } - } - - String pkg = nextArg(); - if (pkg == null) { - System.err.println("Error: no package specified"); - return showUsage(); - } - - ClearDataObserver obs = new ClearDataObserver(); - try { - ActivityManager.getService().clearApplicationUserData(pkg, obs, userId); - synchronized (obs) { - while (!obs.finished) { - try { - obs.wait(); - } catch (InterruptedException e) { - } - } - } - - if (obs.result) { - System.out.println("Success"); - return 0; - } else { - System.err.println("Failed"); - return 1; - } - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } - } - - private static String enabledSettingToString(int state) { - switch (state) { - case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT: - return "default"; - case PackageManager.COMPONENT_ENABLED_STATE_ENABLED: - return "enabled"; - case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: - return "disabled"; - case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER: - return "disabled-user"; - case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED: - return "disabled-until-used"; - } - return "unknown"; - } - - private static boolean isNumber(String s) { - try { - Integer.parseInt(s); - } catch (NumberFormatException nfe) { - return false; - } - return true; - } - - private int runSetEnabledSetting(int state) { - int userId = UserHandle.USER_SYSTEM; - String option = nextOption(); - if (option != null && option.equals("--user")) { - String optionData = nextOptionData(); - if (optionData == null || !isNumber(optionData)) { - System.err.println("Error: no USER_ID specified"); - return showUsage(); - } else { - userId = Integer.parseInt(optionData); - } - } - - String pkg = nextArg(); - if (pkg == null) { - System.err.println("Error: no package or component specified"); - return showUsage(); - } - ComponentName cn = ComponentName.unflattenFromString(pkg); - if (cn == null) { - try { - mPm.setApplicationEnabledSetting(pkg, state, 0, userId, - "shell:" + android.os.Process.myUid()); - System.out.println("Package " + pkg + " new state: " - + enabledSettingToString( - mPm.getApplicationEnabledSetting(pkg, userId))); - return 0; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } - } else { - try { - mPm.setComponentEnabledSetting(cn, state, 0, userId); - System.out.println("Component " + cn.toShortString() + " new state: " - + enabledSettingToString( - mPm.getComponentEnabledSetting(cn, userId))); - return 0; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } - } - } - - private int runSetHiddenSetting(boolean state) { - int userId = UserHandle.USER_SYSTEM; - String option = nextOption(); - if (option != null && option.equals("--user")) { - String optionData = nextOptionData(); - if (optionData == null || !isNumber(optionData)) { - System.err.println("Error: no USER_ID specified"); - return showUsage(); - } else { - userId = Integer.parseInt(optionData); - } - } - - String pkg = nextArg(); - if (pkg == null) { - System.err.println("Error: no package or component specified"); - return showUsage(); - } - try { - mPm.setApplicationHiddenSettingAsUser(pkg, state, userId); - System.out.println("Package " + pkg + " new hidden state: " - + mPm.getApplicationHiddenSettingAsUser(pkg, userId)); - return 0; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } - } - - private int runGrantRevokePermission(boolean grant) { - int userId = UserHandle.USER_SYSTEM; - - String opt = null; - while ((opt = nextOption()) != null) { - if (opt.equals("--user")) { - userId = Integer.parseInt(nextArg()); - } - } - - String pkg = nextArg(); - if (pkg == null) { - System.err.println("Error: no package specified"); - return showUsage(); - } - String perm = nextArg(); - if (perm == null) { - System.err.println("Error: no permission specified"); - return showUsage(); - } - - try { - if (grant) { - mPm.grantRuntimePermission(pkg, perm, userId); - } else { - mPm.revokeRuntimePermission(pkg, perm, userId); - } - return 0; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } catch (IllegalArgumentException e) { - System.err.println("Bad argument: " + e.toString()); - return showUsage(); - } catch (SecurityException e) { - System.err.println("Operation not allowed: " + e.toString()); - return 1; - } - } - - private int runResetPermissions() { - try { - mPm.resetRuntimePermissions(); - return 0; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } catch (IllegalArgumentException e) { - System.err.println("Bad argument: " + e.toString()); - return showUsage(); - } catch (SecurityException e) { - System.err.println("Operation not allowed: " + e.toString()); - return 1; - } - } - private int runSetPermissionEnforced() { - final String permission = nextArg(); - if (permission == null) { - System.err.println("Error: no permission specified"); - return showUsage(); - } - final String enforcedRaw = nextArg(); - if (enforcedRaw == null) { - System.err.println("Error: no enforcement specified"); - return showUsage(); - } - final boolean enforced = Boolean.parseBoolean(enforcedRaw); - try { - mPm.setPermissionEnforced(permission, enforced); - return 0; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } catch (IllegalArgumentException e) { - System.err.println("Bad argument: " + e.toString()); - return showUsage(); - } catch (SecurityException e) { - System.err.println("Operation not allowed: " + e.toString()); - return 1; - } } - static class ClearCacheObserver extends IPackageDataObserver.Stub { + static class ClearDataObserver extends IPackageDataObserver.Stub { boolean finished; boolean result; @@ -1434,66 +622,6 @@ public final class Pm { notifyAll(); } } - - } - - private int runTrimCaches() { - String size = nextArg(); - if (size == null) { - System.err.println("Error: no size specified"); - return showUsage(); - } - long multiplier = 1; - int len = size.length(); - char c = size.charAt(len - 1); - if (c < '0' || c > '9') { - if (c == 'K' || c == 'k') { - multiplier = 1024L; - } else if (c == 'M' || c == 'm') { - multiplier = 1024L*1024L; - } else if (c == 'G' || c == 'g') { - multiplier = 1024L*1024L*1024L; - } else { - System.err.println("Invalid suffix: " + c); - return showUsage(); - } - size = size.substring(0, len-1); - } - long sizeVal; - try { - sizeVal = Long.parseLong(size) * multiplier; - } catch (NumberFormatException e) { - System.err.println("Error: expected number at: " + size); - return showUsage(); - } - String volumeUuid = nextArg(); - if ("internal".equals(volumeUuid)) { - volumeUuid = null; - } - ClearDataObserver obs = new ClearDataObserver(); - try { - mPm.freeStorageAndNotify(volumeUuid, sizeVal, - StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs); - synchronized (obs) { - while (!obs.finished) { - try { - obs.wait(); - } catch (InterruptedException e) { - } - } - } - return 0; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(PM_NOT_RUNNING_ERR); - return 1; - } catch (IllegalArgumentException e) { - System.err.println("Bad argument: " + e.toString()); - return showUsage(); - } catch (SecurityException e) { - System.err.println("Operation not allowed: " + e.toString()); - return 1; - } } /** diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index a1eda6597f60..280b1e80b01d 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -46,6 +46,7 @@ import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.os.BatteryStats; +import android.os.Binder; import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; @@ -3885,21 +3886,36 @@ public class ActivityManager { IBinder service = ServiceManager.checkService(name); if (service == null) { pw.println(" (Service not found)"); + pw.flush(); return; } - TransferPipe tp = null; - try { - pw.flush(); - tp = new TransferPipe(); - tp.setBufferPrefix(" "); - service.dumpAsync(tp.getWriteFd().getFileDescriptor(), args); - tp.go(fd, 10000); - } catch (Throwable e) { - if (tp != null) { - tp.kill(); + pw.flush(); + if (service instanceof Binder) { + // If this is a local object, it doesn't make sense to do an async dump with it, + // just directly dump. + try { + service.dump(fd, args); + } catch (Throwable e) { + pw.println("Failure dumping service:"); + e.printStackTrace(pw); + pw.flush(); + } + } else { + // Otherwise, it is remote, do the dump asynchronously to avoid blocking. + TransferPipe tp = null; + try { + pw.flush(); + tp = new TransferPipe(); + tp.setBufferPrefix(" "); + service.dumpAsync(tp.getWriteFd().getFileDescriptor(), args); + tp.go(fd, 10000); + } catch (Throwable e) { + if (tp != null) { + tp.kill(); + } + pw.println("Failure dumping service:"); + e.printStackTrace(pw); } - pw.println("Failure dumping service:"); - e.printStackTrace(pw); } } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index a8a65e37f914..a8bd940326d6 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -6453,7 +6453,7 @@ public abstract class BatteryStats implements Parcelable { pw.println(); } } - if (!filtering || (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0) { + if (!filtering || (flags & DUMP_DAILY_ONLY) != 0) { pw.println("Daily stats:"); pw.print(" Current start time: "); pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index e9e695bbdf10..66e1651997b4 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -167,7 +167,7 @@ public class Binder implements IBinder { try { if (binder instanceof BinderProxy) { ((BinderProxy) binder).mWarnOnBlocking = false; - } else if (binder != null + } else if (binder != null && binder.getInterfaceDescriptor() != null && binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) { Log.w(TAG, "Unable to allow blocking on interface " + binder); } @@ -414,7 +414,7 @@ public class Binder implements IBinder { * descriptor. */ public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) { - if (mDescriptor.equals(descriptor)) { + if (mDescriptor != null && mDescriptor.equals(descriptor)) { return mOwner; } return null; diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java index e4a12e84e466..6223235e628f 100644 --- a/core/java/android/os/ShellCommand.java +++ b/core/java/android/os/ShellCommand.java @@ -17,6 +17,7 @@ package android.os; import android.util.Slog; + import com.android.internal.util.FastPrintWriter; import java.io.BufferedInputStream; @@ -118,13 +119,33 @@ public abstract class ShellCommand { mErrPrintWriter.flush(); } if (DEBUG) Slog.d(TAG, "Sending command result on " + mTarget); - mResultReceiver.send(res, null); + if (mResultReceiver != null) { + mResultReceiver.send(res, null); + } } if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget); return res; } /** + * Adopt the ResultReceiver that was given to this shell command from it, taking + * it over. Primarily used to dispatch to another shell command. Once called, + * this shell command will no longer return its own result when done. + */ + public ResultReceiver adoptResultReceiver() { + ResultReceiver rr = mResultReceiver; + mResultReceiver = null; + return rr; + } + + /** + * Return the raw FileDescriptor for the output stream. + */ + public FileDescriptor getOutFileDescriptor() { + return mOut; + } + + /** * Return direct raw access (not buffered) to the command's output data stream. */ public OutputStream getRawOutputStream() { @@ -145,6 +166,13 @@ public abstract class ShellCommand { } /** + * Return the raw FileDescriptor for the error stream. + */ + public FileDescriptor getErrFileDescriptor() { + return mErr; + } + + /** * Return direct raw access (not buffered) to the command's error output data stream. */ public OutputStream getRawErrorStream() { @@ -168,6 +196,13 @@ public abstract class ShellCommand { } /** + * Return the raw FileDescriptor for the input stream. + */ + public FileDescriptor getInFileDescriptor() { + return mIn; + } + + /** * Return direct raw access (not buffered) to the command's input data stream. */ public InputStream getRawInputStream() { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 14c5d6a27c5d..a513e140ba2b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -15685,7 +15685,8 @@ public class ActivityManagerService extends IActivityManager.Stub } pw.println(" mPreviousProcess: " + mPreviousProcess); } - if (dumpAll) { + if (dumpAll && (mPreviousProcess == null || dumpPackage == null + || mPreviousProcess.pkgList.containsKey(dumpPackage))) { StringBuilder sb = new StringBuilder(128); sb.append(" mPreviousProcessVisibleTime: "); TimeUtils.formatDuration(mPreviousProcessVisibleTime, sb); @@ -15704,7 +15705,9 @@ public class ActivityManagerService extends IActivityManager.Stub mStackSupervisor.dumpDisplayConfigs(pw, " "); } if (dumpAll) { - pw.println(" mConfigWillChange: " + getFocusedStack().mConfigWillChange); + if (dumpPackage == null) { + pw.println(" mConfigWillChange: " + getFocusedStack().mConfigWillChange); + } if (mCompatModePackages.getPackages().size() > 0) { boolean printed = false; for (Map.Entry<String, Integer> entry @@ -15784,8 +15787,8 @@ public class ActivityManagerService extends IActivityManager.Stub pw.println(" mRunningVoice=" + mRunningVoice); pw.println(" mVoiceWakeLock" + mVoiceWakeLock); } + pw.println(" mVrController=" + mVrController); } - pw.println(" mVrController=" + mVrController); if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient || mOrigWaitForDebugger) { if (dumpPackage == null || dumpPackage.equals(mDebugApp) diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 1fea003a9cc1..a2099e6080e5 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -16,14 +16,17 @@ package com.android.server.pm; +import android.accounts.IAccountManager; import android.app.ActivityManager; import android.content.ComponentName; +import android.content.Context; import android.content.IIntentReceiver; import android.content.IIntentSender; import android.content.Intent; import android.content.IntentSender; import android.content.pm.ApplicationInfo; import android.content.pm.FeatureInfo; +import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; @@ -41,6 +44,7 @@ import android.content.pm.PackageInstaller.SessionInfo; import android.content.pm.PackageInstaller.SessionParams; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; +import android.content.pm.UserInfo; import android.content.pm.VersionedPackage; import android.content.res.AssetManager; import android.content.res.Resources; @@ -49,15 +53,23 @@ import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.IBinder; +import android.os.IUserManager; +import android.os.Process; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.ShellCommand; +import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; +import android.os.UserManager; +import android.os.storage.StorageManager; import android.text.TextUtils; -import android.util.ArrayMap; +import android.text.format.DateUtils; import android.util.ArraySet; import android.util.PrintWriterPrinter; + import com.android.internal.content.PackageHelper; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.SizedInputStream; import com.android.server.SystemConfig; @@ -81,6 +93,12 @@ import java.util.WeakHashMap; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; + class PackageManagerShellCommand extends ShellCommand { /** Path for streaming APK content */ private static final String STDIN_PATH = "-"; @@ -107,6 +125,20 @@ class PackageManagerShellCommand extends ShellCommand { final PrintWriter pw = getOutPrintWriter(); try { switch(cmd) { + case "path": + return runPath(); + case "dump": + return runDump(); + case "list": + return runList(); + case "resolve-activity": + return runResolveActivity(); + case "query-activities": + return runQueryIntentActivities(); + case "query-services": + return runQueryIntentServices(); + case "query-receivers": + return runQueryIntentReceivers(); case "install": return runInstall(); case "install-abandon": @@ -122,44 +154,99 @@ class PackageManagerShellCommand extends ShellCommand { return runInstallWrite(); case "install-existing": return runInstallExisting(); + case "set-install-location": + return runSetInstallLocation(); + case "get-install-location": + return runGetInstallLocation(); + case "move-package": + return runMovePackage(); + case "move-primary-storage": + return runMovePrimaryStorage(); case "compile": return runCompile(); case "reconcile-secondary-dex-files": return runreconcileSecondaryDexFiles(); + case "force-dex-opt": + return runForceDexOpt(); case "bg-dexopt-job": return runDexoptJob(); case "dump-profiles": return runDumpProfiles(); - case "list": - return runList(); case "uninstall": return runUninstall(); - case "resolve-activity": - return runResolveActivity(); - case "query-activities": - return runQueryIntentActivities(); - case "query-services": - return runQueryIntentServices(); - case "query-receivers": - return runQueryIntentReceivers(); + case "clear": + return runClear(); + case "enable": + return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED); + case "disable": + return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); + case "disable-user": + return runSetEnabledSetting( + PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER); + case "disable-until-used": + return runSetEnabledSetting( + PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED); + case "default-state": + return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT); + case "hide": + return runSetHiddenSetting(true); + case "unhide": + return runSetHiddenSetting(false); case "suspend": return runSuspend(true); case "unsuspend": return runSuspend(false); - case "set-home-activity": - return runSetHomeActivity(); + case "grant": + return runGrantRevokePermission(true); + case "revoke": + return runGrantRevokePermission(false); + case "reset-permissions": + return runResetPermissions(); + case "set-permission-enforced": + return runSetPermissionEnforced(); case "get-privapp-permissions": return runGetPrivappPermissions(); case "get-privapp-deny-permissions": return runGetPrivappDenyPermissions(); case "get-oem-permissions": return runGetOemPermissions(); + case "set-app-link": + return runSetAppLink(); + case "get-app-link": + return runGetAppLink(); + case "trim-caches": + return runTrimCaches(); + case "create-user": + return runCreateUser(); + case "remove-user": + return runRemoveUser(); + case "set-user-restriction": + return runSetUserRestriction(); + case "get-max-users": + return runGetMaxUsers(); + case "set-home-activity": + return runSetHomeActivity(); + case "set-installer": + return runSetInstaller(); case "get-instantapp-resolver": return runGetInstantAppResolver(); case "has-feature": return runHasFeature(); - default: + default: { + String nextArg = getNextArg(); + if (nextArg == null) { + if (cmd.equalsIgnoreCase("-l")) { + return runListPackages(false); + } else if (cmd.equalsIgnoreCase("-lf")) { + return runListPackages(true); + } + } else if (getNextArg() == null) { + if (cmd.equalsIgnoreCase("-p")) { + return displayPackageFilePath(nextArg, UserHandle.USER_SYSTEM); + } + } return handleDefaultCommands(cmd); + } } } catch (RemoteException e) { pw.println("Remote exception: " + e); @@ -195,346 +282,40 @@ class PackageManagerShellCommand extends ShellCommand { } } } - - private int runInstall() throws RemoteException { - final PrintWriter pw = getOutPrintWriter(); - final InstallParams params = makeInstallParams(); - final String inPath = getNextArg(); - - setParamsSize(params, inPath); - final int sessionId = doCreateSession(params.sessionParams, - params.installerPackageName, params.userId); - boolean abandonSession = true; - try { - if (inPath == null && params.sessionParams.sizeBytes == -1) { - pw.println("Error: must either specify a package size or an APK file"); - return 1; - } - if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk", - false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { - return 1; - } - if (doCommitSession(sessionId, false /*logSuccess*/) - != PackageInstaller.STATUS_SUCCESS) { - return 1; - } - abandonSession = false; - pw.println("Success"); - return 0; - } finally { - if (abandonSession) { - try { - doAbandonSession(sessionId, false /*logSuccess*/); - } catch (Exception ignore) { + /** + * Displays the package file for a package. + * @param pckg + */ + private int displayPackageFilePath(String pckg, int userId) throws RemoteException { + PackageInfo info = mInterface.getPackageInfo(pckg, 0, userId); + if (info != null && info.applicationInfo != null) { + final PrintWriter pw = getOutPrintWriter(); + pw.print("package:"); + pw.println(info.applicationInfo.sourceDir); + if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) { + for (String splitSourceDir : info.applicationInfo.splitSourceDirs) { + pw.print("package:"); + pw.println(splitSourceDir); } } - } - } - - private int runSuspend(boolean suspendedState) { - final PrintWriter pw = getOutPrintWriter(); - int userId = UserHandle.USER_SYSTEM; - String opt; - while ((opt = getNextOption()) != null) { - switch (opt) { - case "--user": - userId = UserHandle.parseUserArg(getNextArgRequired()); - break; - default: - pw.println("Error: Unknown option: " + opt); - return 1; - } - } - - String packageName = getNextArg(); - if (packageName == null) { - pw.println("Error: package name not specified"); - return 1; - } - - try { - mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState, - userId); - pw.println("Package " + packageName + " new suspended state: " - + mInterface.isPackageSuspendedForUser(packageName, userId)); return 0; - } catch (RemoteException | IllegalArgumentException e) { - pw.println(e.toString()); - return 1; } + return 1; } - private int runInstallAbandon() throws RemoteException { - final int sessionId = Integer.parseInt(getNextArg()); - return doAbandonSession(sessionId, true /*logSuccess*/); - } - - private int runInstallCommit() throws RemoteException { - final int sessionId = Integer.parseInt(getNextArg()); - return doCommitSession(sessionId, true /*logSuccess*/); - } - - private int runInstallCreate() throws RemoteException { - final PrintWriter pw = getOutPrintWriter(); - final InstallParams installParams = makeInstallParams(); - final int sessionId = doCreateSession(installParams.sessionParams, - installParams.installerPackageName, installParams.userId); - - // NOTE: adb depends on parsing this string - pw.println("Success: created install session [" + sessionId + "]"); - return 0; - } - - private int runInstallWrite() throws RemoteException { - long sizeBytes = -1; - - String opt; - while ((opt = getNextOption()) != null) { - if (opt.equals("-S")) { - sizeBytes = Long.parseLong(getNextArg()); - } else { - throw new IllegalArgumentException("Unknown option: " + opt); - } - } - - final int sessionId = Integer.parseInt(getNextArg()); - final String splitName = getNextArg(); - final String path = getNextArg(); - return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/); - } - - private int runInstallRemove() throws RemoteException { - final PrintWriter pw = getOutPrintWriter(); - - final int sessionId = Integer.parseInt(getNextArg()); - - final String splitName = getNextArg(); - if (splitName == null) { - pw.println("Error: split name not specified"); - return 1; - } - return doRemoveSplit(sessionId, splitName, true /*logSuccess*/); - } - - private int runInstallExisting() throws RemoteException { - final PrintWriter pw = getOutPrintWriter(); + private int runPath() throws RemoteException { int userId = UserHandle.USER_SYSTEM; - int installFlags = 0; - String opt; - while ((opt = getNextOption()) != null) { - switch (opt) { - case "--user": - userId = UserHandle.parseUserArg(getNextArgRequired()); - break; - case "--ephemeral": - case "--instant": - installFlags |= PackageManager.INSTALL_INSTANT_APP; - installFlags &= ~PackageManager.INSTALL_FULL_APP; - break; - case "--full": - installFlags &= ~PackageManager.INSTALL_INSTANT_APP; - installFlags |= PackageManager.INSTALL_FULL_APP; - break; - default: - pw.println("Error: Unknown option: " + opt); - return 1; - } + String option = getNextOption(); + if (option != null && option.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); } - final String packageName = getNextArg(); - if (packageName == null) { - pw.println("Error: package name not specified"); - return 1; - } - - try { - final int res = mInterface.installExistingPackageAsUser(packageName, userId, - installFlags, PackageManager.INSTALL_REASON_UNKNOWN); - if (res == PackageManager.INSTALL_FAILED_INVALID_URI) { - throw new NameNotFoundException("Package " + packageName + " doesn't exist"); - } - pw.println("Package " + packageName + " installed for user: " + userId); - return 0; - } catch (RemoteException | NameNotFoundException e) { - pw.println(e.toString()); - return 1; - } - } - - private int runCompile() throws RemoteException { - final PrintWriter pw = getOutPrintWriter(); - boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); - boolean forceCompilation = false; - boolean allPackages = false; - boolean clearProfileData = false; - String compilerFilter = null; - String compilationReason = null; - String checkProfilesRaw = null; - boolean secondaryDex = false; - String split = null; - - String opt; - while ((opt = getNextOption()) != null) { - switch (opt) { - case "-a": - allPackages = true; - break; - case "-c": - clearProfileData = true; - break; - case "-f": - forceCompilation = true; - break; - case "-m": - compilerFilter = getNextArgRequired(); - break; - case "-r": - compilationReason = getNextArgRequired(); - break; - case "--check-prof": - checkProfilesRaw = getNextArgRequired(); - break; - case "--reset": - forceCompilation = true; - clearProfileData = true; - compilationReason = "install"; - break; - case "--secondary-dex": - secondaryDex = true; - break; - case "--split": - split = getNextArgRequired(); - break; - default: - pw.println("Error: Unknown option: " + opt); - return 1; - } - } - - if (checkProfilesRaw != null) { - if ("true".equals(checkProfilesRaw)) { - checkProfiles = true; - } else if ("false".equals(checkProfilesRaw)) { - checkProfiles = false; - } else { - pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\"."); - return 1; - } - } - - if (compilerFilter != null && compilationReason != null) { - pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " + - "at the same time"); - return 1; - } - if (compilerFilter == null && compilationReason == null) { - pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " + - "reason (\"-r\") at the same time"); - return 1; - } - - if (allPackages && split != null) { - pw.println("-a cannot be specified together with --split"); - return 1; - } - - if (secondaryDex && split != null) { - pw.println("--secondary-dex cannot be specified together with --split"); - return 1; - } - - String targetCompilerFilter; - if (compilerFilter != null) { - if (!DexFile.isValidCompilerFilter(compilerFilter)) { - pw.println("Error: \"" + compilerFilter + - "\" is not a valid compilation filter."); - return 1; - } - targetCompilerFilter = compilerFilter; - } else { - int reason = -1; - for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { - if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals( - compilationReason)) { - reason = i; - break; - } - } - if (reason == -1) { - pw.println("Error: Unknown compilation reason: " + compilationReason); - return 1; - } - targetCompilerFilter = - PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason); - } - - - List<String> packageNames = null; - if (allPackages) { - packageNames = mInterface.getAllPackages(); - } else { - String packageName = getNextArg(); - if (packageName == null) { - pw.println("Error: package name not specified"); - return 1; - } - packageNames = Collections.singletonList(packageName); - } - - List<String> failedPackages = new ArrayList<>(); - for (String packageName : packageNames) { - if (clearProfileData) { - mInterface.clearApplicationProfileData(packageName); - } - - boolean result = secondaryDex - ? mInterface.performDexOptSecondary(packageName, - targetCompilerFilter, forceCompilation) - : mInterface.performDexOptMode(packageName, - checkProfiles, targetCompilerFilter, forceCompilation, - true /* bootComplete */, split); - if (!result) { - failedPackages.add(packageName); - } - } - - if (failedPackages.isEmpty()) { - pw.println("Success"); - return 0; - } else if (failedPackages.size() == 1) { - pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled"); - return 1; - } else { - pw.print("Failure: the following packages could not be compiled: "); - boolean is_first = true; - for (String packageName : failedPackages) { - if (is_first) { - is_first = false; - } else { - pw.print(", "); - } - pw.print(packageName); - } - pw.println(); + String pkg = getNextArgRequired(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified"); return 1; } - } - - private int runreconcileSecondaryDexFiles() throws RemoteException { - String packageName = getNextArg(); - mInterface.reconcileSecondaryDexFiles(packageName); - return 0; - } - - private int runDexoptJob() throws RemoteException { - boolean result = mInterface.runBackgroundDexoptJob(); - return result ? 0 : -1; - } - - private int runDumpProfiles() throws RemoteException { - String packageName = getNextArg(); - mInterface.dumpProfiles(packageName); - return 0; + return displayPackageFilePath(pkg, userId); } private int runList() throws RemoteException { @@ -558,6 +339,11 @@ class PackageManagerShellCommand extends ShellCommand { return runListPermissionGroups(); case "permissions": return runListPermissions(); + case "users": + ServiceManager.getService("user").shellCommand( + getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(), + new String[] { "list" }, getShellCallback(), adoptResultReceiver()); + return 0; } pw.println("Error: unknown list type '" + type + "'"); return -1; @@ -590,7 +376,7 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(); } else { pw.println("reqGlEsVersion=0x" - + Integer.toHexString(fi.reqGlEsVersion)); + + Integer.toHexString(fi.reqGlEsVersion)); } } return 0; @@ -872,111 +658,6 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } - private int runUninstall() throws RemoteException { - final PrintWriter pw = getOutPrintWriter(); - int flags = 0; - int userId = UserHandle.USER_ALL; - int versionCode = PackageManager.VERSION_CODE_HIGHEST; - - String opt; - while ((opt = getNextOption()) != null) { - switch (opt) { - case "-k": - flags |= PackageManager.DELETE_KEEP_DATA; - break; - case "--user": - userId = UserHandle.parseUserArg(getNextArgRequired()); - break; - case "--versionCode": - versionCode = Integer.parseInt(getNextArgRequired()); - break; - default: - pw.println("Error: Unknown option: " + opt); - return 1; - } - } - - final String packageName = getNextArg(); - if (packageName == null) { - pw.println("Error: package name not specified"); - return 1; - } - - // if a split is specified, just remove it and not the whole package - final String splitName = getNextArg(); - if (splitName != null) { - return runRemoveSplit(packageName, splitName); - } - - userId = translateUserId(userId, "runUninstall"); - if (userId == UserHandle.USER_ALL) { - userId = UserHandle.USER_SYSTEM; - flags |= PackageManager.DELETE_ALL_USERS; - } else { - final PackageInfo info = mInterface.getPackageInfo(packageName, - PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId); - if (info == null) { - pw.println("Failure [not installed for " + userId + "]"); - return 1; - } - final boolean isSystem = - (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; - // If we are being asked to delete a system app for just one - // user set flag so it disables rather than reverting to system - // version of the app. - if (isSystem) { - flags |= PackageManager.DELETE_SYSTEM_APP; - } - } - - final LocalIntentReceiver receiver = new LocalIntentReceiver(); - mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName, - versionCode), null /*callerPackageName*/, flags, - receiver.getIntentSender(), userId); - - final Intent result = receiver.getResult(); - final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, - PackageInstaller.STATUS_FAILURE); - if (status == PackageInstaller.STATUS_SUCCESS) { - pw.println("Success"); - return 0; - } else { - pw.println("Failure [" - + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); - return 1; - } - } - - private int runRemoveSplit(String packageName, String splitName) throws RemoteException { - final PrintWriter pw = getOutPrintWriter(); - final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING); - sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; - sessionParams.appPackageName = packageName; - final int sessionId = - doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL); - boolean abandonSession = true; - try { - if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/) - != PackageInstaller.STATUS_SUCCESS) { - return 1; - } - if (doCommitSession(sessionId, false /*logSuccess*/) - != PackageInstaller.STATUS_SUCCESS) { - return 1; - } - abandonSession = false; - pw.println("Success"); - return 0; - } finally { - if (abandonSession) { - try { - doAbandonSession(sessionId, false /*logSuccess*/); - } catch (Exception ignore) { - } - } - } - } - private Intent parseIntentAndUser() throws URISyntaxException { mTargetUser = UserHandle.USER_CURRENT; mBrief = false; @@ -1154,6 +835,1029 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } + private int runInstall() throws RemoteException { + final PrintWriter pw = getOutPrintWriter(); + final InstallParams params = makeInstallParams(); + final String inPath = getNextArg(); + + setParamsSize(params, inPath); + final int sessionId = doCreateSession(params.sessionParams, + params.installerPackageName, params.userId); + boolean abandonSession = true; + try { + if (inPath == null && params.sessionParams.sizeBytes == -1) { + pw.println("Error: must either specify a package size or an APK file"); + return 1; + } + if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk", + false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { + return 1; + } + if (doCommitSession(sessionId, false /*logSuccess*/) + != PackageInstaller.STATUS_SUCCESS) { + return 1; + } + abandonSession = false; + pw.println("Success"); + return 0; + } finally { + if (abandonSession) { + try { + doAbandonSession(sessionId, false /*logSuccess*/); + } catch (Exception ignore) { + } + } + } + } + + private int runInstallAbandon() throws RemoteException { + final int sessionId = Integer.parseInt(getNextArg()); + return doAbandonSession(sessionId, true /*logSuccess*/); + } + + private int runInstallCommit() throws RemoteException { + final int sessionId = Integer.parseInt(getNextArg()); + return doCommitSession(sessionId, true /*logSuccess*/); + } + + private int runInstallCreate() throws RemoteException { + final PrintWriter pw = getOutPrintWriter(); + final InstallParams installParams = makeInstallParams(); + final int sessionId = doCreateSession(installParams.sessionParams, + installParams.installerPackageName, installParams.userId); + + // NOTE: adb depends on parsing this string + pw.println("Success: created install session [" + sessionId + "]"); + return 0; + } + + private int runInstallWrite() throws RemoteException { + long sizeBytes = -1; + + String opt; + while ((opt = getNextOption()) != null) { + if (opt.equals("-S")) { + sizeBytes = Long.parseLong(getNextArg()); + } else { + throw new IllegalArgumentException("Unknown option: " + opt); + } + } + + final int sessionId = Integer.parseInt(getNextArg()); + final String splitName = getNextArg(); + final String path = getNextArg(); + return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/); + } + + private int runInstallRemove() throws RemoteException { + final PrintWriter pw = getOutPrintWriter(); + + final int sessionId = Integer.parseInt(getNextArg()); + + final String splitName = getNextArg(); + if (splitName == null) { + pw.println("Error: split name not specified"); + return 1; + } + return doRemoveSplit(sessionId, splitName, true /*logSuccess*/); + } + + private int runInstallExisting() throws RemoteException { + final PrintWriter pw = getOutPrintWriter(); + int userId = UserHandle.USER_SYSTEM; + int installFlags = 0; + String opt; + while ((opt = getNextOption()) != null) { + switch (opt) { + case "--user": + userId = UserHandle.parseUserArg(getNextArgRequired()); + break; + case "--ephemeral": + case "--instant": + installFlags |= PackageManager.INSTALL_INSTANT_APP; + installFlags &= ~PackageManager.INSTALL_FULL_APP; + break; + case "--full": + installFlags &= ~PackageManager.INSTALL_INSTANT_APP; + installFlags |= PackageManager.INSTALL_FULL_APP; + break; + default: + pw.println("Error: Unknown option: " + opt); + return 1; + } + } + + final String packageName = getNextArg(); + if (packageName == null) { + pw.println("Error: package name not specified"); + return 1; + } + + try { + final int res = mInterface.installExistingPackageAsUser(packageName, userId, + installFlags, PackageManager.INSTALL_REASON_UNKNOWN); + if (res == PackageManager.INSTALL_FAILED_INVALID_URI) { + throw new NameNotFoundException("Package " + packageName + " doesn't exist"); + } + pw.println("Package " + packageName + " installed for user: " + userId); + return 0; + } catch (RemoteException | NameNotFoundException e) { + pw.println(e.toString()); + return 1; + } + } + + private int runSetInstallLocation() throws RemoteException { + int loc; + + String arg = getNextArg(); + if (arg == null) { + getErrPrintWriter().println("Error: no install location specified."); + return 1; + } + try { + loc = Integer.parseInt(arg); + } catch (NumberFormatException e) { + getErrPrintWriter().println("Error: install location has to be a number."); + return 1; + } + if (!mInterface.setInstallLocation(loc)) { + getErrPrintWriter().println("Error: install location has to be a number."); + return 1; + } + return 0; + } + + private int runGetInstallLocation() throws RemoteException { + int loc = mInterface.getInstallLocation(); + String locStr = "invalid"; + if (loc == PackageHelper.APP_INSTALL_AUTO) { + locStr = "auto"; + } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) { + locStr = "internal"; + } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) { + locStr = "external"; + } + getOutPrintWriter().println(loc + "[" + locStr + "]"); + return 0; + } + + public int runMovePackage() throws RemoteException { + final String packageName = getNextArg(); + if (packageName == null) { + getErrPrintWriter().println("Error: package name not specified"); + return 1; + } + String volumeUuid = getNextArg(); + if ("internal".equals(volumeUuid)) { + volumeUuid = null; + } + + final int moveId = mInterface.movePackage(packageName, volumeUuid); + + int status = mInterface.getMoveStatus(moveId); + while (!PackageManager.isMoveStatusFinished(status)) { + SystemClock.sleep(DateUtils.SECOND_IN_MILLIS); + status = mInterface.getMoveStatus(moveId); + } + + if (status == PackageManager.MOVE_SUCCEEDED) { + getOutPrintWriter().println("Success"); + return 0; + } else { + getErrPrintWriter().println("Failure [" + status + "]"); + return 1; + } + } + + public int runMovePrimaryStorage() throws RemoteException { + String volumeUuid = getNextArg(); + if ("internal".equals(volumeUuid)) { + volumeUuid = null; + } + + final int moveId = mInterface.movePrimaryStorage(volumeUuid); + + int status = mInterface.getMoveStatus(moveId); + while (!PackageManager.isMoveStatusFinished(status)) { + SystemClock.sleep(DateUtils.SECOND_IN_MILLIS); + status = mInterface.getMoveStatus(moveId); + } + + if (status == PackageManager.MOVE_SUCCEEDED) { + getOutPrintWriter().println("Success"); + return 0; + } else { + getErrPrintWriter().println("Failure [" + status + "]"); + return 1; + } + } + + private int runCompile() throws RemoteException { + final PrintWriter pw = getOutPrintWriter(); + boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); + boolean forceCompilation = false; + boolean allPackages = false; + boolean clearProfileData = false; + String compilerFilter = null; + String compilationReason = null; + String checkProfilesRaw = null; + boolean secondaryDex = false; + String split = null; + + String opt; + while ((opt = getNextOption()) != null) { + switch (opt) { + case "-a": + allPackages = true; + break; + case "-c": + clearProfileData = true; + break; + case "-f": + forceCompilation = true; + break; + case "-m": + compilerFilter = getNextArgRequired(); + break; + case "-r": + compilationReason = getNextArgRequired(); + break; + case "--check-prof": + checkProfilesRaw = getNextArgRequired(); + break; + case "--reset": + forceCompilation = true; + clearProfileData = true; + compilationReason = "install"; + break; + case "--secondary-dex": + secondaryDex = true; + break; + case "--split": + split = getNextArgRequired(); + break; + default: + pw.println("Error: Unknown option: " + opt); + return 1; + } + } + + if (checkProfilesRaw != null) { + if ("true".equals(checkProfilesRaw)) { + checkProfiles = true; + } else if ("false".equals(checkProfilesRaw)) { + checkProfiles = false; + } else { + pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\"."); + return 1; + } + } + + if (compilerFilter != null && compilationReason != null) { + pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " + + "at the same time"); + return 1; + } + if (compilerFilter == null && compilationReason == null) { + pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " + + "reason (\"-r\") at the same time"); + return 1; + } + + if (allPackages && split != null) { + pw.println("-a cannot be specified together with --split"); + return 1; + } + + if (secondaryDex && split != null) { + pw.println("--secondary-dex cannot be specified together with --split"); + return 1; + } + + String targetCompilerFilter; + if (compilerFilter != null) { + if (!DexFile.isValidCompilerFilter(compilerFilter)) { + pw.println("Error: \"" + compilerFilter + + "\" is not a valid compilation filter."); + return 1; + } + targetCompilerFilter = compilerFilter; + } else { + int reason = -1; + for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { + if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals( + compilationReason)) { + reason = i; + break; + } + } + if (reason == -1) { + pw.println("Error: Unknown compilation reason: " + compilationReason); + return 1; + } + targetCompilerFilter = + PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason); + } + + + List<String> packageNames = null; + if (allPackages) { + packageNames = mInterface.getAllPackages(); + } else { + String packageName = getNextArg(); + if (packageName == null) { + pw.println("Error: package name not specified"); + return 1; + } + packageNames = Collections.singletonList(packageName); + } + + List<String> failedPackages = new ArrayList<>(); + for (String packageName : packageNames) { + if (clearProfileData) { + mInterface.clearApplicationProfileData(packageName); + } + + boolean result = secondaryDex + ? mInterface.performDexOptSecondary(packageName, + targetCompilerFilter, forceCompilation) + : mInterface.performDexOptMode(packageName, + checkProfiles, targetCompilerFilter, forceCompilation, + true /* bootComplete */, split); + if (!result) { + failedPackages.add(packageName); + } + } + + if (failedPackages.isEmpty()) { + pw.println("Success"); + return 0; + } else if (failedPackages.size() == 1) { + pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled"); + return 1; + } else { + pw.print("Failure: the following packages could not be compiled: "); + boolean is_first = true; + for (String packageName : failedPackages) { + if (is_first) { + is_first = false; + } else { + pw.print(", "); + } + pw.print(packageName); + } + pw.println(); + return 1; + } + } + + private int runreconcileSecondaryDexFiles() throws RemoteException { + String packageName = getNextArg(); + mInterface.reconcileSecondaryDexFiles(packageName); + return 0; + } + + public int runForceDexOpt() throws RemoteException { + mInterface.forceDexOpt(getNextArgRequired()); + return 0; + } + + private int runDexoptJob() throws RemoteException { + boolean result = mInterface.runBackgroundDexoptJob(); + return result ? 0 : -1; + } + + private int runDumpProfiles() throws RemoteException { + String packageName = getNextArg(); + mInterface.dumpProfiles(packageName); + return 0; + } + + private int runUninstall() throws RemoteException { + final PrintWriter pw = getOutPrintWriter(); + int flags = 0; + int userId = UserHandle.USER_ALL; + int versionCode = PackageManager.VERSION_CODE_HIGHEST; + + String opt; + while ((opt = getNextOption()) != null) { + switch (opt) { + case "-k": + flags |= PackageManager.DELETE_KEEP_DATA; + break; + case "--user": + userId = UserHandle.parseUserArg(getNextArgRequired()); + break; + case "--versionCode": + versionCode = Integer.parseInt(getNextArgRequired()); + break; + default: + pw.println("Error: Unknown option: " + opt); + return 1; + } + } + + final String packageName = getNextArg(); + if (packageName == null) { + pw.println("Error: package name not specified"); + return 1; + } + + // if a split is specified, just remove it and not the whole package + final String splitName = getNextArg(); + if (splitName != null) { + return runRemoveSplit(packageName, splitName); + } + + userId = translateUserId(userId, "runUninstall"); + if (userId == UserHandle.USER_ALL) { + userId = UserHandle.USER_SYSTEM; + flags |= PackageManager.DELETE_ALL_USERS; + } else { + final PackageInfo info = mInterface.getPackageInfo(packageName, + PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId); + if (info == null) { + pw.println("Failure [not installed for " + userId + "]"); + return 1; + } + final boolean isSystem = + (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + // If we are being asked to delete a system app for just one + // user set flag so it disables rather than reverting to system + // version of the app. + if (isSystem) { + flags |= PackageManager.DELETE_SYSTEM_APP; + } + } + + final LocalIntentReceiver receiver = new LocalIntentReceiver(); + mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName, + versionCode), null /*callerPackageName*/, flags, + receiver.getIntentSender(), userId); + + final Intent result = receiver.getResult(); + final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, + PackageInstaller.STATUS_FAILURE); + if (status == PackageInstaller.STATUS_SUCCESS) { + pw.println("Success"); + return 0; + } else { + pw.println("Failure [" + + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); + return 1; + } + } + + private int runRemoveSplit(String packageName, String splitName) throws RemoteException { + final PrintWriter pw = getOutPrintWriter(); + final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING); + sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; + sessionParams.appPackageName = packageName; + final int sessionId = + doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL); + boolean abandonSession = true; + try { + if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/) + != PackageInstaller.STATUS_SUCCESS) { + return 1; + } + if (doCommitSession(sessionId, false /*logSuccess*/) + != PackageInstaller.STATUS_SUCCESS) { + return 1; + } + abandonSession = false; + pw.println("Success"); + return 0; + } finally { + if (abandonSession) { + try { + doAbandonSession(sessionId, false /*logSuccess*/); + } catch (Exception ignore) { + } + } + } + } + + static class ClearDataObserver extends IPackageDataObserver.Stub { + boolean finished; + boolean result; + + @Override + public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { + synchronized (this) { + finished = true; + result = succeeded; + notifyAll(); + } + } + } + + private int runClear() throws RemoteException { + int userId = UserHandle.USER_SYSTEM; + String option = getNextOption(); + if (option != null && option.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } + + String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified"); + return 1; + } + + ClearDataObserver obs = new ClearDataObserver(); + ActivityManager.getService().clearApplicationUserData(pkg, obs, userId); + synchronized (obs) { + while (!obs.finished) { + try { + obs.wait(); + } catch (InterruptedException e) { + } + } + } + + if (obs.result) { + getOutPrintWriter().println("Success"); + return 0; + } else { + getErrPrintWriter().println("Failed"); + return 1; + } + } + + private static String enabledSettingToString(int state) { + switch (state) { + case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT: + return "default"; + case PackageManager.COMPONENT_ENABLED_STATE_ENABLED: + return "enabled"; + case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: + return "disabled"; + case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER: + return "disabled-user"; + case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED: + return "disabled-until-used"; + } + return "unknown"; + } + + private int runSetEnabledSetting(int state) throws RemoteException { + int userId = UserHandle.USER_SYSTEM; + String option = getNextOption(); + if (option != null && option.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } + + String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package or component specified"); + return 1; + } + ComponentName cn = ComponentName.unflattenFromString(pkg); + if (cn == null) { + mInterface.setApplicationEnabledSetting(pkg, state, 0, userId, + "shell:" + android.os.Process.myUid()); + getOutPrintWriter().println("Package " + pkg + " new state: " + + enabledSettingToString( + mInterface.getApplicationEnabledSetting(pkg, userId))); + return 0; + } else { + mInterface.setComponentEnabledSetting(cn, state, 0, userId); + getOutPrintWriter().println("Component " + cn.toShortString() + " new state: " + + enabledSettingToString( + mInterface.getComponentEnabledSetting(cn, userId))); + return 0; + } + } + + private int runSetHiddenSetting(boolean state) throws RemoteException { + int userId = UserHandle.USER_SYSTEM; + String option = getNextOption(); + if (option != null && option.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } + + String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package or component specified"); + return 1; + } + mInterface.setApplicationHiddenSettingAsUser(pkg, state, userId); + getOutPrintWriter().println("Package " + pkg + " new hidden state: " + + mInterface.getApplicationHiddenSettingAsUser(pkg, userId)); + return 0; + } + + private int runSuspend(boolean suspendedState) { + final PrintWriter pw = getOutPrintWriter(); + int userId = UserHandle.USER_SYSTEM; + String opt; + while ((opt = getNextOption()) != null) { + switch (opt) { + case "--user": + userId = UserHandle.parseUserArg(getNextArgRequired()); + break; + default: + pw.println("Error: Unknown option: " + opt); + return 1; + } + } + + String packageName = getNextArg(); + if (packageName == null) { + pw.println("Error: package name not specified"); + return 1; + } + + try { + mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState, + userId); + pw.println("Package " + packageName + " new suspended state: " + + mInterface.isPackageSuspendedForUser(packageName, userId)); + return 0; + } catch (RemoteException | IllegalArgumentException e) { + pw.println(e.toString()); + return 1; + } + } + + private int runGrantRevokePermission(boolean grant) throws RemoteException { + int userId = UserHandle.USER_SYSTEM; + + String opt = null; + while ((opt = getNextOption()) != null) { + if (opt.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } + } + + String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified"); + return 1; + } + String perm = getNextArg(); + if (perm == null) { + getErrPrintWriter().println("Error: no permission specified"); + return 1; + } + + if (grant) { + mInterface.grantRuntimePermission(pkg, perm, userId); + } else { + mInterface.revokeRuntimePermission(pkg, perm, userId); + } + return 0; + } + + private int runResetPermissions() throws RemoteException { + mInterface.resetRuntimePermissions(); + return 0; + } + + private int runSetPermissionEnforced() throws RemoteException { + final String permission = getNextArg(); + if (permission == null) { + getErrPrintWriter().println("Error: no permission specified"); + return 1; + } + final String enforcedRaw = getNextArg(); + if (enforcedRaw == null) { + getErrPrintWriter().println("Error: no enforcement specified"); + return 1; + } + mInterface.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw)); + return 0; + } + + private int runGetPrivappPermissions() { + final String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified."); + return 1; + } + ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg); + getOutPrintWriter().println(privAppPermissions == null + ? "{}" : privAppPermissions.toString()); + return 0; + } + + private int runGetPrivappDenyPermissions() { + final String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified."); + return 1; + } + ArraySet<String> privAppDenyPermissions = + SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); + getOutPrintWriter().println(privAppDenyPermissions == null + ? "{}" : privAppDenyPermissions.toString()); + return 0; + } + + private int runGetOemPermissions() { + final String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified."); + return 1; + } + final Map<String, Boolean> oemPermissions = SystemConfig.getInstance() + .getOemPermissions(pkg); + if (oemPermissions == null || oemPermissions.isEmpty()) { + getOutPrintWriter().println("{}"); + } else { + oemPermissions.forEach((permission, granted) -> + getOutPrintWriter().println(permission + " granted:" + granted) + ); + } + return 0; + } + + private String linkStateToString(int state) { + switch (state) { + case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined"; + case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask"; + case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always"; + case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never"; + case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask"; + } + return "Unknown link state: " + state; + } + + // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined} + private int runSetAppLink() throws RemoteException { + int userId = UserHandle.USER_SYSTEM; + + String opt; + while ((opt = getNextOption()) != null) { + if (opt.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } else { + getErrPrintWriter().println("Error: unknown option: " + opt); + return 1; + } + } + + // Package name to act on; required + final String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified."); + return 1; + } + + // State to apply; {always|ask|never|undefined}, required + final String modeString = getNextArg(); + if (modeString == null) { + getErrPrintWriter().println("Error: no app link state specified."); + return 1; + } + + final int newMode; + switch (modeString.toLowerCase()) { + case "undefined": + newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; + break; + + case "always": + newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; + break; + + case "ask": + newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; + break; + + case "always-ask": + newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; + break; + + case "never": + newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; + break; + + default: + getErrPrintWriter().println("Error: unknown app link state '" + modeString + "'"); + return 1; + } + + final PackageInfo info = mInterface.getPackageInfo(pkg, 0, userId); + if (info == null) { + getErrPrintWriter().println("Error: package " + pkg + " not found."); + return 1; + } + + if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) { + getErrPrintWriter().println("Error: package " + pkg + " does not handle web links."); + return 1; + } + + if (!mInterface.updateIntentVerificationStatus(pkg, newMode, userId)) { + getErrPrintWriter().println("Error: unable to update app link status for " + pkg); + return 1; + } + + return 0; + } + + // pm get-app-link [--user USER_ID] PACKAGE + private int runGetAppLink() throws RemoteException { + int userId = UserHandle.USER_SYSTEM; + + String opt; + while ((opt = getNextOption()) != null) { + if (opt.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } else { + getErrPrintWriter().println("Error: unknown option: " + opt); + return 1; + } + } + + // Package name to act on; required + final String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified."); + return 1; + } + + final PackageInfo info = mInterface.getPackageInfo(pkg, 0, userId); + if (info == null) { + getErrPrintWriter().println("Error: package " + pkg + " not found."); + return 1; + } + + if ((info.applicationInfo.privateFlags + & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) { + getErrPrintWriter().println("Error: package " + pkg + " does not handle web links."); + return 1; + } + + getOutPrintWriter().println(linkStateToString( + mInterface.getIntentVerificationStatus(pkg, userId))); + + return 0; + } + + private int runTrimCaches() throws RemoteException { + String size = getNextArg(); + if (size == null) { + getErrPrintWriter().println("Error: no size specified"); + return 1; + } + long multiplier = 1; + int len = size.length(); + char c = size.charAt(len - 1); + if (c < '0' || c > '9') { + if (c == 'K' || c == 'k') { + multiplier = 1024L; + } else if (c == 'M' || c == 'm') { + multiplier = 1024L*1024L; + } else if (c == 'G' || c == 'g') { + multiplier = 1024L*1024L*1024L; + } else { + getErrPrintWriter().println("Invalid suffix: " + c); + return 1; + } + size = size.substring(0, len-1); + } + long sizeVal; + try { + sizeVal = Long.parseLong(size) * multiplier; + } catch (NumberFormatException e) { + getErrPrintWriter().println("Error: expected number at: " + size); + return 1; + } + String volumeUuid = getNextArg(); + if ("internal".equals(volumeUuid)) { + volumeUuid = null; + } + ClearDataObserver obs = new ClearDataObserver(); + mInterface.freeStorageAndNotify(volumeUuid, sizeVal, + StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs); + synchronized (obs) { + while (!obs.finished) { + try { + obs.wait(); + } catch (InterruptedException e) { + } + } + } + return 0; + } + + private static boolean isNumber(String s) { + try { + Integer.parseInt(s); + } catch (NumberFormatException nfe) { + return false; + } + return true; + } + + public int runCreateUser() throws RemoteException { + String name; + int userId = -1; + int flags = 0; + String opt; + while ((opt = getNextOption()) != null) { + if ("--profileOf".equals(opt)) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } else if ("--managed".equals(opt)) { + flags |= UserInfo.FLAG_MANAGED_PROFILE; + } else if ("--restricted".equals(opt)) { + flags |= UserInfo.FLAG_RESTRICTED; + } else if ("--ephemeral".equals(opt)) { + flags |= UserInfo.FLAG_EPHEMERAL; + } else if ("--guest".equals(opt)) { + flags |= UserInfo.FLAG_GUEST; + } else if ("--demo".equals(opt)) { + flags |= UserInfo.FLAG_DEMO; + } else { + getErrPrintWriter().println("Error: unknown option " + opt); + return 1; + } + } + String arg = getNextArg(); + if (arg == null) { + getErrPrintWriter().println("Error: no user name specified."); + return 1; + } + name = arg; + UserInfo info; + IUserManager um = IUserManager.Stub.asInterface( + ServiceManager.getService(Context.USER_SERVICE)); + IAccountManager accm = IAccountManager.Stub.asInterface( + ServiceManager.getService(Context.ACCOUNT_SERVICE)); + if ((flags & UserInfo.FLAG_RESTRICTED) != 0) { + // In non-split user mode, userId can only be SYSTEM + int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM; + info = um.createRestrictedProfile(name, parentUserId); + accm.addSharedAccountsFromParentUser(parentUserId, userId, + (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell"); + } else if (userId < 0) { + info = um.createUser(name, flags); + } else { + info = um.createProfileForUser(name, flags, userId, null); + } + + if (info != null) { + getOutPrintWriter().println("Success: created user id " + info.id); + return 0; + } else { + getErrPrintWriter().println("Error: couldn't create User."); + return 1; + } + } + + public int runRemoveUser() throws RemoteException { + int userId; + String arg = getNextArg(); + if (arg == null) { + getErrPrintWriter().println("Error: no user id specified."); + return 1; + } + userId = UserHandle.parseUserArg(arg); + IUserManager um = IUserManager.Stub.asInterface( + ServiceManager.getService(Context.USER_SERVICE)); + if (um.removeUser(userId)) { + getOutPrintWriter().println("Success: removed user"); + return 0; + } else { + getErrPrintWriter().println("Error: couldn't remove user id " + userId); + return 1; + } + } + + public int runSetUserRestriction() throws RemoteException { + int userId = UserHandle.USER_SYSTEM; + String opt = getNextOption(); + if (opt != null && "--user".equals(opt)) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } + + String restriction = getNextArg(); + String arg = getNextArg(); + boolean value; + if ("1".equals(arg)) { + value = true; + } else if ("0".equals(arg)) { + value = false; + } else { + getErrPrintWriter().println("Error: valid value not specified"); + return 1; + } + IUserManager um = IUserManager.Stub.asInterface( + ServiceManager.getService(Context.USER_SERVICE)); + um.setUserRestriction(restriction, value, userId); + return 0; + } + + public int runGetMaxUsers() { + getOutPrintWriter().println("Maximum supported users: " + + UserManager.getMaxSupportedUsers()); + return 0; + } + private static class InstallParams { SessionParams sessionParams; String installerPackageName; @@ -1287,46 +1991,17 @@ class PackageManagerShellCommand extends ShellCommand { } } - private int runGetPrivappPermissions() { - final String pkg = getNextArg(); - if (pkg == null) { - System.err.println("Error: no package specified."); - return 1; - } - ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg); - getOutPrintWriter().println(privAppPermissions == null - ? "{}" : privAppPermissions.toString()); - return 0; - } + private int runSetInstaller() throws RemoteException { + final String targetPackage = getNextArg(); + final String installerPackageName = getNextArg(); - private int runGetPrivappDenyPermissions() { - final String pkg = getNextArg(); - if (pkg == null) { - System.err.println("Error: no package specified."); + if (targetPackage == null || installerPackageName == null) { + getErrPrintWriter().println("Must provide both target and installer package names"); return 1; } - ArraySet<String> privAppDenyPermissions = - SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); - getOutPrintWriter().println(privAppDenyPermissions == null - ? "{}" : privAppDenyPermissions.toString()); - return 0; - } - private int runGetOemPermissions() { - final String pkg = getNextArg(); - if (pkg == null) { - System.err.println("Error: no package specified."); - return 1; - } - final Map<String, Boolean> oemPermissions = SystemConfig.getInstance() - .getOemPermissions(pkg); - if (oemPermissions == null || oemPermissions.isEmpty()) { - getOutPrintWriter().println("{}"); - } else { - oemPermissions.forEach((permission, granted) -> - getOutPrintWriter().println(permission + " granted:" + granted) - ); - } + mInterface.setInstallerPackageName(targetPackage, installerPackageName); + getOutPrintWriter().println("Success"); return 0; } @@ -1367,6 +2042,16 @@ class PackageManagerShellCommand extends ShellCommand { } } + private int runDump() { + String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified"); + return 1; + } + ActivityManager.dumpPackageStateStatic(getOutFileDescriptor(), pkg); + return 0; + } + private static String checkAbiArgument(String abi) { if (TextUtils.isEmpty(abi)) { throw new IllegalArgumentException("Missing ABI argument"); @@ -1663,52 +2348,31 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" help"); pw.println(" Print this help text."); pw.println(""); - pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]"); - pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)"); - pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\"."); - pw.println(" Options:"); - pw.println(" -a: compile all packages"); - pw.println(" -c: clear profile data before compiling"); - pw.println(" -f: force compilation even if not needed"); - pw.println(" -m: select compilation mode"); - pw.println(" MODE is one of the dex2oat compiler filters:"); - pw.println(" assume-verified"); - pw.println(" extract"); - pw.println(" verify"); - pw.println(" quicken"); - pw.println(" space-profile"); - pw.println(" space"); - pw.println(" speed-profile"); - pw.println(" speed"); - pw.println(" everything"); - pw.println(" -r: select compilation reason"); - pw.println(" REASON is one of:"); - for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { - pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]); - } - pw.println(" --reset: restore package to its post-install state"); - pw.println(" --check-prof (true | false): look at profiles when doing dexopt?"); - pw.println(" --secondary-dex: compile app secondary dex files"); - pw.println(" --split SPLIT: compile only the given split name"); - pw.println(" bg-dexopt-job"); - pw.println(" Execute the background optimizations immediately."); - pw.println(" Note that the command only runs the background optimizer logic. It may"); - pw.println(" overlap with the actual job but the job scheduler will not be able to"); - pw.println(" cancel it. It will also run even if the device is not in the idle"); - pw.println(" maintenance mode."); + pw.println(" path [--user USER_ID] PACKAGE"); + pw.println(" Print the path to the .apk of the given PACKAGE."); + pw.println(""); + pw.println(" dump PACKAGE"); + pw.println(" Print various system state associated with the given PACKAGE."); + pw.println(""); pw.println(" list features"); pw.println(" Prints all features of the system."); + pw.println(""); + pw.println(" has-feature FEATURE_NAME [version]"); + pw.println(" Prints true and returns exit status 0 when system has a FEATURE_NAME,"); + pw.println(" otherwise prints false and returns exit status 1"); + pw.println(""); pw.println(" list instrumentation [-f] [TARGET-PACKAGE]"); pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE"); pw.println(" Options:"); pw.println(" -f: dump the name of the .apk file containing the test package"); + pw.println(""); pw.println(" list libraries"); pw.println(" Prints all system libraries."); - pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] " - + "[--uid UID] [--user USER_ID] [FILTER]"); + pw.println(""); + pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] "); + pw.println(" [--uid UID] [--user USER_ID] [FILTER]"); pw.println(" Prints all packages; optionally only those whose name contains"); - pw.println(" the text in FILTER."); - pw.println(" Options:"); + pw.println(" the text in FILTER. Options are:"); pw.println(" -f: see their associated file"); pw.println(" -d: filter to only show disabled packages"); pw.println(" -e: filter to only show enabled packages"); @@ -1720,42 +2384,216 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" -u: also include uninstalled packages"); pw.println(" --uid UID: filter to only show packages with the given UID"); pw.println(" --user USER_ID: only list packages belonging to the given user"); - pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE"); - pw.println(" Reconciles the package secondary dex files with the generated oat files."); + pw.println(""); pw.println(" list permission-groups"); pw.println(" Prints all known permission groups."); + pw.println(""); pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]"); - pw.println(" Prints all known permissions; optionally only those in GROUP."); - pw.println(" Options:"); + pw.println(" Prints all known permissions; optionally only those in GROUP. Options are:"); pw.println(" -g: organize by group"); pw.println(" -f: print all information"); pw.println(" -s: short summary"); pw.println(" -d: only list dangerous permissions"); pw.println(" -u: list only the permissions users will see"); - pw.println(" dump-profiles TARGET-PACKAGE"); - pw.println(" Dumps method/class profile files to"); - pw.println(" /data/misc/profman/TARGET-PACKAGE.txt"); + pw.println(""); pw.println(" resolve-activity [--brief] [--components] [--user USER_ID] INTENT"); - pw.println(" Prints the activity that resolves to the given Intent."); + pw.println(" Prints the activity that resolves to the given INTENT."); + pw.println(""); pw.println(" query-activities [--brief] [--components] [--user USER_ID] INTENT"); - pw.println(" Prints all activities that can handle the given Intent."); + pw.println(" Prints all activities that can handle the given INTENT."); + pw.println(""); pw.println(" query-services [--brief] [--components] [--user USER_ID] INTENT"); - pw.println(" Prints all services that can handle the given Intent."); + pw.println(" Prints all services that can handle the given INTENT."); + pw.println(""); pw.println(" query-receivers [--brief] [--components] [--user USER_ID] INTENT"); - pw.println(" Prints all broadcast receivers that can handle the given Intent."); + pw.println(" Prints all broadcast receivers that can handle the given INTENT."); + pw.println(""); + pw.println(" install [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]"); + pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]"); + pw.println(" [--originating-uri URI] [---referrer URI]"); + pw.println(" [--abi ABI_NAME] [--force-sdk]"); + pw.println(" [--preload] [--instantapp] [--full] [--dont-kill]"); + pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES] [PATH|-]"); + pw.println(" Install an application. Must provide the apk data to install, either as a"); + pw.println(" file path or '-' to read from stdin. Options are:"); + pw.println(" -l: forward lock application"); + pw.println(" -r: allow replacement of existing application"); + pw.println(" -t: allow test packages"); + pw.println(" -i: specify package name of installer owning the app"); + pw.println(" -s: install application on sdcard"); + pw.println(" -f: install application on internal flash"); + pw.println(" -d: allow version code downgrade (debuggable packages only)"); + pw.println(" -p: partial application install (new split on top of existing pkg)"); + pw.println(" -g: grant all runtime permissions"); + pw.println(" -S: size in bytes of package, required for stdin"); + pw.println(" --user: install under the given user."); + pw.println(" --dont-kill: installing a new feature split, don't kill running app"); + pw.println(" --originating-uri: set URI where app was downloaded from"); + pw.println(" --referrer: set URI that instigated the install of the app"); + pw.println(" --pkg: specify expected package name of app being installed"); + pw.println(" --abi: override the default ABI of the platform"); + pw.println(" --instantapp: cause the app to be installed as an ephemeral install app"); + pw.println(" --full: cause the app to be installed as a non-ephemeral full app"); + pw.println(" --install-location: force the install location:"); + pw.println(" 0=auto, 1=internal only, 2=prefer external"); + pw.println(" --force-uuid: force install on to disk volume with given UUID"); + pw.println(" --force-sdk: allow install even when existing app targets platform"); + pw.println(" codename but new one targets a final API level"); + pw.println(""); + pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]"); + pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]"); + pw.println(" [--originating-uri URI] [---referrer URI]"); + pw.println(" [--abi ABI_NAME] [--force-sdk]"); + pw.println(" [--preload] [--instantapp] [--full] [--dont-kill]"); + pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]"); + pw.println(" Like \"install\", but starts an install session. Use \"install-write\""); + pw.println(" to push data into the session, and \"install-commit\" to finish."); + pw.println(""); + pw.println(" install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]"); + pw.println(" Write an apk into the given install session. If the path is '-', data"); + pw.println(" will be read from stdin. Options are:"); + pw.println(" -S: size in bytes of package, required for stdin"); + pw.println(""); + pw.println(" install-commit SESSION_ID"); + pw.println(" Commit the given active install session, installing the app."); + pw.println(""); + pw.println(" install-abandon SESSION_ID"); + pw.println(" Delete the given active install session."); + pw.println(""); + pw.println(" set-install-location LOCATION"); + pw.println(" Changes the default install location. NOTE this is only intended for debugging;"); + pw.println(" using this can cause applications to break and other undersireable behavior."); + pw.println(" LOCATION is one of:"); + pw.println(" 0 [auto]: Let system decide the best location"); + pw.println(" 1 [internal]: Install on internal device storage"); + pw.println(" 2 [external]: Install on external media"); + pw.println(""); + pw.println(" get-install-location"); + pw.println(" Returns the current install location: 0, 1 or 2 as per set-install-location."); + pw.println(""); + pw.println(" move-package PACKAGE [internal|UUID]"); + pw.println(""); + pw.println(" move-primary-storage [internal|UUID]"); + pw.println(""); + pw.println(" pm uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE] PACKAGE [SPLIT]"); + pw.println(" Remove the given package name from the system. May remove an entire app"); + pw.println(" if no SPLIT name is specified, otherwise will remove only the split of the"); + pw.println(" given app. Options are:"); + pw.println(" -k: keep the data and cache directories around after package removal."); + pw.println(" --user: remove the app from the given user."); + pw.println(" --versionCode: only uninstall if the app has the given version code."); + pw.println(""); + pw.println(" clear [--user USER_ID] PACKAGE"); + pw.println(" Deletes all data associated with a package."); + pw.println(""); + pw.println(" enable [--user USER_ID] PACKAGE_OR_COMPONENT"); + pw.println(" disable [--user USER_ID] PACKAGE_OR_COMPONENT"); + pw.println(" disable-user [--user USER_ID] PACKAGE_OR_COMPONENT"); + pw.println(" disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT"); + pw.println(" default-state [--user USER_ID] PACKAGE_OR_COMPONENT"); + pw.println(" These commands change the enabled state of a given package or"); + pw.println(" component (written as \"package/class\")."); + pw.println(""); + pw.println(" hide [--user USER_ID] PACKAGE_OR_COMPONENT"); + pw.println(" unhide [--user USER_ID] PACKAGE_OR_COMPONENT"); + pw.println(""); pw.println(" suspend [--user USER_ID] TARGET-PACKAGE"); pw.println(" Suspends the specified package (as user)."); + pw.println(""); pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE"); pw.println(" Unsuspends the specified package (as user)."); - pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT"); - pw.println(" set the default home activity (aka launcher)."); - pw.println(" has-feature FEATURE_NAME [version]"); - pw.println(" prints true and returns exit status 0 when system has a FEATURE_NAME,"); - pw.println(" otherwise prints false and returns exit status 1"); - pw.println(" get-privileged-permissions TARGET-PACKAGE"); - pw.println(" prints all privileged permissions for a package."); + pw.println(""); + pw.println(" grant [--user USER_ID] PACKAGE PERMISSION"); + pw.println(" revoke [--user USER_ID] PACKAGE PERMISSION"); + pw.println(" These commands either grant or revoke permissions to apps. The permissions"); + pw.println(" must be declared as used in the app's manifest, be runtime permissions"); + pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1."); + pw.println(""); + pw.println(" reset-permissions"); + pw.println(" Revert all runtime permissions to their default state."); + pw.println(""); + pw.println(" set-permission-enforced PERMISSION [true|false]"); + pw.println(""); + pw.println(" get-privapp-permissions TARGET-PACKAGE"); + pw.println(" Prints all privileged permissions for a package."); + pw.println(""); + pw.println(" get-privapp-deny-permissions TARGET-PACKAGE"); + pw.println(" Prints all privileged permissions that are denied for a package."); + pw.println(""); pw.println(" get-oem-permissions TARGET-PACKAGE"); - pw.println(" prints all OEM permissions for a package."); + pw.println(" Prints all OEM permissions for a package."); + pw.println(""); + pw.println(" set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}"); + pw.println(" get-app-link [--user USER_ID] PACKAGE"); + pw.println(""); + pw.println(" trim-caches DESIRED_FREE_SPACE [internal|UUID]"); + pw.println(" Trim cache files to reach the given free space."); + pw.println(""); + pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]"); + pw.println(" [--guest] USER_NAME"); + pw.println(" Create a new user with the given USER_NAME, printing the new user identifier"); + pw.println(" of the user."); + pw.println(""); + pw.println(" remove-user USER_ID"); + pw.println(" Remove the user with the given USER_IDENTIFIER, deleting all data"); + pw.println(" associated with that user"); + pw.println(""); + pw.println(" set-user-restriction [--user USER_ID] RESTRICTION VALUE"); + pw.println(""); + pw.println(" get-max-users"); + pw.println(""); + pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]"); + pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)"); + pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\". Options are:"); + pw.println(" -a: compile all packages"); + pw.println(" -c: clear profile data before compiling"); + pw.println(" -f: force compilation even if not needed"); + pw.println(" -m: select compilation mode"); + pw.println(" MODE is one of the dex2oat compiler filters:"); + pw.println(" assume-verified"); + pw.println(" extract"); + pw.println(" verify"); + pw.println(" quicken"); + pw.println(" space-profile"); + pw.println(" space"); + pw.println(" speed-profile"); + pw.println(" speed"); + pw.println(" everything"); + pw.println(" -r: select compilation reason"); + pw.println(" REASON is one of:"); + for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { + pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]); + } + pw.println(" --reset: restore package to its post-install state"); + pw.println(" --check-prof (true | false): look at profiles when doing dexopt?"); + pw.println(" --secondary-dex: compile app secondary dex files"); + pw.println(" --split SPLIT: compile only the given split name"); + pw.println(""); + pw.println(" force-dex-opt PACKAGE"); + pw.println(" Force immediate execution of dex opt for the given PACKAGE."); + pw.println(""); + pw.println(" bg-dexopt-job"); + pw.println(" Execute the background optimizations immediately."); + pw.println(" Note that the command only runs the background optimizer logic. It may"); + pw.println(" overlap with the actual job but the job scheduler will not be able to"); + pw.println(" cancel it. It will also run even if the device is not in the idle"); + pw.println(" maintenance mode."); + pw.println(""); + pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE"); + pw.println(" Reconciles the package secondary dex files with the generated oat files."); + pw.println(""); + pw.println(" dump-profiles TARGET-PACKAGE"); + pw.println(" Dumps method/class profile files to"); + pw.println(" /data/misc/profman/TARGET-PACKAGE.txt"); + pw.println(""); + pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT"); + pw.println(" Set the default home activity (aka launcher)."); + pw.println(""); + pw.println(" set-installer PACKAGE INSTALLER"); + pw.println(" Set installer package name"); + pw.println(""); + pw.println(" get-instantapp-resolver"); + pw.println(" Return the name of the component that is the current instant app installer."); pw.println(); Intent.printIntentArgsHelp(pw , ""); } diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java index 6dd9aa4094f5..e5d3915dde4c 100644 --- a/services/usage/java/com/android/server/usage/AppIdleHistory.java +++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java @@ -478,7 +478,7 @@ public class AppIdleHistory { } } - public void dump(IndentingPrintWriter idpw, int userId) { + public void dump(IndentingPrintWriter idpw, int userId, String pkg) { idpw.println("Package idle stats:"); idpw.increaseIndent(); ArrayMap<String, AppUsageHistory> userHistory = mIdleHistory.get(userId); @@ -490,6 +490,9 @@ public class AppIdleHistory { for (int p = 0; p < P; p++) { final String packageName = userHistory.keyAt(p); final AppUsageHistory appUsageHistory = userHistory.valueAt(p); + if (pkg != null && !pkg.equals(packageName)) { + continue; + } idpw.print("package=" + packageName); idpw.print(" lastUsedElapsed="); TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastUsedElapsedTime, idpw); diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java index dad595071df5..17fde57907d7 100644 --- a/services/usage/java/com/android/server/usage/AppStandbyController.java +++ b/services/usage/java/com/android/server/usage/AppStandbyController.java @@ -873,9 +873,9 @@ public class AppStandbyController { } } - void dumpUser(IndentingPrintWriter idpw, int userId) { + void dumpUser(IndentingPrintWriter idpw, int userId, String pkg) { synchronized (mAppIdleLock) { - mAppIdleHistory.dump(idpw, userId); + mAppIdleHistory.dump(idpw, userId, pkg); } } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 3a958da2db16..44e6a6cb7459 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -470,8 +470,32 @@ public class UsageStatsService extends SystemService implements void dump(String[] args, PrintWriter pw) { synchronized (mLock) { IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " "); - ArraySet<String> argSet = new ArraySet<>(); - argSet.addAll(Arrays.asList(args)); + + boolean checkin = false; + boolean history = false; + String pkg = null; + + if (args != null) { + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if ("--checkin".equals(arg)) { + checkin = true; + } else if ("--history".equals(arg)) { + history = true; + } else if ("history".equals(arg)) { + history = true; + break; + } else if ("flush".equals(arg)) { + flushToDiskLocked(); + pw.println("Flushed stats to disk"); + return; + } else { + // Anything else is a pkg to filter + pkg = arg; + break; + } + } + } final int userCount = mUserState.size(); for (int i = 0; i < userCount; i++) { @@ -479,26 +503,23 @@ public class UsageStatsService extends SystemService implements idpw.printPair("user", userId); idpw.println(); idpw.increaseIndent(); - if (argSet.contains("--checkin")) { + if (checkin) { mUserState.valueAt(i).checkin(idpw); } else { - mUserState.valueAt(i).dump(idpw); + mUserState.valueAt(i).dump(idpw, pkg); idpw.println(); - if (args.length > 0) { - if ("history".equals(args[0])) { - mAppStandby.dumpHistory(idpw, userId); - } else if ("flush".equals(args[0])) { - flushToDiskLocked(); - pw.println("Flushed stats to disk"); - } + if (history) { + mAppStandby.dumpHistory(idpw, userId); } } - mAppStandby.dumpUser(idpw, userId); + mAppStandby.dumpUser(idpw, userId, pkg); idpw.decreaseIndent(); } - pw.println(); - mAppStandby.dumpState(args, pw); + if (pkg == null) { + pw.println(); + mAppStandby.dumpState(args, pw); + } } } diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 0abbb82a68a1..0b1059045b5b 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -474,19 +474,19 @@ class UserUsageStatsService { mDatabase.checkinDailyFiles(new UsageStatsDatabase.CheckinAction() { @Override public boolean checkin(IntervalStats stats) { - printIntervalStats(pw, stats, false); + printIntervalStats(pw, stats, false, null); return true; } }); } - void dump(IndentingPrintWriter pw) { + void dump(IndentingPrintWriter pw, String pkg) { // This is not a check-in, only dump in-memory stats. for (int interval = 0; interval < mCurrentStats.length; interval++) { pw.print("In-memory "); pw.print(intervalToString(interval)); pw.println(" stats"); - printIntervalStats(pw, mCurrentStats[interval], true); + printIntervalStats(pw, mCurrentStats[interval], true, pkg); } } @@ -505,7 +505,7 @@ class UserUsageStatsService { } void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats, - boolean prettyDates) { + boolean prettyDates, String pkg) { if (prettyDates) { pw.printPair("timeRange", "\"" + DateUtils.formatDateRange(mContext, stats.beginTime, stats.endTime, sDateFormatFlags) + "\""); @@ -521,6 +521,9 @@ class UserUsageStatsService { final int pkgCount = pkgStats.size(); for (int i = 0; i < pkgCount; i++) { final UsageStats usageStats = pkgStats.valueAt(i); + if (pkg != null && !pkg.equals(usageStats.mPackageName)) { + continue; + } pw.printPair("package", usageStats.mPackageName); pw.printPair("totalTime", formatElapsedTime(usageStats.mTotalTimeInForeground, prettyDates)); @@ -533,6 +536,9 @@ class UserUsageStatsService { pw.println("ChooserCounts"); pw.increaseIndent(); for (UsageStats usageStats : pkgStats.values()) { + if (pkg != null && !pkg.equals(usageStats.mPackageName)) { + continue; + } pw.printPair("package", usageStats.mPackageName); if (usageStats.mChooserCounts != null) { final int chooserCountSize = usageStats.mChooserCounts.size(); @@ -555,19 +561,22 @@ class UserUsageStatsService { } pw.decreaseIndent(); - pw.println("configurations"); - pw.increaseIndent(); - final ArrayMap<Configuration, ConfigurationStats> configStats = stats.configurations; - final int configCount = configStats.size(); - for (int i = 0; i < configCount; i++) { - final ConfigurationStats config = configStats.valueAt(i); - pw.printPair("config", Configuration.resourceQualifierString(config.mConfiguration)); - pw.printPair("totalTime", formatElapsedTime(config.mTotalTimeActive, prettyDates)); - pw.printPair("lastTime", formatDateTime(config.mLastTimeActive, prettyDates)); - pw.printPair("count", config.mActivationCount); - pw.println(); + if (pkg == null) { + pw.println("configurations"); + pw.increaseIndent(); + final ArrayMap<Configuration, ConfigurationStats> configStats = stats.configurations; + final int configCount = configStats.size(); + for (int i = 0; i < configCount; i++) { + final ConfigurationStats config = configStats.valueAt(i); + pw.printPair("config", Configuration.resourceQualifierString( + config.mConfiguration)); + pw.printPair("totalTime", formatElapsedTime(config.mTotalTimeActive, prettyDates)); + pw.printPair("lastTime", formatDateTime(config.mLastTimeActive, prettyDates)); + pw.printPair("count", config.mActivationCount); + pw.println(); + } + pw.decreaseIndent(); } - pw.decreaseIndent(); pw.println("events"); pw.increaseIndent(); @@ -575,6 +584,9 @@ class UserUsageStatsService { final int eventCount = events != null ? events.size() : 0; for (int i = 0; i < eventCount; i++) { final UsageEvents.Event event = events.valueAt(i); + if (pkg != null && !pkg.equals(event.mPackage)) { + continue; + } pw.printPair("time", formatDateTime(event.mTimeStamp, prettyDates)); pw.printPair("type", eventToString(event.mEventType)); pw.printPair("package", event.mPackage); |