• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.commands.pm;
18 
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;
24 
25 import android.accounts.IAccountManager;
26 import android.app.ActivityManager;
27 import android.app.ActivityManagerNative;
28 import android.app.PackageInstallObserver;
29 import android.content.ComponentName;
30 import android.content.Context;
31 import android.content.IIntentReceiver;
32 import android.content.IIntentSender;
33 import android.content.Intent;
34 import android.content.IntentSender;
35 import android.content.pm.ApplicationInfo;
36 import android.content.pm.IPackageDataObserver;
37 import android.content.pm.IPackageInstaller;
38 import android.content.pm.IPackageManager;
39 import android.content.pm.PackageInfo;
40 import android.content.pm.PackageInstaller;
41 import android.content.pm.PackageInstaller.SessionInfo;
42 import android.content.pm.PackageInstaller.SessionParams;
43 import android.content.pm.PackageManager;
44 import android.content.pm.UserInfo;
45 import android.net.Uri;
46 import android.os.Binder;
47 import android.os.Build;
48 import android.os.Bundle;
49 import android.os.Handler;
50 import android.os.HandlerThread;
51 import android.os.IUserManager;
52 import android.os.RemoteException;
53 import android.os.ResultReceiver;
54 import android.os.ServiceManager;
55 import android.os.SystemClock;
56 import android.os.UserHandle;
57 import android.os.UserManager;
58 import android.text.TextUtils;
59 import android.text.format.DateUtils;
60 import android.util.Log;
61 
62 import com.android.internal.content.PackageHelper;
63 import com.android.internal.util.ArrayUtils;
64 import com.android.internal.util.SizedInputStream;
65 
66 import libcore.io.IoUtils;
67 
68 import java.io.File;
69 import java.io.FileDescriptor;
70 import java.io.FileInputStream;
71 import java.io.IOException;
72 import java.io.InputStream;
73 import java.io.OutputStream;
74 import java.util.concurrent.SynchronousQueue;
75 import java.util.concurrent.TimeUnit;
76 
77 public final class Pm {
78     private static final String TAG = "Pm";
79 
80     IPackageManager mPm;
81     IPackageInstaller mInstaller;
82     IUserManager mUm;
83     IAccountManager mAm;
84 
85     private String[] mArgs;
86     private int mNextArg;
87     private String mCurArgData;
88 
89     private static final String PM_NOT_RUNNING_ERR =
90         "Error: Could not access the Package Manager.  Is the system running?";
91 
main(String[] args)92     public static void main(String[] args) {
93         int exitCode = 1;
94         try {
95             exitCode = new Pm().run(args);
96         } catch (Exception e) {
97             Log.e(TAG, "Error", e);
98             System.err.println("Error: " + e);
99             if (e instanceof RemoteException) {
100                 System.err.println(PM_NOT_RUNNING_ERR);
101             }
102         }
103         System.exit(exitCode);
104     }
105 
run(String[] args)106     public int run(String[] args) throws RemoteException {
107         boolean validCommand = false;
108         if (args.length < 1) {
109             return showUsage();
110         }
111         mAm = IAccountManager.Stub.asInterface(ServiceManager.getService(Context.ACCOUNT_SERVICE));
112         mUm = IUserManager.Stub.asInterface(ServiceManager.getService(Context.USER_SERVICE));
113         mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
114 
115         if (mPm == null) {
116             System.err.println(PM_NOT_RUNNING_ERR);
117             return 1;
118         }
119         mInstaller = mPm.getPackageInstaller();
120 
121         mArgs = args;
122         String op = args[0];
123         mNextArg = 1;
124 
125         if ("list".equals(op)) {
126             return runList();
127         }
128 
129         if ("path".equals(op)) {
130             return runPath();
131         }
132 
133         if ("dump".equals(op)) {
134             return runDump();
135         }
136 
137         if ("install".equals(op)) {
138             return runInstall();
139         }
140 
141         if ("install-create".equals(op)) {
142             return runInstallCreate();
143         }
144 
145         if ("install-write".equals(op)) {
146             return runInstallWrite();
147         }
148 
149         if ("install-commit".equals(op)) {
150             return runInstallCommit();
151         }
152 
153         if ("install-abandon".equals(op) || "install-destroy".equals(op)) {
154             return runInstallAbandon();
155         }
156 
157         if ("set-installer".equals(op)) {
158             return runSetInstaller();
159         }
160 
161         if ("uninstall".equals(op)) {
162             return runUninstall();
163         }
164 
165         if ("clear".equals(op)) {
166             return runClear();
167         }
168 
169         if ("enable".equals(op)) {
170             return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
171         }
172 
173         if ("disable".equals(op)) {
174             return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
175         }
176 
177         if ("disable-user".equals(op)) {
178             return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
179         }
180 
181         if ("disable-until-used".equals(op)) {
182             return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
183         }
184 
185         if ("default-state".equals(op)) {
186             return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
187         }
188 
189         if ("hide".equals(op)) {
190             return runSetHiddenSetting(true);
191         }
192 
193         if ("unhide".equals(op)) {
194             return runSetHiddenSetting(false);
195         }
196 
197         if ("grant".equals(op)) {
198             return runGrantRevokePermission(true);
199         }
200 
201         if ("revoke".equals(op)) {
202             return runGrantRevokePermission(false);
203         }
204 
205         if ("reset-permissions".equals(op)) {
206             return runResetPermissions();
207         }
208 
209         if ("set-permission-enforced".equals(op)) {
210             return runSetPermissionEnforced();
211         }
212 
213         if ("set-app-link".equals(op)) {
214             return runSetAppLink();
215         }
216 
217         if ("get-app-link".equals(op)) {
218             return runGetAppLink();
219         }
220 
221         if ("set-install-location".equals(op)) {
222             return runSetInstallLocation();
223         }
224 
225         if ("get-install-location".equals(op)) {
226             return runGetInstallLocation();
227         }
228 
229         if ("trim-caches".equals(op)) {
230             return runTrimCaches();
231         }
232 
233         if ("create-user".equals(op)) {
234             return runCreateUser();
235         }
236 
237         if ("remove-user".equals(op)) {
238             return runRemoveUser();
239         }
240 
241         if ("get-max-users".equals(op)) {
242             return runGetMaxUsers();
243         }
244 
245         if ("force-dex-opt".equals(op)) {
246             return runForceDexOpt();
247         }
248 
249         if ("move-package".equals(op)) {
250             return runMovePackage();
251         }
252 
253         if ("move-primary-storage".equals(op)) {
254             return runMovePrimaryStorage();
255         }
256 
257         if ("set-user-restriction".equals(op)) {
258             return runSetUserRestriction();
259         }
260 
261         try {
262             if (args.length == 1) {
263                 if (args[0].equalsIgnoreCase("-l")) {
264                     validCommand = true;
265                     return runShellCommand("package", new String[] { "list", "package" });
266                 } else if (args[0].equalsIgnoreCase("-lf")) {
267                     validCommand = true;
268                     return runShellCommand("package", new String[] { "list", "package", "-f" });
269                 }
270             } else if (args.length == 2) {
271                 if (args[0].equalsIgnoreCase("-p")) {
272                     validCommand = true;
273                     return displayPackageFilePath(args[1], UserHandle.USER_SYSTEM);
274                 }
275             }
276             return 1;
277         } finally {
278             if (validCommand == false) {
279                 if (op != null) {
280                     System.err.println("Error: unknown command '" + op + "'");
281                 }
282                 showUsage();
283             }
284         }
285     }
286 
runShellCommand(String serviceName, String[] args)287     private int runShellCommand(String serviceName, String[] args) {
288         final HandlerThread handlerThread = new HandlerThread("results");
289         handlerThread.start();
290         try {
291             ServiceManager.getService(serviceName).shellCommand(
292                     FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
293                     args, new ResultReceiver(new Handler(handlerThread.getLooper())));
294             return 0;
295         } catch (RemoteException e) {
296             e.printStackTrace();
297         } finally {
298             handlerThread.quitSafely();
299         }
300         return -1;
301     }
302 
303     private static class LocalIntentReceiver {
304         private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
305 
306         private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
307             @Override
308             public void send(int code, Intent intent, String resolvedType,
309                     IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
310                 try {
311                     mResult.offer(intent, 5, TimeUnit.SECONDS);
312                 } catch (InterruptedException e) {
313                     throw new RuntimeException(e);
314                 }
315             }
316         };
317 
getIntentSender()318         public IntentSender getIntentSender() {
319             return new IntentSender((IIntentSender) mLocalSender);
320         }
321 
getResult()322         public Intent getResult() {
323             try {
324                 return mResult.take();
325             } catch (InterruptedException e) {
326                 throw new RuntimeException(e);
327             }
328         }
329     }
330 
translateUserId(int userId, String logContext)331     private int translateUserId(int userId, String logContext) {
332         return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
333                 userId, true, true, logContext, "pm command");
334     }
335 
checkAbiArgument(String abi)336     private static String checkAbiArgument(String abi) {
337         if (TextUtils.isEmpty(abi)) {
338             throw new IllegalArgumentException("Missing ABI argument");
339         }
340         if ("-".equals(abi)) {
341             return abi;
342         }
343         final String[] supportedAbis = Build.SUPPORTED_ABIS;
344         for (String supportedAbi : supportedAbis) {
345             if (supportedAbi.equals(abi)) {
346                 return abi;
347             }
348         }
349         throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
350     }
351 
352     /*
353      * Keep this around to support existing users of the "pm install" command that may not be
354      * able to be updated [or, at least informed the API has changed] such as ddmlib.
355      *
356      * Moving the implementation of "pm install" to "cmd package install" changes the executing
357      * context. Instead of being a stand alone process, "cmd package install" runs in the
358      * system_server process. Due to SELinux rules, system_server cannot access many directories;
359      * one of which being the package install staging directory [/data/local/tmp].
360      *
361      * The use of "adb install" or "cmd package install" over "pm install" is highly encouraged.
362      */
runInstall()363     private int runInstall() throws RemoteException {
364         final InstallParams params = makeInstallParams();
365         final int sessionId = doCreateSession(params.sessionParams,
366                 params.installerPackageName, params.userId);
367 
368         try {
369             final String inPath = nextArg();
370             if (inPath == null && params.sessionParams.sizeBytes == 0) {
371                 System.err.println("Error: must either specify a package size or an APK file");
372                 return 1;
373             }
374             if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
375                     false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
376                 return 1;
377             }
378             if (doCommitSession(sessionId, false /*logSuccess*/)
379                     != PackageInstaller.STATUS_SUCCESS) {
380                 return 1;
381             }
382             System.out.println("Success");
383             return 0;
384         } finally {
385             try {
386                 mInstaller.abandonSession(sessionId);
387             } catch (Exception ignore) {
388             }
389         }
390     }
391 
runInstallAbandon()392     private int runInstallAbandon() throws RemoteException {
393         final int sessionId = Integer.parseInt(nextArg());
394         return doAbandonSession(sessionId, true /*logSuccess*/);
395     }
396 
runInstallCommit()397     private int runInstallCommit() throws RemoteException {
398         final int sessionId = Integer.parseInt(nextArg());
399         return doCommitSession(sessionId, true /*logSuccess*/);
400     }
401 
runInstallCreate()402     private int runInstallCreate() throws RemoteException {
403         final InstallParams installParams = makeInstallParams();
404         final int sessionId = doCreateSession(installParams.sessionParams,
405                 installParams.installerPackageName, installParams.userId);
406 
407         // NOTE: adb depends on parsing this string
408         System.out.println("Success: created install session [" + sessionId + "]");
409         return PackageInstaller.STATUS_SUCCESS;
410     }
411 
runInstallWrite()412     private int runInstallWrite() throws RemoteException {
413         long sizeBytes = -1;
414 
415         String opt;
416         while ((opt = nextOption()) != null) {
417             if (opt.equals("-S")) {
418                 sizeBytes = Long.parseLong(nextArg());
419             } else {
420                 throw new IllegalArgumentException("Unknown option: " + opt);
421             }
422         }
423 
424         final int sessionId = Integer.parseInt(nextArg());
425         final String splitName = nextArg();
426         final String path = nextArg();
427         return doWriteSession(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
428     }
429 
430     private static class InstallParams {
431         SessionParams sessionParams;
432         String installerPackageName;
433         int userId = UserHandle.USER_ALL;
434     }
435 
makeInstallParams()436     private InstallParams makeInstallParams() {
437         final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
438         final InstallParams params = new InstallParams();
439         params.sessionParams = sessionParams;
440         String opt;
441         while ((opt = nextOption()) != null) {
442             switch (opt) {
443                 case "-l":
444                     sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
445                     break;
446                 case "-r":
447                     sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
448                     break;
449                 case "-i":
450                     params.installerPackageName = nextArg();
451                     if (params.installerPackageName == null) {
452                         throw new IllegalArgumentException("Missing installer package");
453                     }
454                     break;
455                 case "-t":
456                     sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
457                     break;
458                 case "-s":
459                     sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL;
460                     break;
461                 case "-f":
462                     sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
463                     break;
464                 case "-d":
465                     sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
466                     break;
467                 case "-g":
468                     sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
469                     break;
470                 case "--dont-kill":
471                     sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
472                     break;
473                 case "--originating-uri":
474                     sessionParams.originatingUri = Uri.parse(nextOptionData());
475                     break;
476                 case "--referrer":
477                     sessionParams.referrerUri = Uri.parse(nextOptionData());
478                     break;
479                 case "-p":
480                     sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
481                     sessionParams.appPackageName = nextOptionData();
482                     if (sessionParams.appPackageName == null) {
483                         throw new IllegalArgumentException("Missing inherit package name");
484                     }
485                     break;
486                 case "-S":
487                     sessionParams.setSize(Long.parseLong(nextOptionData()));
488                     break;
489                 case "--abi":
490                     sessionParams.abiOverride = checkAbiArgument(nextOptionData());
491                     break;
492                 case "--ephemeral":
493                     sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL;
494                     break;
495                 case "--user":
496                     params.userId = UserHandle.parseUserArg(nextOptionData());
497                     break;
498                 case "--install-location":
499                     sessionParams.installLocation = Integer.parseInt(nextOptionData());
500                     break;
501                 case "--force-uuid":
502                     sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
503                     sessionParams.volumeUuid = nextOptionData();
504                     if ("internal".equals(sessionParams.volumeUuid)) {
505                         sessionParams.volumeUuid = null;
506                     }
507                     break;
508                 case "--force-sdk":
509                     sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK;
510                     break;
511                 default:
512                     throw new IllegalArgumentException("Unknown option " + opt);
513             }
514         }
515         return params;
516     }
517 
doCreateSession(SessionParams params, String installerPackageName, int userId)518     private int doCreateSession(SessionParams params, String installerPackageName, int userId)
519             throws RemoteException {
520         userId = translateUserId(userId, "runInstallCreate");
521         if (userId == UserHandle.USER_ALL) {
522             userId = UserHandle.USER_SYSTEM;
523             params.installFlags |= PackageManager.INSTALL_ALL_USERS;
524         }
525 
526         final int sessionId = mInstaller.createSession(params, installerPackageName, userId);
527         return sessionId;
528     }
529 
doWriteSession(int sessionId, String inPath, long sizeBytes, String splitName, boolean logSuccess)530     private int doWriteSession(int sessionId, String inPath, long sizeBytes, String splitName,
531             boolean logSuccess) throws RemoteException {
532         if ("-".equals(inPath)) {
533             inPath = null;
534         } else if (inPath != null) {
535             final File file = new File(inPath);
536             if (file.isFile()) {
537                 sizeBytes = file.length();
538             }
539         }
540 
541         final SessionInfo info = mInstaller.getSessionInfo(sessionId);
542 
543         PackageInstaller.Session session = null;
544         InputStream in = null;
545         OutputStream out = null;
546         try {
547             session = new PackageInstaller.Session(
548                     mInstaller.openSession(sessionId));
549 
550             if (inPath != null) {
551                 in = new FileInputStream(inPath);
552             } else {
553                 in = new SizedInputStream(System.in, sizeBytes);
554             }
555             out = session.openWrite(splitName, 0, sizeBytes);
556 
557             int total = 0;
558             byte[] buffer = new byte[65536];
559             int c;
560             while ((c = in.read(buffer)) != -1) {
561                 total += c;
562                 out.write(buffer, 0, c);
563 
564                 if (info.sizeBytes > 0) {
565                     final float fraction = ((float) c / (float) info.sizeBytes);
566                     session.addProgress(fraction);
567                 }
568             }
569             session.fsync(out);
570 
571             if (logSuccess) {
572                 System.out.println("Success: streamed " + total + " bytes");
573             }
574             return PackageInstaller.STATUS_SUCCESS;
575         } catch (IOException e) {
576             System.err.println("Error: failed to write; " + e.getMessage());
577             return PackageInstaller.STATUS_FAILURE;
578         } finally {
579             IoUtils.closeQuietly(out);
580             IoUtils.closeQuietly(in);
581             IoUtils.closeQuietly(session);
582         }
583     }
584 
doCommitSession(int sessionId, boolean logSuccess)585     private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
586         PackageInstaller.Session session = null;
587         try {
588             session = new PackageInstaller.Session(
589                     mInstaller.openSession(sessionId));
590 
591             final LocalIntentReceiver receiver = new LocalIntentReceiver();
592             session.commit(receiver.getIntentSender());
593 
594             final Intent result = receiver.getResult();
595             final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
596                     PackageInstaller.STATUS_FAILURE);
597             if (status == PackageInstaller.STATUS_SUCCESS) {
598                 if (logSuccess) {
599                     System.out.println("Success");
600                 }
601             } else {
602                 System.err.println("Failure ["
603                         + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
604             }
605             return status;
606         } finally {
607             IoUtils.closeQuietly(session);
608         }
609     }
610 
doAbandonSession(int sessionId, boolean logSuccess)611     private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
612         PackageInstaller.Session session = null;
613         try {
614             session = new PackageInstaller.Session(mInstaller.openSession(sessionId));
615             session.abandon();
616             if (logSuccess) {
617                 System.out.println("Success");
618             }
619             return PackageInstaller.STATUS_SUCCESS;
620         } finally {
621             IoUtils.closeQuietly(session);
622         }
623     }
624 
625     /**
626      * Execute the list sub-command.
627      *
628      * pm list [package | packages]
629      * pm list permission-groups
630      * pm list permissions
631      * pm list features
632      * pm list libraries
633      * pm list instrumentation
634      */
runList()635     private int runList() {
636         final String type = nextArg();
637         if ("users".equals(type)) {
638             return runShellCommand("user", new String[] { "list" });
639         }
640         return runShellCommand("package", mArgs);
641     }
642 
runUninstall()643     private int runUninstall() {
644         return runShellCommand("package", mArgs);
645     }
646 
runPath()647     private int runPath() {
648         int userId = UserHandle.USER_SYSTEM;
649         String option = nextOption();
650         if (option != null && option.equals("--user")) {
651             String optionData = nextOptionData();
652             if (optionData == null || !isNumber(optionData)) {
653                 System.err.println("Error: no USER_ID specified");
654                 return showUsage();
655             } else {
656                 userId = Integer.parseInt(optionData);
657             }
658         }
659 
660         String pkg = nextArg();
661         if (pkg == null) {
662             System.err.println("Error: no package specified");
663             return 1;
664         }
665         return displayPackageFilePath(pkg, userId);
666     }
667 
runDump()668     private int runDump() {
669         String pkg = nextArg();
670         if (pkg == null) {
671             System.err.println("Error: no package specified");
672             return 1;
673         }
674         ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg);
675         return 0;
676     }
677 
678     class LocalPackageInstallObserver extends PackageInstallObserver {
679         boolean finished;
680         int result;
681         String extraPermission;
682         String extraPackage;
683 
684         @Override
onPackageInstalled(String name, int status, String msg, Bundle extras)685         public void onPackageInstalled(String name, int status, String msg, Bundle extras) {
686             synchronized (this) {
687                 finished = true;
688                 result = status;
689                 if (status == PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION) {
690                     extraPermission = extras.getString(
691                             PackageManager.EXTRA_FAILURE_EXISTING_PERMISSION);
692                     extraPackage = extras.getString(
693                             PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
694                 }
695                 notifyAll();
696             }
697         }
698     }
699 
700     // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
runSetAppLink()701     private int runSetAppLink() {
702         int userId = UserHandle.USER_SYSTEM;
703 
704         String opt;
705         while ((opt = nextOption()) != null) {
706             if (opt.equals("--user")) {
707                 userId = Integer.parseInt(nextOptionData());
708                 if (userId < 0) {
709                     System.err.println("Error: user must be >= 0");
710                     return 1;
711                 }
712             } else {
713                 System.err.println("Error: unknown option: " + opt);
714                 return showUsage();
715             }
716         }
717 
718         // Package name to act on; required
719         final String pkg = nextArg();
720         if (pkg == null) {
721             System.err.println("Error: no package specified.");
722             return showUsage();
723         }
724 
725         // State to apply; {always|ask|never|undefined}, required
726         final String modeString = nextArg();
727         if (modeString == null) {
728             System.err.println("Error: no app link state specified.");
729             return showUsage();
730         }
731 
732         final int newMode;
733         switch (modeString.toLowerCase()) {
734             case "undefined":
735                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
736                 break;
737 
738             case "always":
739                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
740                 break;
741 
742             case "ask":
743                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
744                 break;
745 
746             case "always-ask":
747                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
748                 break;
749 
750             case "never":
751                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
752                 break;
753 
754             default:
755                 System.err.println("Error: unknown app link state '" + modeString + "'");
756                 return 1;
757         }
758 
759         try {
760             final PackageInfo info = mPm.getPackageInfo(pkg, 0, userId);
761             if (info == null) {
762                 System.err.println("Error: package " + pkg + " not found.");
763                 return 1;
764             }
765 
766             if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
767                 System.err.println("Error: package " + pkg + " does not handle web links.");
768                 return 1;
769             }
770 
771             if (!mPm.updateIntentVerificationStatus(pkg, newMode, userId)) {
772                 System.err.println("Error: unable to update app link status for " + pkg);
773                 return 1;
774             }
775         } catch (Exception e) {
776             System.err.println(e.toString());
777             System.err.println(PM_NOT_RUNNING_ERR);
778             return 1;
779         }
780 
781         return 0;
782     }
783 
784     // pm get-app-link [--user USER_ID] PACKAGE
runGetAppLink()785     private int runGetAppLink() {
786         int userId = UserHandle.USER_SYSTEM;
787 
788         String opt;
789         while ((opt = nextOption()) != null) {
790             if (opt.equals("--user")) {
791                 userId = Integer.parseInt(nextOptionData());
792                 if (userId < 0) {
793                     System.err.println("Error: user must be >= 0");
794                     return 1;
795                 }
796             } else {
797                 System.err.println("Error: unknown option: " + opt);
798                 return showUsage();
799             }
800         }
801 
802         // Package name to act on; required
803         final String pkg = nextArg();
804         if (pkg == null) {
805             System.err.println("Error: no package specified.");
806             return showUsage();
807         }
808 
809         try {
810             final PackageInfo info = mPm.getPackageInfo(pkg, 0, userId);
811             if (info == null) {
812                 System.err.println("Error: package " + pkg + " not found.");
813                 return 1;
814             }
815 
816             if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
817                 System.err.println("Error: package " + pkg + " does not handle web links.");
818                 return 1;
819             }
820 
821             System.out.println(linkStateToString(mPm.getIntentVerificationStatus(pkg, userId)));
822         } catch (Exception e) {
823             System.err.println(e.toString());
824             System.err.println(PM_NOT_RUNNING_ERR);
825             return 1;
826         }
827 
828         return 0;
829     }
830 
linkStateToString(int state)831     private String linkStateToString(int state) {
832         switch (state) {
833             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
834             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
835             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
836             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
837             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
838         }
839         return "Unknown link state: " + state;
840     }
841 
runSetInstallLocation()842     private int runSetInstallLocation() {
843         int loc;
844 
845         String arg = nextArg();
846         if (arg == null) {
847             System.err.println("Error: no install location specified.");
848             return 1;
849         }
850         try {
851             loc = Integer.parseInt(arg);
852         } catch (NumberFormatException e) {
853             System.err.println("Error: install location has to be a number.");
854             return 1;
855         }
856         try {
857             if (!mPm.setInstallLocation(loc)) {
858                 System.err.println("Error: install location has to be a number.");
859                 return 1;
860             }
861             return 0;
862         } catch (RemoteException e) {
863             System.err.println(e.toString());
864             System.err.println(PM_NOT_RUNNING_ERR);
865             return 1;
866         }
867     }
868 
runGetInstallLocation()869     private int runGetInstallLocation() {
870         try {
871             int loc = mPm.getInstallLocation();
872             String locStr = "invalid";
873             if (loc == PackageHelper.APP_INSTALL_AUTO) {
874                 locStr = "auto";
875             } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
876                 locStr = "internal";
877             } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
878                 locStr = "external";
879             }
880             System.out.println(loc + "[" + locStr + "]");
881             return 0;
882         } catch (RemoteException e) {
883             System.err.println(e.toString());
884             System.err.println(PM_NOT_RUNNING_ERR);
885             return 1;
886         }
887     }
888 
runSetInstaller()889     private int runSetInstaller() throws RemoteException {
890         final String targetPackage = nextArg();
891         final String installerPackageName = nextArg();
892 
893         if (targetPackage == null || installerPackageName == null) {
894             throw new IllegalArgumentException(
895                     "must provide both target and installer package names");
896         }
897 
898         mPm.setInstallerPackageName(targetPackage, installerPackageName);
899         System.out.println("Success");
900         return 0;
901     }
902 
runCreateUser()903     public int runCreateUser() {
904         String name;
905         int userId = -1;
906         int flags = 0;
907         String opt;
908         while ((opt = nextOption()) != null) {
909             if ("--profileOf".equals(opt)) {
910                 String optionData = nextOptionData();
911                 if (optionData == null || !isNumber(optionData)) {
912                     System.err.println("Error: no USER_ID specified");
913                     return showUsage();
914                 } else {
915                     userId = Integer.parseInt(optionData);
916                 }
917             } else if ("--managed".equals(opt)) {
918                 flags |= UserInfo.FLAG_MANAGED_PROFILE;
919             } else if ("--restricted".equals(opt)) {
920                 flags |= UserInfo.FLAG_RESTRICTED;
921             } else if ("--ephemeral".equals(opt)) {
922                 flags |= UserInfo.FLAG_EPHEMERAL;
923             } else if ("--guest".equals(opt)) {
924                 flags |= UserInfo.FLAG_GUEST;
925             } else if ("--demo".equals(opt)) {
926                 flags |= UserInfo.FLAG_DEMO;
927             } else {
928                 System.err.println("Error: unknown option " + opt);
929                 return showUsage();
930             }
931         }
932         String arg = nextArg();
933         if (arg == null) {
934             System.err.println("Error: no user name specified.");
935             return 1;
936         }
937         name = arg;
938         try {
939             UserInfo info;
940             if ((flags & UserInfo.FLAG_RESTRICTED) != 0) {
941                 // In non-split user mode, userId can only be SYSTEM
942                 int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
943                 info = mUm.createRestrictedProfile(name, parentUserId);
944                 mAm.addSharedAccountsFromParentUser(parentUserId, userId);
945             } else if (userId < 0) {
946                 info = mUm.createUser(name, flags);
947             } else {
948                 info = mUm.createProfileForUser(name, flags, userId);
949             }
950 
951             if (info != null) {
952                 System.out.println("Success: created user id " + info.id);
953                 return 1;
954             } else {
955                 System.err.println("Error: couldn't create User.");
956                 return 1;
957             }
958         } catch (RemoteException e) {
959             System.err.println(e.toString());
960             System.err.println(PM_NOT_RUNNING_ERR);
961             return 1;
962         }
963     }
964 
runRemoveUser()965     public int runRemoveUser() {
966         int userId;
967         String arg = nextArg();
968         if (arg == null) {
969             System.err.println("Error: no user id specified.");
970             return 1;
971         }
972         try {
973             userId = Integer.parseInt(arg);
974         } catch (NumberFormatException e) {
975             System.err.println("Error: user id '" + arg + "' is not a number.");
976             return 1;
977         }
978         try {
979             if (mUm.removeUser(userId)) {
980                 System.out.println("Success: removed user");
981                 return 0;
982             } else {
983                 System.err.println("Error: couldn't remove user id " + userId);
984                 return 1;
985             }
986         } catch (RemoteException e) {
987             System.err.println(e.toString());
988             System.err.println(PM_NOT_RUNNING_ERR);
989             return 1;
990         }
991     }
992 
runGetMaxUsers()993     public int runGetMaxUsers() {
994         System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers());
995         return 0;
996     }
997 
runForceDexOpt()998     public int runForceDexOpt() {
999         final String packageName = nextArg();
1000         try {
1001             mPm.forceDexOpt(packageName);
1002             return 0;
1003         } catch (RemoteException e) {
1004             throw e.rethrowAsRuntimeException();
1005         }
1006     }
1007 
runMovePackage()1008     public int runMovePackage() {
1009         final String packageName = nextArg();
1010         String volumeUuid = nextArg();
1011         if ("internal".equals(volumeUuid)) {
1012             volumeUuid = null;
1013         }
1014 
1015         try {
1016             final int moveId = mPm.movePackage(packageName, volumeUuid);
1017 
1018             int status = mPm.getMoveStatus(moveId);
1019             while (!PackageManager.isMoveStatusFinished(status)) {
1020                 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1021                 status = mPm.getMoveStatus(moveId);
1022             }
1023 
1024             if (status == PackageManager.MOVE_SUCCEEDED) {
1025                 System.out.println("Success");
1026                 return 0;
1027             } else {
1028                 System.err.println("Failure [" + status + "]");
1029                 return 1;
1030             }
1031         } catch (RemoteException e) {
1032             throw e.rethrowAsRuntimeException();
1033         }
1034     }
1035 
runMovePrimaryStorage()1036     public int runMovePrimaryStorage() {
1037         String volumeUuid = nextArg();
1038         if ("internal".equals(volumeUuid)) {
1039             volumeUuid = null;
1040         }
1041 
1042         try {
1043             final int moveId = mPm.movePrimaryStorage(volumeUuid);
1044 
1045             int status = mPm.getMoveStatus(moveId);
1046             while (!PackageManager.isMoveStatusFinished(status)) {
1047                 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1048                 status = mPm.getMoveStatus(moveId);
1049             }
1050 
1051             if (status == PackageManager.MOVE_SUCCEEDED) {
1052                 System.out.println("Success");
1053                 return 0;
1054             } else {
1055                 System.err.println("Failure [" + status + "]");
1056                 return 1;
1057             }
1058         } catch (RemoteException e) {
1059             throw e.rethrowAsRuntimeException();
1060         }
1061     }
1062 
runSetUserRestriction()1063     public int runSetUserRestriction() {
1064         int userId = UserHandle.USER_SYSTEM;
1065         String opt = nextOption();
1066         if (opt != null && "--user".equals(opt)) {
1067             String arg = nextArg();
1068             if (arg == null || !isNumber(arg)) {
1069                 System.err.println("Error: valid userId not specified");
1070                 return 1;
1071             }
1072             userId = Integer.parseInt(arg);
1073         }
1074 
1075         String restriction = nextArg();
1076         String arg = nextArg();
1077         boolean value;
1078         if ("1".equals(arg)) {
1079             value = true;
1080         } else if ("0".equals(arg)) {
1081             value = false;
1082         } else {
1083             System.err.println("Error: valid value not specified");
1084             return 1;
1085         }
1086         try {
1087             mUm.setUserRestriction(restriction, value, userId);
1088             return 0;
1089         } catch (RemoteException e) {
1090             System.err.println(e.toString());
1091             return 1;
1092         }
1093     }
1094 
1095     static class ClearDataObserver extends IPackageDataObserver.Stub {
1096         boolean finished;
1097         boolean result;
1098 
1099         @Override
onRemoveCompleted(String packageName, boolean succeeded)1100         public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1101             synchronized (this) {
1102                 finished = true;
1103                 result = succeeded;
1104                 notifyAll();
1105             }
1106         }
1107     }
1108 
runClear()1109     private int runClear() {
1110         int userId = UserHandle.USER_SYSTEM;
1111         String option = nextOption();
1112         if (option != null && option.equals("--user")) {
1113             String optionData = nextOptionData();
1114             if (optionData == null || !isNumber(optionData)) {
1115                 System.err.println("Error: no USER_ID specified");
1116                 return showUsage();
1117             } else {
1118                 userId = Integer.parseInt(optionData);
1119             }
1120         }
1121 
1122         String pkg = nextArg();
1123         if (pkg == null) {
1124             System.err.println("Error: no package specified");
1125             return showUsage();
1126         }
1127 
1128         ClearDataObserver obs = new ClearDataObserver();
1129         try {
1130             ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, userId);
1131             synchronized (obs) {
1132                 while (!obs.finished) {
1133                     try {
1134                         obs.wait();
1135                     } catch (InterruptedException e) {
1136                     }
1137                 }
1138             }
1139 
1140             if (obs.result) {
1141                 System.out.println("Success");
1142                 return 0;
1143             } else {
1144                 System.err.println("Failed");
1145                 return 1;
1146             }
1147         } catch (RemoteException e) {
1148             System.err.println(e.toString());
1149             System.err.println(PM_NOT_RUNNING_ERR);
1150             return 1;
1151         }
1152     }
1153 
enabledSettingToString(int state)1154     private static String enabledSettingToString(int state) {
1155         switch (state) {
1156             case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
1157                 return "default";
1158             case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
1159                 return "enabled";
1160             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
1161                 return "disabled";
1162             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
1163                 return "disabled-user";
1164             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
1165                 return "disabled-until-used";
1166         }
1167         return "unknown";
1168     }
1169 
isNumber(String s)1170     private static boolean isNumber(String s) {
1171         try {
1172             Integer.parseInt(s);
1173         } catch (NumberFormatException nfe) {
1174             return false;
1175         }
1176         return true;
1177     }
1178 
runSetEnabledSetting(int state)1179     private int runSetEnabledSetting(int state) {
1180         int userId = UserHandle.USER_SYSTEM;
1181         String option = nextOption();
1182         if (option != null && option.equals("--user")) {
1183             String optionData = nextOptionData();
1184             if (optionData == null || !isNumber(optionData)) {
1185                 System.err.println("Error: no USER_ID specified");
1186                 return showUsage();
1187             } else {
1188                 userId = Integer.parseInt(optionData);
1189             }
1190         }
1191 
1192         String pkg = nextArg();
1193         if (pkg == null) {
1194             System.err.println("Error: no package or component specified");
1195             return showUsage();
1196         }
1197         ComponentName cn = ComponentName.unflattenFromString(pkg);
1198         if (cn == null) {
1199             try {
1200                 mPm.setApplicationEnabledSetting(pkg, state, 0, userId,
1201                         "shell:" + android.os.Process.myUid());
1202                 System.out.println("Package " + pkg + " new state: "
1203                         + enabledSettingToString(
1204                         mPm.getApplicationEnabledSetting(pkg, userId)));
1205                 return 0;
1206             } catch (RemoteException e) {
1207                 System.err.println(e.toString());
1208                 System.err.println(PM_NOT_RUNNING_ERR);
1209                 return 1;
1210             }
1211         } else {
1212             try {
1213                 mPm.setComponentEnabledSetting(cn, state, 0, userId);
1214                 System.out.println("Component " + cn.toShortString() + " new state: "
1215                         + enabledSettingToString(
1216                         mPm.getComponentEnabledSetting(cn, userId)));
1217                 return 0;
1218             } catch (RemoteException e) {
1219                 System.err.println(e.toString());
1220                 System.err.println(PM_NOT_RUNNING_ERR);
1221                 return 1;
1222             }
1223         }
1224     }
1225 
runSetHiddenSetting(boolean state)1226     private int runSetHiddenSetting(boolean state) {
1227         int userId = UserHandle.USER_SYSTEM;
1228         String option = nextOption();
1229         if (option != null && option.equals("--user")) {
1230             String optionData = nextOptionData();
1231             if (optionData == null || !isNumber(optionData)) {
1232                 System.err.println("Error: no USER_ID specified");
1233                 return showUsage();
1234             } else {
1235                 userId = Integer.parseInt(optionData);
1236             }
1237         }
1238 
1239         String pkg = nextArg();
1240         if (pkg == null) {
1241             System.err.println("Error: no package or component specified");
1242             return showUsage();
1243         }
1244         try {
1245             mPm.setApplicationHiddenSettingAsUser(pkg, state, userId);
1246             System.out.println("Package " + pkg + " new hidden state: "
1247                     + mPm.getApplicationHiddenSettingAsUser(pkg, userId));
1248             return 0;
1249         } catch (RemoteException e) {
1250             System.err.println(e.toString());
1251             System.err.println(PM_NOT_RUNNING_ERR);
1252             return 1;
1253         }
1254     }
1255 
runGrantRevokePermission(boolean grant)1256     private int runGrantRevokePermission(boolean grant) {
1257         int userId = UserHandle.USER_SYSTEM;
1258 
1259         String opt = null;
1260         while ((opt = nextOption()) != null) {
1261             if (opt.equals("--user")) {
1262                 userId = Integer.parseInt(nextArg());
1263             }
1264         }
1265 
1266         String pkg = nextArg();
1267         if (pkg == null) {
1268             System.err.println("Error: no package specified");
1269             return showUsage();
1270         }
1271         String perm = nextArg();
1272         if (perm == null) {
1273             System.err.println("Error: no permission specified");
1274             return showUsage();
1275         }
1276 
1277         try {
1278             if (grant) {
1279                 mPm.grantRuntimePermission(pkg, perm, userId);
1280             } else {
1281                 mPm.revokeRuntimePermission(pkg, perm, userId);
1282             }
1283             return 0;
1284         } catch (RemoteException e) {
1285             System.err.println(e.toString());
1286             System.err.println(PM_NOT_RUNNING_ERR);
1287             return 1;
1288         } catch (IllegalArgumentException e) {
1289             System.err.println("Bad argument: " + e.toString());
1290             return showUsage();
1291         } catch (SecurityException e) {
1292             System.err.println("Operation not allowed: " + e.toString());
1293             return 1;
1294         }
1295     }
1296 
runResetPermissions()1297     private int runResetPermissions() {
1298         try {
1299             mPm.resetRuntimePermissions();
1300             return 0;
1301         } catch (RemoteException e) {
1302             System.err.println(e.toString());
1303             System.err.println(PM_NOT_RUNNING_ERR);
1304             return 1;
1305         } catch (IllegalArgumentException e) {
1306             System.err.println("Bad argument: " + e.toString());
1307             return showUsage();
1308         } catch (SecurityException e) {
1309             System.err.println("Operation not allowed: " + e.toString());
1310             return 1;
1311         }
1312     }
1313 
runSetPermissionEnforced()1314     private int runSetPermissionEnforced() {
1315         final String permission = nextArg();
1316         if (permission == null) {
1317             System.err.println("Error: no permission specified");
1318             return showUsage();
1319         }
1320         final String enforcedRaw = nextArg();
1321         if (enforcedRaw == null) {
1322             System.err.println("Error: no enforcement specified");
1323             return showUsage();
1324         }
1325         final boolean enforced = Boolean.parseBoolean(enforcedRaw);
1326         try {
1327             mPm.setPermissionEnforced(permission, enforced);
1328             return 0;
1329         } catch (RemoteException e) {
1330             System.err.println(e.toString());
1331             System.err.println(PM_NOT_RUNNING_ERR);
1332             return 1;
1333         } catch (IllegalArgumentException e) {
1334             System.err.println("Bad argument: " + e.toString());
1335             return showUsage();
1336         } catch (SecurityException e) {
1337             System.err.println("Operation not allowed: " + e.toString());
1338             return 1;
1339         }
1340     }
1341 
1342     static class ClearCacheObserver extends IPackageDataObserver.Stub {
1343         boolean finished;
1344         boolean result;
1345 
1346         @Override
onRemoveCompleted(String packageName, boolean succeeded)1347         public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1348             synchronized (this) {
1349                 finished = true;
1350                 result = succeeded;
1351                 notifyAll();
1352             }
1353         }
1354 
1355     }
1356 
runTrimCaches()1357     private int runTrimCaches() {
1358         String size = nextArg();
1359         if (size == null) {
1360             System.err.println("Error: no size specified");
1361             return showUsage();
1362         }
1363         int len = size.length();
1364         long multiplier = 1;
1365         if (len > 1) {
1366             char c = size.charAt(len-1);
1367             if (c == 'K' || c == 'k') {
1368                 multiplier = 1024L;
1369             } else if (c == 'M' || c == 'm') {
1370                 multiplier = 1024L*1024L;
1371             } else if (c == 'G' || c == 'g') {
1372                 multiplier = 1024L*1024L*1024L;
1373             } else {
1374                 System.err.println("Invalid suffix: " + c);
1375                 return showUsage();
1376             }
1377             size = size.substring(0, len-1);
1378         }
1379         long sizeVal;
1380         try {
1381             sizeVal = Long.parseLong(size) * multiplier;
1382         } catch (NumberFormatException e) {
1383             System.err.println("Error: expected number at: " + size);
1384             return showUsage();
1385         }
1386         String volumeUuid = nextArg();
1387         if ("internal".equals(volumeUuid)) {
1388             volumeUuid = null;
1389         }
1390         ClearDataObserver obs = new ClearDataObserver();
1391         try {
1392             mPm.freeStorageAndNotify(volumeUuid, sizeVal, obs);
1393             synchronized (obs) {
1394                 while (!obs.finished) {
1395                     try {
1396                         obs.wait();
1397                     } catch (InterruptedException e) {
1398                     }
1399                 }
1400             }
1401             return 0;
1402         } catch (RemoteException e) {
1403             System.err.println(e.toString());
1404             System.err.println(PM_NOT_RUNNING_ERR);
1405             return 1;
1406         } catch (IllegalArgumentException e) {
1407             System.err.println("Bad argument: " + e.toString());
1408             return showUsage();
1409         } catch (SecurityException e) {
1410             System.err.println("Operation not allowed: " + e.toString());
1411             return 1;
1412         }
1413     }
1414 
1415     /**
1416      * Displays the package file for a package.
1417      * @param pckg
1418      */
displayPackageFilePath(String pckg, int userId)1419     private int displayPackageFilePath(String pckg, int userId) {
1420         try {
1421             PackageInfo info = mPm.getPackageInfo(pckg, 0, userId);
1422             if (info != null && info.applicationInfo != null) {
1423                 System.out.print("package:");
1424                 System.out.println(info.applicationInfo.sourceDir);
1425                 if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
1426                     for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
1427                         System.out.print("package:");
1428                         System.out.println(splitSourceDir);
1429                     }
1430                 }
1431                 return 0;
1432             }
1433         } catch (RemoteException e) {
1434             System.err.println(e.toString());
1435             System.err.println(PM_NOT_RUNNING_ERR);
1436         }
1437         return 1;
1438     }
1439 
nextOption()1440     private String nextOption() {
1441         if (mNextArg >= mArgs.length) {
1442             return null;
1443         }
1444         String arg = mArgs[mNextArg];
1445         if (!arg.startsWith("-")) {
1446             return null;
1447         }
1448         mNextArg++;
1449         if (arg.equals("--")) {
1450             return null;
1451         }
1452         if (arg.length() > 1 && arg.charAt(1) != '-') {
1453             if (arg.length() > 2) {
1454                 mCurArgData = arg.substring(2);
1455                 return arg.substring(0, 2);
1456             } else {
1457                 mCurArgData = null;
1458                 return arg;
1459             }
1460         }
1461         mCurArgData = null;
1462         return arg;
1463     }
1464 
nextOptionData()1465     private String nextOptionData() {
1466         if (mCurArgData != null) {
1467             return mCurArgData;
1468         }
1469         if (mNextArg >= mArgs.length) {
1470             return null;
1471         }
1472         String data = mArgs[mNextArg];
1473         mNextArg++;
1474         return data;
1475     }
1476 
nextArg()1477     private String nextArg() {
1478         if (mNextArg >= mArgs.length) {
1479             return null;
1480         }
1481         String arg = mArgs[mNextArg];
1482         mNextArg++;
1483         return arg;
1484     }
1485 
showUsage()1486     private static int showUsage() {
1487         System.err.println("usage: pm path [--user USER_ID] PACKAGE");
1488         System.err.println("       pm dump PACKAGE");
1489         System.err.println("       pm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH]");
1490         System.err.println("       pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]");
1491         System.err.println("               [--install-location 0/1/2]");
1492         System.err.println("               [--force-uuid internal|UUID]");
1493         System.err.println("       pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]");
1494         System.err.println("       pm install-commit SESSION_ID");
1495         System.err.println("       pm install-abandon SESSION_ID");
1496         System.err.println("       pm uninstall [-k] [--user USER_ID] PACKAGE");
1497         System.err.println("       pm set-installer PACKAGE INSTALLER");
1498         System.err.println("       pm move-package PACKAGE [internal|UUID]");
1499         System.err.println("       pm move-primary-storage [internal|UUID]");
1500         System.err.println("       pm clear [--user USER_ID] PACKAGE");
1501         System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
1502         System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
1503         System.err.println("       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
1504         System.err.println("       pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
1505         System.err.println("       pm default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
1506         System.err.println("       pm hide [--user USER_ID] PACKAGE_OR_COMPONENT");
1507         System.err.println("       pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
1508         System.err.println("       pm grant [--user USER_ID] PACKAGE PERMISSION");
1509         System.err.println("       pm revoke [--user USER_ID] PACKAGE PERMISSION");
1510         System.err.println("       pm reset-permissions");
1511         System.err.println("       pm set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
1512         System.err.println("       pm get-app-link [--user USER_ID] PACKAGE");
1513         System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
1514         System.err.println("       pm get-install-location");
1515         System.err.println("       pm set-permission-enforced PERMISSION [true|false]");
1516         System.err.println("       pm trim-caches DESIRED_FREE_SPACE [internal|UUID]");
1517         System.err.println("       pm create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral] [--guest] USER_NAME");
1518         System.err.println("       pm remove-user USER_ID");
1519         System.err.println("       pm get-max-users");
1520         System.err.println("");
1521         System.err.println("NOTE: 'pm list' commands have moved! Run 'adb shell cmd package'");
1522         System.err.println("  to display the new commands.");
1523         System.err.println("");
1524         System.err.println("pm path: print the path to the .apk of the given PACKAGE.");
1525         System.err.println("");
1526         System.err.println("pm dump: print system state associated with the given PACKAGE.");
1527         System.err.println("");
1528         System.err.println("pm install: install a single legacy package");
1529         System.err.println("pm install-create: create an install session");
1530         System.err.println("    -l: forward lock application");
1531         System.err.println("    -r: replace existing application");
1532         System.err.println("    -t: allow test packages");
1533         System.err.println("    -i: specify the installer package name");
1534         System.err.println("    -s: install application on sdcard");
1535         System.err.println("    -f: install application on internal flash");
1536         System.err.println("    -d: allow version code downgrade (debuggable packages only)");
1537         System.err.println("    -p: partial application install");
1538         System.err.println("    -g: grant all runtime permissions");
1539         System.err.println("    -S: size in bytes of entire session");
1540         System.err.println("");
1541         System.err.println("pm install-write: write a package into existing session; path may");
1542         System.err.println("  be '-' to read from stdin");
1543         System.err.println("    -S: size in bytes of package, required for stdin");
1544         System.err.println("");
1545         System.err.println("pm install-commit: perform install of fully staged session");
1546         System.err.println("pm install-abandon: abandon session");
1547         System.err.println("");
1548         System.err.println("pm set-installer: set installer package name");
1549         System.err.println("");
1550         System.err.println("pm uninstall: removes a package from the system. Options:");
1551         System.err.println("    -k: keep the data and cache directories around after package removal.");
1552         System.err.println("");
1553         System.err.println("pm clear: deletes all data associated with a package.");
1554         System.err.println("");
1555         System.err.println("pm enable, disable, disable-user, disable-until-used, default-state:");
1556         System.err.println("  these commands change the enabled state of a given package or");
1557         System.err.println("  component (written as \"package/class\").");
1558         System.err.println("");
1559         System.err.println("pm grant, revoke: these commands either grant or revoke permissions");
1560         System.err.println("    to apps. The permissions must be declared as used in the app's");
1561         System.err.println("    manifest, be runtime permissions (protection level dangerous),");
1562         System.err.println("    and the app targeting SDK greater than Lollipop MR1.");
1563         System.err.println("");
1564         System.err.println("pm reset-permissions: revert all runtime permissions to their default state.");
1565         System.err.println("");
1566         System.err.println("pm get-install-location: returns the current install location.");
1567         System.err.println("    0 [auto]: Let system decide the best location");
1568         System.err.println("    1 [internal]: Install on internal device storage");
1569         System.err.println("    2 [external]: Install on external media");
1570         System.err.println("");
1571         System.err.println("pm set-install-location: changes the default install location.");
1572         System.err.println("  NOTE: this is only intended for debugging; using this can cause");
1573         System.err.println("  applications to break and other undersireable behavior.");
1574         System.err.println("    0 [auto]: Let system decide the best location");
1575         System.err.println("    1 [internal]: Install on internal device storage");
1576         System.err.println("    2 [external]: Install on external media");
1577         System.err.println("");
1578         System.err.println("pm trim-caches: trim cache files to reach the given free space.");
1579         System.err.println("");
1580         System.err.println("pm create-user: create a new user with the given USER_NAME,");
1581         System.err.println("  printing the new user identifier of the user.");
1582         System.err.println("");
1583         System.err.println("pm remove-user: remove the user with the given USER_IDENTIFIER,");
1584         System.err.println("  deleting all data associated with that user");
1585         System.err.println("");
1586         return 1;
1587     }
1588 }
1589