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
17package com.android.commands.pm;
18
19import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
20import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
21import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
22import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
23import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
24
25import android.accounts.IAccountManager;
26import android.app.ActivityManager;
27import android.app.ActivityManagerNative;
28import android.app.PackageInstallObserver;
29import android.content.ComponentName;
30import android.content.Context;
31import android.content.IIntentReceiver;
32import android.content.IIntentSender;
33import android.content.Intent;
34import android.content.IntentSender;
35import android.content.pm.ApplicationInfo;
36import android.content.pm.IPackageDataObserver;
37import android.content.pm.IPackageInstaller;
38import android.content.pm.IPackageManager;
39import android.content.pm.PackageInfo;
40import android.content.pm.PackageInstaller;
41import android.content.pm.PackageInstaller.SessionInfo;
42import android.content.pm.PackageInstaller.SessionParams;
43import android.content.pm.PackageManager;
44import android.content.pm.UserInfo;
45import android.net.Uri;
46import android.os.Binder;
47import android.os.Build;
48import android.os.Bundle;
49import android.os.Handler;
50import android.os.HandlerThread;
51import android.os.IUserManager;
52import android.os.RemoteException;
53import android.os.ResultReceiver;
54import android.os.ServiceManager;
55import android.os.SystemClock;
56import android.os.UserHandle;
57import android.os.UserManager;
58import android.text.TextUtils;
59import android.text.format.DateUtils;
60import android.util.Log;
61
62import com.android.internal.content.PackageHelper;
63import com.android.internal.util.ArrayUtils;
64import com.android.internal.util.SizedInputStream;
65
66import libcore.io.IoUtils;
67
68import java.io.File;
69import java.io.FileDescriptor;
70import java.io.FileInputStream;
71import java.io.IOException;
72import java.io.InputStream;
73import java.io.OutputStream;
74import java.util.concurrent.SynchronousQueue;
75import java.util.concurrent.TimeUnit;
76
77public 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
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
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
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
318        public IntentSender getIntentSender() {
319            return new IntentSender((IIntentSender) mLocalSender);
320        }
321
322        public Intent getResult() {
323            try {
324                return mResult.take();
325            } catch (InterruptedException e) {
326                throw new RuntimeException(e);
327            }
328        }
329    }
330
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
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     */
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
392    private int runInstallAbandon() throws RemoteException {
393        final int sessionId = Integer.parseInt(nextArg());
394        return doAbandonSession(sessionId, true /*logSuccess*/);
395    }
396
397    private int runInstallCommit() throws RemoteException {
398        final int sessionId = Integer.parseInt(nextArg());
399        return doCommitSession(sessionId, true /*logSuccess*/);
400    }
401
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
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
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
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
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
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
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     */
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
643    private int runUninstall() {
644        return runShellCommand("package", mArgs);
645    }
646
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
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
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}
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
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
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
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
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
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
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 {
926                System.err.println("Error: unknown option " + opt);
927                return showUsage();
928            }
929        }
930        String arg = nextArg();
931        if (arg == null) {
932            System.err.println("Error: no user name specified.");
933            return 1;
934        }
935        name = arg;
936        try {
937            UserInfo info;
938            if ((flags & UserInfo.FLAG_RESTRICTED) != 0) {
939                // In non-split user mode, userId can only be SYSTEM
940                int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
941                info = mUm.createRestrictedProfile(name, parentUserId);
942                mAm.addSharedAccountsFromParentUser(parentUserId, userId);
943            } else if (userId < 0) {
944                info = mUm.createUser(name, flags);
945            } else {
946                info = mUm.createProfileForUser(name, flags, userId);
947            }
948
949            if (info != null) {
950                System.out.println("Success: created user id " + info.id);
951                return 1;
952            } else {
953                System.err.println("Error: couldn't create User.");
954                return 1;
955            }
956        } catch (RemoteException e) {
957            System.err.println(e.toString());
958            System.err.println(PM_NOT_RUNNING_ERR);
959            return 1;
960        }
961    }
962
963    public int runRemoveUser() {
964        int userId;
965        String arg = nextArg();
966        if (arg == null) {
967            System.err.println("Error: no user id specified.");
968            return 1;
969        }
970        try {
971            userId = Integer.parseInt(arg);
972        } catch (NumberFormatException e) {
973            System.err.println("Error: user id '" + arg + "' is not a number.");
974            return 1;
975        }
976        try {
977            if (mUm.removeUser(userId)) {
978                System.out.println("Success: removed user");
979                return 0;
980            } else {
981                System.err.println("Error: couldn't remove user id " + userId);
982                return 1;
983            }
984        } catch (RemoteException e) {
985            System.err.println(e.toString());
986            System.err.println(PM_NOT_RUNNING_ERR);
987            return 1;
988        }
989    }
990
991    public int runGetMaxUsers() {
992        System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers());
993        return 0;
994    }
995
996    public int runForceDexOpt() {
997        final String packageName = nextArg();
998        try {
999            mPm.forceDexOpt(packageName);
1000            return 0;
1001        } catch (RemoteException e) {
1002            throw e.rethrowAsRuntimeException();
1003        }
1004    }
1005
1006    public int runMovePackage() {
1007        final String packageName = nextArg();
1008        String volumeUuid = nextArg();
1009        if ("internal".equals(volumeUuid)) {
1010            volumeUuid = null;
1011        }
1012
1013        try {
1014            final int moveId = mPm.movePackage(packageName, volumeUuid);
1015
1016            int status = mPm.getMoveStatus(moveId);
1017            while (!PackageManager.isMoveStatusFinished(status)) {
1018                SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1019                status = mPm.getMoveStatus(moveId);
1020            }
1021
1022            if (status == PackageManager.MOVE_SUCCEEDED) {
1023                System.out.println("Success");
1024                return 0;
1025            } else {
1026                System.err.println("Failure [" + status + "]");
1027                return 1;
1028            }
1029        } catch (RemoteException e) {
1030            throw e.rethrowAsRuntimeException();
1031        }
1032    }
1033
1034    public int runMovePrimaryStorage() {
1035        String volumeUuid = nextArg();
1036        if ("internal".equals(volumeUuid)) {
1037            volumeUuid = null;
1038        }
1039
1040        try {
1041            final int moveId = mPm.movePrimaryStorage(volumeUuid);
1042
1043            int status = mPm.getMoveStatus(moveId);
1044            while (!PackageManager.isMoveStatusFinished(status)) {
1045                SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1046                status = mPm.getMoveStatus(moveId);
1047            }
1048
1049            if (status == PackageManager.MOVE_SUCCEEDED) {
1050                System.out.println("Success");
1051                return 0;
1052            } else {
1053                System.err.println("Failure [" + status + "]");
1054                return 1;
1055            }
1056        } catch (RemoteException e) {
1057            throw e.rethrowAsRuntimeException();
1058        }
1059    }
1060
1061    public int runSetUserRestriction() {
1062        int userId = UserHandle.USER_SYSTEM;
1063        String opt = nextOption();
1064        if (opt != null && "--user".equals(opt)) {
1065            String arg = nextArg();
1066            if (arg == null || !isNumber(arg)) {
1067                System.err.println("Error: valid userId not specified");
1068                return 1;
1069            }
1070            userId = Integer.parseInt(arg);
1071        }
1072
1073        String restriction = nextArg();
1074        String arg = nextArg();
1075        boolean value;
1076        if ("1".equals(arg)) {
1077            value = true;
1078        } else if ("0".equals(arg)) {
1079            value = false;
1080        } else {
1081            System.err.println("Error: valid value not specified");
1082            return 1;
1083        }
1084        try {
1085            mUm.setUserRestriction(restriction, value, userId);
1086            return 0;
1087        } catch (RemoteException e) {
1088            System.err.println(e.toString());
1089            return 1;
1090        }
1091    }
1092
1093    static class ClearDataObserver extends IPackageDataObserver.Stub {
1094        boolean finished;
1095        boolean result;
1096
1097        @Override
1098        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1099            synchronized (this) {
1100                finished = true;
1101                result = succeeded;
1102                notifyAll();
1103            }
1104        }
1105    }
1106
1107    private int runClear() {
1108        int userId = UserHandle.USER_SYSTEM;
1109        String option = nextOption();
1110        if (option != null && option.equals("--user")) {
1111            String optionData = nextOptionData();
1112            if (optionData == null || !isNumber(optionData)) {
1113                System.err.println("Error: no USER_ID specified");
1114                return showUsage();
1115            } else {
1116                userId = Integer.parseInt(optionData);
1117            }
1118        }
1119
1120        String pkg = nextArg();
1121        if (pkg == null) {
1122            System.err.println("Error: no package specified");
1123            return showUsage();
1124        }
1125
1126        ClearDataObserver obs = new ClearDataObserver();
1127        try {
1128            ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, userId);
1129            synchronized (obs) {
1130                while (!obs.finished) {
1131                    try {
1132                        obs.wait();
1133                    } catch (InterruptedException e) {
1134                    }
1135                }
1136            }
1137
1138            if (obs.result) {
1139                System.out.println("Success");
1140                return 0;
1141            } else {
1142                System.err.println("Failed");
1143                return 1;
1144            }
1145        } catch (RemoteException e) {
1146            System.err.println(e.toString());
1147            System.err.println(PM_NOT_RUNNING_ERR);
1148            return 1;
1149        }
1150    }
1151
1152    private static String enabledSettingToString(int state) {
1153        switch (state) {
1154            case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
1155                return "default";
1156            case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
1157                return "enabled";
1158            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
1159                return "disabled";
1160            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
1161                return "disabled-user";
1162            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
1163                return "disabled-until-used";
1164        }
1165        return "unknown";
1166    }
1167
1168    private static boolean isNumber(String s) {
1169        try {
1170            Integer.parseInt(s);
1171        } catch (NumberFormatException nfe) {
1172            return false;
1173        }
1174        return true;
1175    }
1176
1177    private int runSetEnabledSetting(int state) {
1178        int userId = UserHandle.USER_SYSTEM;
1179        String option = nextOption();
1180        if (option != null && option.equals("--user")) {
1181            String optionData = nextOptionData();
1182            if (optionData == null || !isNumber(optionData)) {
1183                System.err.println("Error: no USER_ID specified");
1184                return showUsage();
1185            } else {
1186                userId = Integer.parseInt(optionData);
1187            }
1188        }
1189
1190        String pkg = nextArg();
1191        if (pkg == null) {
1192            System.err.println("Error: no package or component specified");
1193            return showUsage();
1194        }
1195        ComponentName cn = ComponentName.unflattenFromString(pkg);
1196        if (cn == null) {
1197            try {
1198                mPm.setApplicationEnabledSetting(pkg, state, 0, userId,
1199                        "shell:" + android.os.Process.myUid());
1200                System.out.println("Package " + pkg + " new state: "
1201                        + enabledSettingToString(
1202                        mPm.getApplicationEnabledSetting(pkg, userId)));
1203                return 0;
1204            } catch (RemoteException e) {
1205                System.err.println(e.toString());
1206                System.err.println(PM_NOT_RUNNING_ERR);
1207                return 1;
1208            }
1209        } else {
1210            try {
1211                mPm.setComponentEnabledSetting(cn, state, 0, userId);
1212                System.out.println("Component " + cn.toShortString() + " new state: "
1213                        + enabledSettingToString(
1214                        mPm.getComponentEnabledSetting(cn, userId)));
1215                return 0;
1216            } catch (RemoteException e) {
1217                System.err.println(e.toString());
1218                System.err.println(PM_NOT_RUNNING_ERR);
1219                return 1;
1220            }
1221        }
1222    }
1223
1224    private int runSetHiddenSetting(boolean state) {
1225        int userId = UserHandle.USER_SYSTEM;
1226        String option = nextOption();
1227        if (option != null && option.equals("--user")) {
1228            String optionData = nextOptionData();
1229            if (optionData == null || !isNumber(optionData)) {
1230                System.err.println("Error: no USER_ID specified");
1231                return showUsage();
1232            } else {
1233                userId = Integer.parseInt(optionData);
1234            }
1235        }
1236
1237        String pkg = nextArg();
1238        if (pkg == null) {
1239            System.err.println("Error: no package or component specified");
1240            return showUsage();
1241        }
1242        try {
1243            mPm.setApplicationHiddenSettingAsUser(pkg, state, userId);
1244            System.out.println("Package " + pkg + " new hidden state: "
1245                    + mPm.getApplicationHiddenSettingAsUser(pkg, userId));
1246            return 0;
1247        } catch (RemoteException e) {
1248            System.err.println(e.toString());
1249            System.err.println(PM_NOT_RUNNING_ERR);
1250            return 1;
1251        }
1252    }
1253
1254    private int runGrantRevokePermission(boolean grant) {
1255        int userId = UserHandle.USER_SYSTEM;
1256
1257        String opt = null;
1258        while ((opt = nextOption()) != null) {
1259            if (opt.equals("--user")) {
1260                userId = Integer.parseInt(nextArg());
1261            }
1262        }
1263
1264        String pkg = nextArg();
1265        if (pkg == null) {
1266            System.err.println("Error: no package specified");
1267            return showUsage();
1268        }
1269        String perm = nextArg();
1270        if (perm == null) {
1271            System.err.println("Error: no permission specified");
1272            return showUsage();
1273        }
1274
1275        try {
1276            if (grant) {
1277                mPm.grantRuntimePermission(pkg, perm, userId);
1278            } else {
1279                mPm.revokeRuntimePermission(pkg, perm, userId);
1280            }
1281            return 0;
1282        } catch (RemoteException e) {
1283            System.err.println(e.toString());
1284            System.err.println(PM_NOT_RUNNING_ERR);
1285            return 1;
1286        } catch (IllegalArgumentException e) {
1287            System.err.println("Bad argument: " + e.toString());
1288            return showUsage();
1289        } catch (SecurityException e) {
1290            System.err.println("Operation not allowed: " + e.toString());
1291            return 1;
1292        }
1293    }
1294
1295    private int runResetPermissions() {
1296        try {
1297            mPm.resetRuntimePermissions();
1298            return 0;
1299        } catch (RemoteException e) {
1300            System.err.println(e.toString());
1301            System.err.println(PM_NOT_RUNNING_ERR);
1302            return 1;
1303        } catch (IllegalArgumentException e) {
1304            System.err.println("Bad argument: " + e.toString());
1305            return showUsage();
1306        } catch (SecurityException e) {
1307            System.err.println("Operation not allowed: " + e.toString());
1308            return 1;
1309        }
1310    }
1311
1312    private int runSetPermissionEnforced() {
1313        final String permission = nextArg();
1314        if (permission == null) {
1315            System.err.println("Error: no permission specified");
1316            return showUsage();
1317        }
1318        final String enforcedRaw = nextArg();
1319        if (enforcedRaw == null) {
1320            System.err.println("Error: no enforcement specified");
1321            return showUsage();
1322        }
1323        final boolean enforced = Boolean.parseBoolean(enforcedRaw);
1324        try {
1325            mPm.setPermissionEnforced(permission, enforced);
1326            return 0;
1327        } catch (RemoteException e) {
1328            System.err.println(e.toString());
1329            System.err.println(PM_NOT_RUNNING_ERR);
1330            return 1;
1331        } catch (IllegalArgumentException e) {
1332            System.err.println("Bad argument: " + e.toString());
1333            return showUsage();
1334        } catch (SecurityException e) {
1335            System.err.println("Operation not allowed: " + e.toString());
1336            return 1;
1337        }
1338    }
1339
1340    static class ClearCacheObserver extends IPackageDataObserver.Stub {
1341        boolean finished;
1342        boolean result;
1343
1344        @Override
1345        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1346            synchronized (this) {
1347                finished = true;
1348                result = succeeded;
1349                notifyAll();
1350            }
1351        }
1352
1353    }
1354
1355    private int runTrimCaches() {
1356        String size = nextArg();
1357        if (size == null) {
1358            System.err.println("Error: no size specified");
1359            return showUsage();
1360        }
1361        int len = size.length();
1362        long multiplier = 1;
1363        if (len > 1) {
1364            char c = size.charAt(len-1);
1365            if (c == 'K' || c == 'k') {
1366                multiplier = 1024L;
1367            } else if (c == 'M' || c == 'm') {
1368                multiplier = 1024L*1024L;
1369            } else if (c == 'G' || c == 'g') {
1370                multiplier = 1024L*1024L*1024L;
1371            } else {
1372                System.err.println("Invalid suffix: " + c);
1373                return showUsage();
1374            }
1375            size = size.substring(0, len-1);
1376        }
1377        long sizeVal;
1378        try {
1379            sizeVal = Long.parseLong(size) * multiplier;
1380        } catch (NumberFormatException e) {
1381            System.err.println("Error: expected number at: " + size);
1382            return showUsage();
1383        }
1384        String volumeUuid = nextArg();
1385        if ("internal".equals(volumeUuid)) {
1386            volumeUuid = null;
1387        }
1388        ClearDataObserver obs = new ClearDataObserver();
1389        try {
1390            mPm.freeStorageAndNotify(volumeUuid, sizeVal, obs);
1391            synchronized (obs) {
1392                while (!obs.finished) {
1393                    try {
1394                        obs.wait();
1395                    } catch (InterruptedException e) {
1396                    }
1397                }
1398            }
1399            return 0;
1400        } catch (RemoteException e) {
1401            System.err.println(e.toString());
1402            System.err.println(PM_NOT_RUNNING_ERR);
1403            return 1;
1404        } catch (IllegalArgumentException e) {
1405            System.err.println("Bad argument: " + e.toString());
1406            return showUsage();
1407        } catch (SecurityException e) {
1408            System.err.println("Operation not allowed: " + e.toString());
1409            return 1;
1410        }
1411    }
1412
1413    /**
1414     * Displays the package file for a package.
1415     * @param pckg
1416     */
1417    private int displayPackageFilePath(String pckg, int userId) {
1418        try {
1419            PackageInfo info = mPm.getPackageInfo(pckg, 0, userId);
1420            if (info != null && info.applicationInfo != null) {
1421                System.out.print("package:");
1422                System.out.println(info.applicationInfo.sourceDir);
1423                if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
1424                    for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
1425                        System.out.print("package:");
1426                        System.out.println(splitSourceDir);
1427                    }
1428                }
1429                return 0;
1430            }
1431        } catch (RemoteException e) {
1432            System.err.println(e.toString());
1433            System.err.println(PM_NOT_RUNNING_ERR);
1434        }
1435        return 1;
1436    }
1437
1438    private String nextOption() {
1439        if (mNextArg >= mArgs.length) {
1440            return null;
1441        }
1442        String arg = mArgs[mNextArg];
1443        if (!arg.startsWith("-")) {
1444            return null;
1445        }
1446        mNextArg++;
1447        if (arg.equals("--")) {
1448            return null;
1449        }
1450        if (arg.length() > 1 && arg.charAt(1) != '-') {
1451            if (arg.length() > 2) {
1452                mCurArgData = arg.substring(2);
1453                return arg.substring(0, 2);
1454            } else {
1455                mCurArgData = null;
1456                return arg;
1457            }
1458        }
1459        mCurArgData = null;
1460        return arg;
1461    }
1462
1463    private String nextOptionData() {
1464        if (mCurArgData != null) {
1465            return mCurArgData;
1466        }
1467        if (mNextArg >= mArgs.length) {
1468            return null;
1469        }
1470        String data = mArgs[mNextArg];
1471        mNextArg++;
1472        return data;
1473    }
1474
1475    private String nextArg() {
1476        if (mNextArg >= mArgs.length) {
1477            return null;
1478        }
1479        String arg = mArgs[mNextArg];
1480        mNextArg++;
1481        return arg;
1482    }
1483
1484    private static int showUsage() {
1485        System.err.println("usage: pm path [--user USER_ID] PACKAGE");
1486        System.err.println("       pm dump PACKAGE");
1487        System.err.println("       pm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH]");
1488        System.err.println("       pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]");
1489        System.err.println("               [--install-location 0/1/2]");
1490        System.err.println("               [--force-uuid internal|UUID]");
1491        System.err.println("       pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]");
1492        System.err.println("       pm install-commit SESSION_ID");
1493        System.err.println("       pm install-abandon SESSION_ID");
1494        System.err.println("       pm uninstall [-k] [--user USER_ID] PACKAGE");
1495        System.err.println("       pm set-installer PACKAGE INSTALLER");
1496        System.err.println("       pm move-package PACKAGE [internal|UUID]");
1497        System.err.println("       pm move-primary-storage [internal|UUID]");
1498        System.err.println("       pm clear [--user USER_ID] PACKAGE");
1499        System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
1500        System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
1501        System.err.println("       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
1502        System.err.println("       pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
1503        System.err.println("       pm default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
1504        System.err.println("       pm hide [--user USER_ID] PACKAGE_OR_COMPONENT");
1505        System.err.println("       pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
1506        System.err.println("       pm grant [--user USER_ID] PACKAGE PERMISSION");
1507        System.err.println("       pm revoke [--user USER_ID] PACKAGE PERMISSION");
1508        System.err.println("       pm reset-permissions");
1509        System.err.println("       pm set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
1510        System.err.println("       pm get-app-link [--user USER_ID] PACKAGE");
1511        System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
1512        System.err.println("       pm get-install-location");
1513        System.err.println("       pm set-permission-enforced PERMISSION [true|false]");
1514        System.err.println("       pm trim-caches DESIRED_FREE_SPACE [internal|UUID]");
1515        System.err.println("       pm create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral] [--guest] USER_NAME");
1516        System.err.println("       pm remove-user USER_ID");
1517        System.err.println("       pm get-max-users");
1518        System.err.println("");
1519        System.err.println("NOTE: 'pm list' commands have moved! Run 'adb shell cmd package'");
1520        System.err.println("  to display the new commands.");
1521        System.err.println("");
1522        System.err.println("pm path: print the path to the .apk of the given PACKAGE.");
1523        System.err.println("");
1524        System.err.println("pm dump: print system state associated with the given PACKAGE.");
1525        System.err.println("");
1526        System.err.println("pm install: install a single legacy package");
1527        System.err.println("pm install-create: create an install session");
1528        System.err.println("    -l: forward lock application");
1529        System.err.println("    -r: replace existing application");
1530        System.err.println("    -t: allow test packages");
1531        System.err.println("    -i: specify the installer package name");
1532        System.err.println("    -s: install application on sdcard");
1533        System.err.println("    -f: install application on internal flash");
1534        System.err.println("    -d: allow version code downgrade (debuggable packages only)");
1535        System.err.println("    -p: partial application install");
1536        System.err.println("    -g: grant all runtime permissions");
1537        System.err.println("    -S: size in bytes of entire session");
1538        System.err.println("");
1539        System.err.println("pm install-write: write a package into existing session; path may");
1540        System.err.println("  be '-' to read from stdin");
1541        System.err.println("    -S: size in bytes of package, required for stdin");
1542        System.err.println("");
1543        System.err.println("pm install-commit: perform install of fully staged session");
1544        System.err.println("pm install-abandon: abandon session");
1545        System.err.println("");
1546        System.err.println("pm set-installer: set installer package name");
1547        System.err.println("");
1548        System.err.println("pm uninstall: removes a package from the system. Options:");
1549        System.err.println("    -k: keep the data and cache directories around after package removal.");
1550        System.err.println("");
1551        System.err.println("pm clear: deletes all data associated with a package.");
1552        System.err.println("");
1553        System.err.println("pm enable, disable, disable-user, disable-until-used, default-state:");
1554        System.err.println("  these commands change the enabled state of a given package or");
1555        System.err.println("  component (written as \"package/class\").");
1556        System.err.println("");
1557        System.err.println("pm grant, revoke: these commands either grant or revoke permissions");
1558        System.err.println("    to apps. The permissions must be declared as used in the app's");
1559        System.err.println("    manifest, be runtime permissions (protection level dangerous),");
1560        System.err.println("    and the app targeting SDK greater than Lollipop MR1.");
1561        System.err.println("");
1562        System.err.println("pm reset-permissions: revert all runtime permissions to their default state.");
1563        System.err.println("");
1564        System.err.println("pm get-install-location: returns the current install location.");
1565        System.err.println("    0 [auto]: Let system decide the best location");
1566        System.err.println("    1 [internal]: Install on internal device storage");
1567        System.err.println("    2 [external]: Install on external media");
1568        System.err.println("");
1569        System.err.println("pm set-install-location: changes the default install location.");
1570        System.err.println("  NOTE: this is only intended for debugging; using this can cause");
1571        System.err.println("  applications to break and other undersireable behavior.");
1572        System.err.println("    0 [auto]: Let system decide the best location");
1573        System.err.println("    1 [internal]: Install on internal device storage");
1574        System.err.println("    2 [external]: Install on external media");
1575        System.err.println("");
1576        System.err.println("pm trim-caches: trim cache files to reach the given free space.");
1577        System.err.println("");
1578        System.err.println("pm create-user: create a new user with the given USER_NAME,");
1579        System.err.println("  printing the new user identifier of the user.");
1580        System.err.println("");
1581        System.err.println("pm remove-user: remove the user with the given USER_IDENTIFIER,");
1582        System.err.println("  deleting all data associated with that user");
1583        System.err.println("");
1584        return 1;
1585    }
1586}
1587