2 * Copyright (C) 2007 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.commands.pm;
19 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
20 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
21 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
22 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
23 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
25 import android.accounts.IAccountManager;
26 import android.app.ActivityManager;
27 import android.app.PackageInstallObserver;
28 import android.content.ComponentName;
29 import android.content.Context;
30 import android.content.IIntentReceiver;
31 import android.content.IIntentSender;
32 import android.content.Intent;
33 import android.content.IntentSender;
34 import android.content.pm.ApplicationInfo;
35 import android.content.pm.IPackageDataObserver;
36 import android.content.pm.IPackageInstaller;
37 import android.content.pm.IPackageManager;
38 import android.content.pm.PackageInfo;
39 import android.content.pm.PackageInstaller;
40 import android.content.pm.PackageInstaller.SessionInfo;
41 import android.content.pm.PackageInstaller.SessionParams;
42 import android.content.pm.PackageManager;
43 import android.content.pm.PackageParser;
44 import android.content.pm.PackageParser.ApkLite;
45 import android.content.pm.PackageParser.PackageLite;
46 import android.content.pm.PackageParser.PackageParserException;
47 import android.content.pm.UserInfo;
48 import android.net.Uri;
49 import android.os.Binder;
50 import android.os.Build;
51 import android.os.Bundle;
52 import android.os.Handler;
53 import android.os.HandlerThread;
54 import android.os.IBinder;
55 import android.os.IUserManager;
56 import android.os.ParcelFileDescriptor;
57 import android.os.Process;
58 import android.os.RemoteException;
59 import android.os.ResultReceiver;
60 import android.os.SELinux;
61 import android.os.ServiceManager;
62 import android.os.ShellCallback;
63 import android.os.SystemClock;
64 import android.os.UserHandle;
65 import android.os.UserManager;
66 import android.os.storage.StorageManager;
67 import android.text.TextUtils;
68 import android.text.format.DateUtils;
69 import android.util.Log;
70 import android.util.Pair;
72 import com.android.internal.content.PackageHelper;
73 import com.android.internal.util.ArrayUtils;
74 import com.android.internal.util.SizedInputStream;
76 import libcore.io.IoUtils;
79 import java.io.FileDescriptor;
80 import java.io.FileInputStream;
81 import java.io.FileNotFoundException;
82 import java.io.IOException;
83 import java.io.InputStream;
84 import java.io.OutputStream;
85 import java.util.concurrent.SynchronousQueue;
86 import java.util.concurrent.TimeUnit;
88 public final class Pm {
89 private static final String TAG = "Pm";
90 private static final String STDIN_PATH = "-";
93 IPackageInstaller mInstaller;
97 private String[] mArgs;
99 private String mCurArgData;
101 private static final String PM_NOT_RUNNING_ERR =
102 "Error: Could not access the Package Manager. Is the system running?";
104 public static void main(String[] args) {
107 exitCode = new Pm().run(args);
108 } catch (Exception e) {
109 Log.e(TAG, "Error", e);
110 System.err.println("Error: " + e);
111 if (e instanceof RemoteException) {
112 System.err.println(PM_NOT_RUNNING_ERR);
115 System.exit(exitCode);
118 public int run(String[] args) throws RemoteException {
119 boolean validCommand = false;
120 if (args.length < 1) {
123 mAm = IAccountManager.Stub.asInterface(ServiceManager.getService(Context.ACCOUNT_SERVICE));
124 mUm = IUserManager.Stub.asInterface(ServiceManager.getService(Context.USER_SERVICE));
125 mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
128 System.err.println(PM_NOT_RUNNING_ERR);
131 mInstaller = mPm.getPackageInstaller();
137 if ("list".equals(op)) {
141 if ("path".equals(op)) {
145 if ("dump".equals(op)) {
149 if ("install".equals(op)) {
153 if ("install-create".equals(op)) {
154 return runInstallCreate();
157 if ("install-write".equals(op)) {
158 return runInstallWrite();
161 if ("install-commit".equals(op)) {
162 return runInstallCommit();
165 if ("install-abandon".equals(op) || "install-destroy".equals(op)) {
166 return runInstallAbandon();
169 if ("set-installer".equals(op)) {
170 return runSetInstaller();
173 if ("uninstall".equals(op)) {
174 return runUninstall();
177 if ("clear".equals(op)) {
181 if ("enable".equals(op)) {
182 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
185 if ("disable".equals(op)) {
186 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
189 if ("disable-user".equals(op)) {
190 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
193 if ("disable-until-used".equals(op)) {
194 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
197 if ("default-state".equals(op)) {
198 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
201 if ("hide".equals(op)) {
202 return runSetHiddenSetting(true);
205 if ("unhide".equals(op)) {
206 return runSetHiddenSetting(false);
209 if ("grant".equals(op)) {
210 return runGrantRevokePermission(true);
213 if ("revoke".equals(op)) {
214 return runGrantRevokePermission(false);
217 if ("reset-permissions".equals(op)) {
218 return runResetPermissions();
221 if ("set-permission-enforced".equals(op)) {
222 return runSetPermissionEnforced();
225 if ("set-app-link".equals(op)) {
226 return runSetAppLink();
229 if ("get-app-link".equals(op)) {
230 return runGetAppLink();
233 if ("set-install-location".equals(op)) {
234 return runSetInstallLocation();
237 if ("get-install-location".equals(op)) {
238 return runGetInstallLocation();
241 if ("trim-caches".equals(op)) {
242 return runTrimCaches();
245 if ("create-user".equals(op)) {
246 return runCreateUser();
249 if ("remove-user".equals(op)) {
250 return runRemoveUser();
253 if ("get-max-users".equals(op)) {
254 return runGetMaxUsers();
257 if ("force-dex-opt".equals(op)) {
258 return runForceDexOpt();
261 if ("move-package".equals(op)) {
262 return runMovePackage();
265 if ("move-primary-storage".equals(op)) {
266 return runMovePrimaryStorage();
269 if ("set-user-restriction".equals(op)) {
270 return runSetUserRestriction();
274 if (args.length == 1) {
275 if (args[0].equalsIgnoreCase("-l")) {
277 return runShellCommand("package", new String[] { "list", "package" });
278 } else if (args[0].equalsIgnoreCase("-lf")) {
280 return runShellCommand("package", new String[] { "list", "package", "-f" });
282 } else if (args.length == 2) {
283 if (args[0].equalsIgnoreCase("-p")) {
285 return displayPackageFilePath(args[1], UserHandle.USER_SYSTEM);
290 if (validCommand == false) {
292 System.err.println("Error: unknown command '" + op + "'");
299 static final class MyShellCallback extends ShellCallback {
300 @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) {
301 File file = new File(path);
302 final ParcelFileDescriptor fd;
304 fd = ParcelFileDescriptor.open(file,
305 ParcelFileDescriptor.MODE_CREATE |
306 ParcelFileDescriptor.MODE_TRUNCATE |
307 ParcelFileDescriptor.MODE_WRITE_ONLY);
308 } catch (FileNotFoundException e) {
309 String msg = "Unable to open file " + path + ": " + e;
310 System.err.println(msg);
311 throw new IllegalArgumentException(msg);
313 if (seLinuxContext != null) {
314 final String tcon = SELinux.getFileContext(file.getAbsolutePath());
315 if (!SELinux.checkSELinuxAccess(seLinuxContext, tcon, "file", "write")) {
318 } catch (IOException e) {
320 String msg = "System server has no access to file context " + tcon;
321 System.err.println(msg + " (from path " + file.getAbsolutePath()
322 + ", context " + seLinuxContext + ")");
323 throw new IllegalArgumentException(msg);
330 private int runShellCommand(String serviceName, String[] args) {
331 final HandlerThread handlerThread = new HandlerThread("results");
332 handlerThread.start();
334 ServiceManager.getService(serviceName).shellCommand(
335 FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
336 args, new MyShellCallback(),
337 new ResultReceiver(new Handler(handlerThread.getLooper())));
339 } catch (RemoteException e) {
342 handlerThread.quitSafely();
347 private static class LocalIntentReceiver {
348 private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
350 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
352 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
353 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
355 mResult.offer(intent, 5, TimeUnit.SECONDS);
356 } catch (InterruptedException e) {
357 throw new RuntimeException(e);
362 public IntentSender getIntentSender() {
363 return new IntentSender((IIntentSender) mLocalSender);
366 public Intent getResult() {
368 return mResult.take();
369 } catch (InterruptedException e) {
370 throw new RuntimeException(e);
375 private int translateUserId(int userId, String logContext) {
376 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
377 userId, true, true, logContext, "pm command");
380 private static String checkAbiArgument(String abi) {
381 if (TextUtils.isEmpty(abi)) {
382 throw new IllegalArgumentException("Missing ABI argument");
384 if ("-".equals(abi)) {
387 final String[] supportedAbis = Build.SUPPORTED_ABIS;
388 for (String supportedAbi : supportedAbis) {
389 if (supportedAbi.equals(abi)) {
393 throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
397 * Keep this around to support existing users of the "pm install" command that may not be
398 * able to be updated [or, at least informed the API has changed] such as ddmlib.
400 * Moving the implementation of "pm install" to "cmd package install" changes the executing
401 * context. Instead of being a stand alone process, "cmd package install" runs in the
402 * system_server process. Due to SELinux rules, system_server cannot access many directories;
403 * one of which being the package install staging directory [/data/local/tmp].
405 * The use of "adb install" or "cmd package install" over "pm install" is highly encouraged.
407 private int runInstall() throws RemoteException {
408 long startedTime = SystemClock.elapsedRealtime();
409 final InstallParams params = makeInstallParams();
410 final String inPath = nextArg();
411 if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
412 File file = new File(inPath);
415 ApkLite baseApk = PackageParser.parseApkLite(file, 0);
416 PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
418 params.sessionParams.setSize(
419 PackageHelper.calculateInstalledSize(pkgLite, false,
420 params.sessionParams.abiOverride));
421 } catch (PackageParserException | IOException e) {
422 System.err.println("Error: Failed to parse APK file: " + e);
426 System.err.println("Error: Can't open non-file: " + inPath);
431 final int sessionId = doCreateSession(params.sessionParams,
432 params.installerPackageName, params.userId);
435 if (inPath == null && params.sessionParams.sizeBytes == -1) {
436 System.err.println("Error: must either specify a package size or an APK file");
439 if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
440 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
443 Pair<String, Integer> status = doCommitSession(sessionId, false /*logSuccess*/);
444 if (status.second != PackageInstaller.STATUS_SUCCESS) {
447 Log.i(TAG, "Package " + status.first + " installed in " + (SystemClock.elapsedRealtime()
448 - startedTime) + " ms");
449 System.out.println("Success");
453 mInstaller.abandonSession(sessionId);
454 } catch (Exception ignore) {
459 private int runInstallAbandon() throws RemoteException {
460 final int sessionId = Integer.parseInt(nextArg());
461 return doAbandonSession(sessionId, true /*logSuccess*/);
464 private int runInstallCommit() throws RemoteException {
465 final int sessionId = Integer.parseInt(nextArg());
466 return doCommitSession(sessionId, true /*logSuccess*/).second;
469 private int runInstallCreate() throws RemoteException {
470 final InstallParams installParams = makeInstallParams();
471 final int sessionId = doCreateSession(installParams.sessionParams,
472 installParams.installerPackageName, installParams.userId);
474 // NOTE: adb depends on parsing this string
475 System.out.println("Success: created install session [" + sessionId + "]");
476 return PackageInstaller.STATUS_SUCCESS;
479 private int runInstallWrite() throws RemoteException {
483 while ((opt = nextOption()) != null) {
484 if (opt.equals("-S")) {
485 sizeBytes = Long.parseLong(nextArg());
487 throw new IllegalArgumentException("Unknown option: " + opt);
491 final int sessionId = Integer.parseInt(nextArg());
492 final String splitName = nextArg();
493 final String path = nextArg();
494 return doWriteSession(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
497 private static class InstallParams {
498 SessionParams sessionParams;
499 String installerPackageName;
500 int userId = UserHandle.USER_ALL;
503 private InstallParams makeInstallParams() {
504 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
505 final InstallParams params = new InstallParams();
506 params.sessionParams = sessionParams;
508 while ((opt = nextOption()) != null) {
511 sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
514 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
517 params.installerPackageName = nextArg();
518 if (params.installerPackageName == null) {
519 throw new IllegalArgumentException("Missing installer package");
523 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
526 sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL;
529 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
532 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
535 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
538 sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
540 case "--originating-uri":
541 sessionParams.originatingUri = Uri.parse(nextOptionData());
544 sessionParams.referrerUri = Uri.parse(nextOptionData());
547 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
548 sessionParams.appPackageName = nextOptionData();
549 if (sessionParams.appPackageName == null) {
550 throw new IllegalArgumentException("Missing inherit package name");
554 sessionParams.appPackageName = nextOptionData();
555 if (sessionParams.appPackageName == null) {
556 throw new IllegalArgumentException("Missing package name");
560 final long sizeBytes = Long.parseLong(nextOptionData());
561 if (sizeBytes <= 0) {
562 throw new IllegalArgumentException("Size must be positive");
564 sessionParams.setSize(sizeBytes);
567 sessionParams.abiOverride = checkAbiArgument(nextOptionData());
571 sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
574 sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
577 params.userId = UserHandle.parseUserArg(nextOptionData());
579 case "--install-location":
580 sessionParams.installLocation = Integer.parseInt(nextOptionData());
583 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
584 sessionParams.volumeUuid = nextOptionData();
585 if ("internal".equals(sessionParams.volumeUuid)) {
586 sessionParams.volumeUuid = null;
590 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK;
593 throw new IllegalArgumentException("Unknown option " + opt);
599 private int doCreateSession(SessionParams params, String installerPackageName, int userId)
600 throws RemoteException {
601 userId = translateUserId(userId, "runInstallCreate");
602 if (userId == UserHandle.USER_ALL) {
603 userId = UserHandle.USER_SYSTEM;
604 params.installFlags |= PackageManager.INSTALL_ALL_USERS;
607 final int sessionId = mInstaller.createSession(params, installerPackageName, userId);
611 private int doWriteSession(int sessionId, String inPath, long sizeBytes, String splitName,
612 boolean logSuccess) throws RemoteException {
613 if (STDIN_PATH.equals(inPath)) {
615 } else if (inPath != null) {
616 final File file = new File(inPath);
618 sizeBytes = file.length();
622 final SessionInfo info = mInstaller.getSessionInfo(sessionId);
624 PackageInstaller.Session session = null;
625 InputStream in = null;
626 OutputStream out = null;
628 session = new PackageInstaller.Session(
629 mInstaller.openSession(sessionId));
631 if (inPath != null) {
632 in = new FileInputStream(inPath);
634 in = new SizedInputStream(System.in, sizeBytes);
636 out = session.openWrite(splitName, 0, sizeBytes);
639 byte[] buffer = new byte[65536];
641 while ((c = in.read(buffer)) != -1) {
643 out.write(buffer, 0, c);
645 if (info.sizeBytes > 0) {
646 final float fraction = ((float) c / (float) info.sizeBytes);
647 session.addProgress(fraction);
653 System.out.println("Success: streamed " + total + " bytes");
655 return PackageInstaller.STATUS_SUCCESS;
656 } catch (IOException e) {
657 System.err.println("Error: failed to write; " + e.getMessage());
658 return PackageInstaller.STATUS_FAILURE;
660 IoUtils.closeQuietly(out);
661 IoUtils.closeQuietly(in);
662 IoUtils.closeQuietly(session);
666 private Pair<String, Integer> doCommitSession(int sessionId, boolean logSuccess)
667 throws RemoteException {
668 PackageInstaller.Session session = null;
670 session = new PackageInstaller.Session(
671 mInstaller.openSession(sessionId));
673 final LocalIntentReceiver receiver = new LocalIntentReceiver();
674 session.commit(receiver.getIntentSender());
676 final Intent result = receiver.getResult();
677 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
678 PackageInstaller.STATUS_FAILURE);
679 if (status == PackageInstaller.STATUS_SUCCESS) {
681 System.out.println("Success");
684 System.err.println("Failure ["
685 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
687 return new Pair<>(result.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME), status);
689 IoUtils.closeQuietly(session);
693 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
694 PackageInstaller.Session session = null;
696 session = new PackageInstaller.Session(mInstaller.openSession(sessionId));
699 System.out.println("Success");
701 return PackageInstaller.STATUS_SUCCESS;
703 IoUtils.closeQuietly(session);
708 * Execute the list sub-command.
710 * pm list [package | packages]
711 * pm list permission-groups
712 * pm list permissions
715 * pm list instrumentation
717 private int runList() {
718 final String type = nextArg();
719 if ("users".equals(type)) {
720 return runShellCommand("user", new String[] { "list" });
722 return runShellCommand("package", mArgs);
725 private int runUninstall() {
726 return runShellCommand("package", mArgs);
729 private int runPath() {
730 int userId = UserHandle.USER_SYSTEM;
731 String option = nextOption();
732 if (option != null && option.equals("--user")) {
733 String optionData = nextOptionData();
734 if (optionData == null || !isNumber(optionData)) {
735 System.err.println("Error: no USER_ID specified");
738 userId = Integer.parseInt(optionData);
742 String pkg = nextArg();
744 System.err.println("Error: no package specified");
747 return displayPackageFilePath(pkg, userId);
750 private int runDump() {
751 String pkg = nextArg();
753 System.err.println("Error: no package specified");
756 ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg);
760 class LocalPackageInstallObserver extends PackageInstallObserver {
763 String extraPermission;
767 public void onPackageInstalled(String name, int status, String msg, Bundle extras) {
768 synchronized (this) {
771 if (status == PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION) {
772 extraPermission = extras.getString(
773 PackageManager.EXTRA_FAILURE_EXISTING_PERMISSION);
774 extraPackage = extras.getString(
775 PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
782 // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
783 private int runSetAppLink() {
784 int userId = UserHandle.USER_SYSTEM;
787 while ((opt = nextOption()) != null) {
788 if (opt.equals("--user")) {
789 userId = Integer.parseInt(nextOptionData());
791 System.err.println("Error: user must be >= 0");
795 System.err.println("Error: unknown option: " + opt);
800 // Package name to act on; required
801 final String pkg = nextArg();
803 System.err.println("Error: no package specified.");
807 // State to apply; {always|ask|never|undefined}, required
808 final String modeString = nextArg();
809 if (modeString == null) {
810 System.err.println("Error: no app link state specified.");
815 switch (modeString.toLowerCase()) {
817 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
821 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
825 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
829 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
833 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
837 System.err.println("Error: unknown app link state '" + modeString + "'");
842 final PackageInfo info = mPm.getPackageInfo(pkg, 0, userId);
844 System.err.println("Error: package " + pkg + " not found.");
848 if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
849 System.err.println("Error: package " + pkg + " does not handle web links.");
853 if (!mPm.updateIntentVerificationStatus(pkg, newMode, userId)) {
854 System.err.println("Error: unable to update app link status for " + pkg);
857 } catch (Exception e) {
858 System.err.println(e.toString());
859 System.err.println(PM_NOT_RUNNING_ERR);
866 // pm get-app-link [--user USER_ID] PACKAGE
867 private int runGetAppLink() {
868 int userId = UserHandle.USER_SYSTEM;
871 while ((opt = nextOption()) != null) {
872 if (opt.equals("--user")) {
873 userId = Integer.parseInt(nextOptionData());
875 System.err.println("Error: user must be >= 0");
879 System.err.println("Error: unknown option: " + opt);
884 // Package name to act on; required
885 final String pkg = nextArg();
887 System.err.println("Error: no package specified.");
892 final PackageInfo info = mPm.getPackageInfo(pkg, 0, userId);
894 System.err.println("Error: package " + pkg + " not found.");
898 if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
899 System.err.println("Error: package " + pkg + " does not handle web links.");
903 System.out.println(linkStateToString(mPm.getIntentVerificationStatus(pkg, userId)));
904 } catch (Exception e) {
905 System.err.println(e.toString());
906 System.err.println(PM_NOT_RUNNING_ERR);
913 private String linkStateToString(int state) {
915 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
916 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
917 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
918 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
919 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
921 return "Unknown link state: " + state;
924 private int runSetInstallLocation() {
927 String arg = nextArg();
929 System.err.println("Error: no install location specified.");
933 loc = Integer.parseInt(arg);
934 } catch (NumberFormatException e) {
935 System.err.println("Error: install location has to be a number.");
939 if (!mPm.setInstallLocation(loc)) {
940 System.err.println("Error: install location has to be a number.");
944 } catch (RemoteException e) {
945 System.err.println(e.toString());
946 System.err.println(PM_NOT_RUNNING_ERR);
951 private int runGetInstallLocation() {
953 int loc = mPm.getInstallLocation();
954 String locStr = "invalid";
955 if (loc == PackageHelper.APP_INSTALL_AUTO) {
957 } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
959 } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
962 System.out.println(loc + "[" + locStr + "]");
964 } catch (RemoteException e) {
965 System.err.println(e.toString());
966 System.err.println(PM_NOT_RUNNING_ERR);
971 private int runSetInstaller() throws RemoteException {
972 final String targetPackage = nextArg();
973 final String installerPackageName = nextArg();
975 if (targetPackage == null || installerPackageName == null) {
976 throw new IllegalArgumentException(
977 "must provide both target and installer package names");
980 mPm.setInstallerPackageName(targetPackage, installerPackageName);
981 System.out.println("Success");
985 public int runCreateUser() {
990 while ((opt = nextOption()) != null) {
991 if ("--profileOf".equals(opt)) {
992 String optionData = nextOptionData();
993 if (optionData == null || !isNumber(optionData)) {
994 System.err.println("Error: no USER_ID specified");
997 userId = Integer.parseInt(optionData);
999 } else if ("--managed".equals(opt)) {
1000 flags |= UserInfo.FLAG_MANAGED_PROFILE;
1001 } else if ("--restricted".equals(opt)) {
1002 flags |= UserInfo.FLAG_RESTRICTED;
1003 } else if ("--ephemeral".equals(opt)) {
1004 flags |= UserInfo.FLAG_EPHEMERAL;
1005 } else if ("--guest".equals(opt)) {
1006 flags |= UserInfo.FLAG_GUEST;
1007 } else if ("--demo".equals(opt)) {
1008 flags |= UserInfo.FLAG_DEMO;
1010 System.err.println("Error: unknown option " + opt);
1014 String arg = nextArg();
1016 System.err.println("Error: no user name specified.");
1022 if ((flags & UserInfo.FLAG_RESTRICTED) != 0) {
1023 // In non-split user mode, userId can only be SYSTEM
1024 int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
1025 info = mUm.createRestrictedProfile(name, parentUserId);
1026 mAm.addSharedAccountsFromParentUser(parentUserId, userId,
1027 (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
1028 } else if (userId < 0) {
1029 info = mUm.createUser(name, flags);
1031 info = mUm.createProfileForUser(name, flags, userId, null);
1035 System.out.println("Success: created user id " + info.id);
1038 System.err.println("Error: couldn't create User.");
1041 } catch (RemoteException e) {
1042 System.err.println(e.toString());
1043 System.err.println(PM_NOT_RUNNING_ERR);
1048 public int runRemoveUser() {
1050 String arg = nextArg();
1052 System.err.println("Error: no user id specified.");
1056 userId = Integer.parseInt(arg);
1057 } catch (NumberFormatException e) {
1058 System.err.println("Error: user id '" + arg + "' is not a number.");
1062 if (mUm.removeUser(userId)) {
1063 System.out.println("Success: removed user");
1066 System.err.println("Error: couldn't remove user id " + userId);
1069 } catch (RemoteException e) {
1070 System.err.println(e.toString());
1071 System.err.println(PM_NOT_RUNNING_ERR);
1076 public int runGetMaxUsers() {
1077 System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers());
1081 public int runForceDexOpt() {
1082 final String packageName = nextArg();
1084 mPm.forceDexOpt(packageName);
1086 } catch (RemoteException e) {
1087 throw e.rethrowAsRuntimeException();
1091 public int runMovePackage() {
1092 final String packageName = nextArg();
1093 String volumeUuid = nextArg();
1094 if ("internal".equals(volumeUuid)) {
1099 final int moveId = mPm.movePackage(packageName, volumeUuid);
1101 int status = mPm.getMoveStatus(moveId);
1102 while (!PackageManager.isMoveStatusFinished(status)) {
1103 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1104 status = mPm.getMoveStatus(moveId);
1107 if (status == PackageManager.MOVE_SUCCEEDED) {
1108 System.out.println("Success");
1111 System.err.println("Failure [" + status + "]");
1114 } catch (RemoteException e) {
1115 throw e.rethrowAsRuntimeException();
1119 public int runMovePrimaryStorage() {
1120 String volumeUuid = nextArg();
1121 if ("internal".equals(volumeUuid)) {
1126 final int moveId = mPm.movePrimaryStorage(volumeUuid);
1128 int status = mPm.getMoveStatus(moveId);
1129 while (!PackageManager.isMoveStatusFinished(status)) {
1130 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1131 status = mPm.getMoveStatus(moveId);
1134 if (status == PackageManager.MOVE_SUCCEEDED) {
1135 System.out.println("Success");
1138 System.err.println("Failure [" + status + "]");
1141 } catch (RemoteException e) {
1142 throw e.rethrowAsRuntimeException();
1146 public int runSetUserRestriction() {
1147 int userId = UserHandle.USER_SYSTEM;
1148 String opt = nextOption();
1149 if (opt != null && "--user".equals(opt)) {
1150 String arg = nextArg();
1151 if (arg == null || !isNumber(arg)) {
1152 System.err.println("Error: valid userId not specified");
1155 userId = Integer.parseInt(arg);
1158 String restriction = nextArg();
1159 String arg = nextArg();
1161 if ("1".equals(arg)) {
1163 } else if ("0".equals(arg)) {
1166 System.err.println("Error: valid value not specified");
1170 mUm.setUserRestriction(restriction, value, userId);
1172 } catch (RemoteException e) {
1173 System.err.println(e.toString());
1178 static class ClearDataObserver extends IPackageDataObserver.Stub {
1183 public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1184 synchronized (this) {
1192 private int runClear() {
1193 int userId = UserHandle.USER_SYSTEM;
1194 String option = nextOption();
1195 if (option != null && option.equals("--user")) {
1196 String optionData = nextOptionData();
1197 if (optionData == null || !isNumber(optionData)) {
1198 System.err.println("Error: no USER_ID specified");
1201 userId = Integer.parseInt(optionData);
1205 String pkg = nextArg();
1207 System.err.println("Error: no package specified");
1211 ClearDataObserver obs = new ClearDataObserver();
1213 ActivityManager.getService().clearApplicationUserData(pkg, obs, userId);
1214 synchronized (obs) {
1215 while (!obs.finished) {
1218 } catch (InterruptedException e) {
1224 System.out.println("Success");
1227 System.err.println("Failed");
1230 } catch (RemoteException e) {
1231 System.err.println(e.toString());
1232 System.err.println(PM_NOT_RUNNING_ERR);
1237 private static String enabledSettingToString(int state) {
1239 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
1241 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
1243 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
1245 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
1246 return "disabled-user";
1247 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
1248 return "disabled-until-used";
1253 private static boolean isNumber(String s) {
1255 Integer.parseInt(s);
1256 } catch (NumberFormatException nfe) {
1262 private int runSetEnabledSetting(int state) {
1263 int userId = UserHandle.USER_SYSTEM;
1264 String option = nextOption();
1265 if (option != null && option.equals("--user")) {
1266 String optionData = nextOptionData();
1267 if (optionData == null || !isNumber(optionData)) {
1268 System.err.println("Error: no USER_ID specified");
1271 userId = Integer.parseInt(optionData);
1275 String pkg = nextArg();
1277 System.err.println("Error: no package or component specified");
1280 ComponentName cn = ComponentName.unflattenFromString(pkg);
1283 mPm.setApplicationEnabledSetting(pkg, state, 0, userId,
1284 "shell:" + android.os.Process.myUid());
1285 System.out.println("Package " + pkg + " new state: "
1286 + enabledSettingToString(
1287 mPm.getApplicationEnabledSetting(pkg, userId)));
1289 } catch (RemoteException e) {
1290 System.err.println(e.toString());
1291 System.err.println(PM_NOT_RUNNING_ERR);
1296 mPm.setComponentEnabledSetting(cn, state, 0, userId);
1297 System.out.println("Component " + cn.toShortString() + " new state: "
1298 + enabledSettingToString(
1299 mPm.getComponentEnabledSetting(cn, userId)));
1301 } catch (RemoteException e) {
1302 System.err.println(e.toString());
1303 System.err.println(PM_NOT_RUNNING_ERR);
1309 private int runSetHiddenSetting(boolean state) {
1310 int userId = UserHandle.USER_SYSTEM;
1311 String option = nextOption();
1312 if (option != null && option.equals("--user")) {
1313 String optionData = nextOptionData();
1314 if (optionData == null || !isNumber(optionData)) {
1315 System.err.println("Error: no USER_ID specified");
1318 userId = Integer.parseInt(optionData);
1322 String pkg = nextArg();
1324 System.err.println("Error: no package or component specified");
1328 mPm.setApplicationHiddenSettingAsUser(pkg, state, userId);
1329 System.out.println("Package " + pkg + " new hidden state: "
1330 + mPm.getApplicationHiddenSettingAsUser(pkg, userId));
1332 } catch (RemoteException e) {
1333 System.err.println(e.toString());
1334 System.err.println(PM_NOT_RUNNING_ERR);
1339 private int runGrantRevokePermission(boolean grant) {
1340 int userId = UserHandle.USER_SYSTEM;
1343 while ((opt = nextOption()) != null) {
1344 if (opt.equals("--user")) {
1345 userId = Integer.parseInt(nextArg());
1349 String pkg = nextArg();
1351 System.err.println("Error: no package specified");
1354 String perm = nextArg();
1356 System.err.println("Error: no permission specified");
1362 mPm.grantRuntimePermission(pkg, perm, userId);
1364 mPm.revokeRuntimePermission(pkg, perm, userId);
1367 } catch (RemoteException e) {
1368 System.err.println(e.toString());
1369 System.err.println(PM_NOT_RUNNING_ERR);
1371 } catch (IllegalArgumentException e) {
1372 System.err.println("Bad argument: " + e.toString());
1374 } catch (SecurityException e) {
1375 System.err.println("Operation not allowed: " + e.toString());
1380 private int runResetPermissions() {
1382 mPm.resetRuntimePermissions();
1384 } catch (RemoteException e) {
1385 System.err.println(e.toString());
1386 System.err.println(PM_NOT_RUNNING_ERR);
1388 } catch (IllegalArgumentException e) {
1389 System.err.println("Bad argument: " + e.toString());
1391 } catch (SecurityException e) {
1392 System.err.println("Operation not allowed: " + e.toString());
1397 private int runSetPermissionEnforced() {
1398 final String permission = nextArg();
1399 if (permission == null) {
1400 System.err.println("Error: no permission specified");
1403 final String enforcedRaw = nextArg();
1404 if (enforcedRaw == null) {
1405 System.err.println("Error: no enforcement specified");
1408 final boolean enforced = Boolean.parseBoolean(enforcedRaw);
1410 mPm.setPermissionEnforced(permission, enforced);
1412 } catch (RemoteException e) {
1413 System.err.println(e.toString());
1414 System.err.println(PM_NOT_RUNNING_ERR);
1416 } catch (IllegalArgumentException e) {
1417 System.err.println("Bad argument: " + e.toString());
1419 } catch (SecurityException e) {
1420 System.err.println("Operation not allowed: " + e.toString());
1425 static class ClearCacheObserver extends IPackageDataObserver.Stub {
1430 public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1431 synchronized (this) {
1440 private int runTrimCaches() {
1441 String size = nextArg();
1443 System.err.println("Error: no size specified");
1446 long multiplier = 1;
1447 int len = size.length();
1448 char c = size.charAt(len - 1);
1449 if (c < '0' || c > '9') {
1450 if (c == 'K' || c == 'k') {
1452 } else if (c == 'M' || c == 'm') {
1453 multiplier = 1024L*1024L;
1454 } else if (c == 'G' || c == 'g') {
1455 multiplier = 1024L*1024L*1024L;
1457 System.err.println("Invalid suffix: " + c);
1460 size = size.substring(0, len-1);
1464 sizeVal = Long.parseLong(size) * multiplier;
1465 } catch (NumberFormatException e) {
1466 System.err.println("Error: expected number at: " + size);
1469 String volumeUuid = nextArg();
1470 if ("internal".equals(volumeUuid)) {
1473 ClearDataObserver obs = new ClearDataObserver();
1475 mPm.freeStorageAndNotify(volumeUuid, sizeVal,
1476 StorageManager.FLAG_ALLOCATE_DEFY_RESERVED, obs);
1477 synchronized (obs) {
1478 while (!obs.finished) {
1481 } catch (InterruptedException e) {
1486 } catch (RemoteException e) {
1487 System.err.println(e.toString());
1488 System.err.println(PM_NOT_RUNNING_ERR);
1490 } catch (IllegalArgumentException e) {
1491 System.err.println("Bad argument: " + e.toString());
1493 } catch (SecurityException e) {
1494 System.err.println("Operation not allowed: " + e.toString());
1500 * Displays the package file for a package.
1503 private int displayPackageFilePath(String pckg, int userId) {
1505 PackageInfo info = mPm.getPackageInfo(pckg, 0, userId);
1506 if (info != null && info.applicationInfo != null) {
1507 System.out.print("package:");
1508 System.out.println(info.applicationInfo.sourceDir);
1509 if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
1510 for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
1511 System.out.print("package:");
1512 System.out.println(splitSourceDir);
1517 } catch (RemoteException e) {
1518 System.err.println(e.toString());
1519 System.err.println(PM_NOT_RUNNING_ERR);
1524 private String nextOption() {
1525 if (mNextArg >= mArgs.length) {
1528 String arg = mArgs[mNextArg];
1529 if (!arg.startsWith("-")) {
1533 if (arg.equals("--")) {
1536 if (arg.length() > 1 && arg.charAt(1) != '-') {
1537 if (arg.length() > 2) {
1538 mCurArgData = arg.substring(2);
1539 return arg.substring(0, 2);
1549 private String nextOptionData() {
1550 if (mCurArgData != null) {
1553 if (mNextArg >= mArgs.length) {
1556 String data = mArgs[mNextArg];
1561 private String nextArg() {
1562 if (mNextArg >= mArgs.length) {
1565 String arg = mArgs[mNextArg];
1570 private static int showUsage() {
1571 System.err.println("usage: pm path [--user USER_ID] PACKAGE");
1572 System.err.println(" pm dump PACKAGE");
1573 System.err.println(" pm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH]");
1574 System.err.println(" pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]");
1575 System.err.println(" [--install-location 0/1/2]");
1576 System.err.println(" [--force-uuid internal|UUID]");
1577 System.err.println(" pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]");
1578 System.err.println(" pm install-commit SESSION_ID");
1579 System.err.println(" pm install-abandon SESSION_ID");
1580 System.err.println(" pm uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE] PACKAGE");
1581 System.err.println(" pm set-installer PACKAGE INSTALLER");
1582 System.err.println(" pm move-package PACKAGE [internal|UUID]");
1583 System.err.println(" pm move-primary-storage [internal|UUID]");
1584 System.err.println(" pm clear [--user USER_ID] PACKAGE");
1585 System.err.println(" pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
1586 System.err.println(" pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
1587 System.err.println(" pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
1588 System.err.println(" pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
1589 System.err.println(" pm default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
1590 System.err.println(" pm set-user-restriction [--user USER_ID] RESTRICTION VALUE");
1591 System.err.println(" pm hide [--user USER_ID] PACKAGE_OR_COMPONENT");
1592 System.err.println(" pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
1593 System.err.println(" pm grant [--user USER_ID] PACKAGE PERMISSION");
1594 System.err.println(" pm revoke [--user USER_ID] PACKAGE PERMISSION");
1595 System.err.println(" pm reset-permissions");
1596 System.err.println(" pm set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
1597 System.err.println(" pm get-app-link [--user USER_ID] PACKAGE");
1598 System.err.println(" pm set-install-location [0/auto] [1/internal] [2/external]");
1599 System.err.println(" pm get-install-location");
1600 System.err.println(" pm set-permission-enforced PERMISSION [true|false]");
1601 System.err.println(" pm trim-caches DESIRED_FREE_SPACE [internal|UUID]");
1602 System.err.println(" pm create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral] [--guest] USER_NAME");
1603 System.err.println(" pm remove-user USER_ID");
1604 System.err.println(" pm get-max-users");
1605 System.err.println("");
1606 System.err.println("NOTE: 'pm list' commands have moved! Run 'adb shell cmd package'");
1607 System.err.println(" to display the new commands.");
1608 System.err.println("");
1609 System.err.println("pm path: print the path to the .apk of the given PACKAGE.");
1610 System.err.println("");
1611 System.err.println("pm dump: print system state associated with the given PACKAGE.");
1612 System.err.println("");
1613 System.err.println("pm install: install a single legacy package");
1614 System.err.println("pm install-create: create an install session");
1615 System.err.println(" -l: forward lock application");
1616 System.err.println(" -r: replace existing application");
1617 System.err.println(" -t: allow test packages");
1618 System.err.println(" -i: specify the installer package name");
1619 System.err.println(" -s: install application on sdcard");
1620 System.err.println(" -f: install application on internal flash");
1621 System.err.println(" -d: allow version code downgrade (debuggable packages only)");
1622 System.err.println(" -p: partial application install");
1623 System.err.println(" -g: grant all runtime permissions");
1624 System.err.println(" -S: size in bytes of entire session");
1625 System.err.println("");
1626 System.err.println("pm install-write: write a package into existing session; path may");
1627 System.err.println(" be '-' to read from stdin");
1628 System.err.println(" -S: size in bytes of package, required for stdin");
1629 System.err.println("");
1630 System.err.println("pm install-commit: perform install of fully staged session");
1631 System.err.println("pm install-abandon: abandon session");
1632 System.err.println("");
1633 System.err.println("pm set-installer: set installer package name");
1634 System.err.println("");
1635 System.err.println("pm uninstall: removes a package from the system. Options:");
1636 System.err.println(" -k: keep the data and cache directories around after package removal.");
1637 System.err.println("");
1638 System.err.println("pm clear: deletes all data associated with a package.");
1639 System.err.println("");
1640 System.err.println("pm enable, disable, disable-user, disable-until-used, default-state:");
1641 System.err.println(" these commands change the enabled state of a given package or");
1642 System.err.println(" component (written as \"package/class\").");
1643 System.err.println("");
1644 System.err.println("pm grant, revoke: these commands either grant or revoke permissions");
1645 System.err.println(" to apps. The permissions must be declared as used in the app's");
1646 System.err.println(" manifest, be runtime permissions (protection level dangerous),");
1647 System.err.println(" and the app targeting SDK greater than Lollipop MR1.");
1648 System.err.println("");
1649 System.err.println("pm reset-permissions: revert all runtime permissions to their default state.");
1650 System.err.println("");
1651 System.err.println("pm get-install-location: returns the current install location.");
1652 System.err.println(" 0 [auto]: Let system decide the best location");
1653 System.err.println(" 1 [internal]: Install on internal device storage");
1654 System.err.println(" 2 [external]: Install on external media");
1655 System.err.println("");
1656 System.err.println("pm set-install-location: changes the default install location.");
1657 System.err.println(" NOTE: this is only intended for debugging; using this can cause");
1658 System.err.println(" applications to break and other undersireable behavior.");
1659 System.err.println(" 0 [auto]: Let system decide the best location");
1660 System.err.println(" 1 [internal]: Install on internal device storage");
1661 System.err.println(" 2 [external]: Install on external media");
1662 System.err.println("");
1663 System.err.println("pm trim-caches: trim cache files to reach the given free space.");
1664 System.err.println("");
1665 System.err.println("pm create-user: create a new user with the given USER_NAME,");
1666 System.err.println(" printing the new user identifier of the user.");
1667 System.err.println("");
1668 System.err.println("pm remove-user: remove the user with the given USER_IDENTIFIER,");
1669 System.err.println(" deleting all data associated with that user");
1670 System.err.println("");