Pm.java revision a3e9ff7debde50f6b58ebc3033cbbad650c10ac7
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 com.android.internal.content.PackageHelper;
20
21import android.app.ActivityManagerNative;
22import android.content.ComponentName;
23import android.content.pm.ApplicationInfo;
24import android.content.pm.ContainerEncryptionParams;
25import android.content.pm.FeatureInfo;
26import android.content.pm.IPackageDataObserver;
27import android.content.pm.IPackageDeleteObserver;
28import android.content.pm.IPackageInstallObserver;
29import android.content.pm.IPackageManager;
30import android.content.pm.InstrumentationInfo;
31import android.content.pm.PackageInfo;
32import android.content.pm.PackageItemInfo;
33import android.content.pm.PackageManager;
34import android.content.pm.ParceledListSlice;
35import android.content.pm.PermissionGroupInfo;
36import android.content.pm.PermissionInfo;
37import android.content.pm.UserInfo;
38import android.content.pm.VerificationParams;
39import android.content.res.AssetManager;
40import android.content.res.Resources;
41import android.net.Uri;
42import android.os.IUserManager;
43import android.os.RemoteException;
44import android.os.ServiceManager;
45import android.os.UserHandle;
46import android.os.UserManager;
47
48import java.io.File;
49import java.lang.reflect.Field;
50import java.lang.reflect.Modifier;
51import java.security.InvalidAlgorithmParameterException;
52import java.util.ArrayList;
53import java.util.Collections;
54import java.util.Comparator;
55import java.util.List;
56import java.util.WeakHashMap;
57
58import javax.crypto.SecretKey;
59import javax.crypto.spec.IvParameterSpec;
60import javax.crypto.spec.SecretKeySpec;
61
62public final class Pm {
63    IPackageManager mPm;
64    IUserManager mUm;
65
66    private WeakHashMap<String, Resources> mResourceCache
67            = new WeakHashMap<String, Resources>();
68
69    private String[] mArgs;
70    private int mNextArg;
71    private String mCurArgData;
72
73    private static final String PM_NOT_RUNNING_ERR =
74        "Error: Could not access the Package Manager.  Is the system running?";
75
76    public static void main(String[] args) {
77        new Pm().run(args);
78    }
79
80    public void run(String[] args) {
81        boolean validCommand = false;
82        if (args.length < 1) {
83            showUsage();
84            return;
85        }
86
87        mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user"));
88        mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
89        if (mPm == null) {
90            System.err.println(PM_NOT_RUNNING_ERR);
91            return;
92        }
93
94        mArgs = args;
95        String op = args[0];
96        mNextArg = 1;
97
98        if ("list".equals(op)) {
99            runList();
100            return;
101        }
102
103        if ("path".equals(op)) {
104            runPath();
105            return;
106        }
107
108        if ("install".equals(op)) {
109            runInstall();
110            return;
111        }
112
113        if ("uninstall".equals(op)) {
114            runUninstall();
115            return;
116        }
117
118        if ("clear".equals(op)) {
119            runClear();
120            return;
121        }
122
123        if ("enable".equals(op)) {
124            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
125            return;
126        }
127
128        if ("disable".equals(op)) {
129            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
130            return;
131        }
132
133        if ("disable-user".equals(op)) {
134            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
135            return;
136        }
137
138        if ("grant".equals(op)) {
139            runGrantRevokePermission(true);
140            return;
141        }
142
143        if ("revoke".equals(op)) {
144            runGrantRevokePermission(false);
145            return;
146        }
147
148        if ("set-permission-enforced".equals(op)) {
149            runSetPermissionEnforced();
150            return;
151        }
152
153        if ("set-install-location".equals(op)) {
154            runSetInstallLocation();
155            return;
156        }
157
158        if ("get-install-location".equals(op)) {
159            runGetInstallLocation();
160            return;
161        }
162
163        if ("trim-caches".equals(op)) {
164            runTrimCaches();
165            return;
166        }
167
168        if ("create-user".equals(op)) {
169            runCreateUser();
170            return;
171        }
172
173        if ("remove-user".equals(op)) {
174            runRemoveUser();
175            return;
176        }
177
178        if ("get-max-users".equals(op)) {
179            runGetMaxUsers();
180            return;
181        }
182
183        try {
184            if (args.length == 1) {
185                if (args[0].equalsIgnoreCase("-l")) {
186                    validCommand = true;
187                    runListPackages(false);
188                } else if (args[0].equalsIgnoreCase("-lf")){
189                    validCommand = true;
190                    runListPackages(true);
191                }
192            } else if (args.length == 2) {
193                if (args[0].equalsIgnoreCase("-p")) {
194                    validCommand = true;
195                    displayPackageFilePath(args[1]);
196                }
197            }
198        } finally {
199            if (validCommand == false) {
200                if (op != null) {
201                    System.err.println("Error: unknown command '" + op + "'");
202                }
203                showUsage();
204            }
205        }
206    }
207
208    /**
209     * Execute the list sub-command.
210     *
211     * pm list [package | packages]
212     * pm list permission-groups
213     * pm list permissions
214     * pm list features
215     * pm list libraries
216     * pm list instrumentation
217     */
218    private void runList() {
219        String type = nextArg();
220        if (type == null) {
221            System.err.println("Error: didn't specify type of data to list");
222            return;
223        }
224        if ("package".equals(type) || "packages".equals(type)) {
225            runListPackages(false);
226        } else if ("permission-groups".equals(type)) {
227            runListPermissionGroups();
228        } else if ("permissions".equals(type)) {
229            runListPermissions();
230        } else if ("features".equals(type)) {
231            runListFeatures();
232        } else if ("libraries".equals(type)) {
233            runListLibraries();
234        } else if ("instrumentation".equals(type)) {
235            runListInstrumentation();
236        } else if ("users".equals(type)) {
237            runListUsers();
238        } else {
239            System.err.println("Error: unknown list type '" + type + "'");
240        }
241    }
242
243    /**
244     * Lists all the installed packages.
245     */
246    private void runListPackages(boolean showApplicationPackage) {
247        int getFlags = 0;
248        boolean listDisabled = false, listEnabled = false;
249        boolean listSystem = false, listThirdParty = false;
250        boolean listInstaller = false;
251        int userId = UserHandle.USER_OWNER;
252        try {
253            String opt;
254            while ((opt=nextOption()) != null) {
255                if (opt.equals("-l")) {
256                    // old compat
257                } else if (opt.equals("-lf")) {
258                    showApplicationPackage = true;
259                } else if (opt.equals("-f")) {
260                    showApplicationPackage = true;
261                } else if (opt.equals("-d")) {
262                    listDisabled = true;
263                } else if (opt.equals("-e")) {
264                    listEnabled = true;
265                } else if (opt.equals("-s")) {
266                    listSystem = true;
267                } else if (opt.equals("-3")) {
268                    listThirdParty = true;
269                } else if (opt.equals("-i")) {
270                    listInstaller = true;
271                } else if (opt.equals("--user")) {
272                    userId = Integer.parseInt(nextArg());
273                } else if (opt.equals("-u")) {
274                    getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
275                } else {
276                    System.err.println("Error: Unknown option: " + opt);
277                    return;
278                }
279            }
280        } catch (RuntimeException ex) {
281            System.err.println("Error: " + ex.toString());
282            return;
283        }
284
285        String filter = nextArg();
286
287        try {
288            final List<PackageInfo> packages = getInstalledPackages(mPm, getFlags, userId);
289
290            int count = packages.size();
291            for (int p = 0 ; p < count ; p++) {
292                PackageInfo info = packages.get(p);
293                if (filter != null && !info.packageName.contains(filter)) {
294                    continue;
295                }
296                final boolean isSystem =
297                        (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
298                if ((!listDisabled || !info.applicationInfo.enabled) &&
299                        (!listEnabled || info.applicationInfo.enabled) &&
300                        (!listSystem || isSystem) &&
301                        (!listThirdParty || !isSystem)) {
302                    System.out.print("package:");
303                    if (showApplicationPackage) {
304                        System.out.print(info.applicationInfo.sourceDir);
305                        System.out.print("=");
306                    }
307                    System.out.print(info.packageName);
308                    if (listInstaller) {
309                        System.out.print("  installer=");
310                        System.out.print(mPm.getInstallerPackageName(info.packageName));
311                    }
312                    System.out.println();
313                }
314            }
315        } catch (RemoteException e) {
316            System.err.println(e.toString());
317            System.err.println(PM_NOT_RUNNING_ERR);
318        }
319    }
320
321    @SuppressWarnings("unchecked")
322    private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags, int userId)
323            throws RemoteException {
324        final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
325        PackageInfo lastItem = null;
326        ParceledListSlice<PackageInfo> slice;
327
328        do {
329            final String lastKey = lastItem != null ? lastItem.packageName : null;
330            slice = pm.getInstalledPackages(flags, lastKey, userId);
331            lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
332        } while (!slice.isLastSlice());
333
334        return packageInfos;
335    }
336
337    /**
338     * Lists all of the features supported by the current device.
339     *
340     * pm list features
341     */
342    private void runListFeatures() {
343        try {
344            List<FeatureInfo> list = new ArrayList<FeatureInfo>();
345            FeatureInfo[] rawList = mPm.getSystemAvailableFeatures();
346            for (int i=0; i<rawList.length; i++) {
347                list.add(rawList[i]);
348            }
349
350
351            // Sort by name
352            Collections.sort(list, new Comparator<FeatureInfo>() {
353                public int compare(FeatureInfo o1, FeatureInfo o2) {
354                    if (o1.name == o2.name) return 0;
355                    if (o1.name == null) return -1;
356                    if (o2.name == null) return 1;
357                    return o1.name.compareTo(o2.name);
358                }
359            });
360
361            int count = (list != null) ? list.size() : 0;
362            for (int p = 0; p < count; p++) {
363                FeatureInfo fi = list.get(p);
364                System.out.print("feature:");
365                if (fi.name != null) System.out.println(fi.name);
366                else System.out.println("reqGlEsVersion=0x"
367                        + Integer.toHexString(fi.reqGlEsVersion));
368            }
369        } catch (RemoteException e) {
370            System.err.println(e.toString());
371            System.err.println(PM_NOT_RUNNING_ERR);
372        }
373    }
374
375    /**
376     * Lists all of the libraries supported by the current device.
377     *
378     * pm list libraries
379     */
380    private void runListLibraries() {
381        try {
382            List<String> list = new ArrayList<String>();
383            String[] rawList = mPm.getSystemSharedLibraryNames();
384            for (int i=0; i<rawList.length; i++) {
385                list.add(rawList[i]);
386            }
387
388
389            // Sort by name
390            Collections.sort(list, new Comparator<String>() {
391                public int compare(String o1, String o2) {
392                    if (o1 == o2) return 0;
393                    if (o1 == null) return -1;
394                    if (o2 == null) return 1;
395                    return o1.compareTo(o2);
396                }
397            });
398
399            int count = (list != null) ? list.size() : 0;
400            for (int p = 0; p < count; p++) {
401                String lib = list.get(p);
402                System.out.print("library:");
403                System.out.println(lib);
404            }
405        } catch (RemoteException e) {
406            System.err.println(e.toString());
407            System.err.println(PM_NOT_RUNNING_ERR);
408        }
409    }
410
411    /**
412     * Lists all of the installed instrumentation, or all for a given package
413     *
414     * pm list instrumentation [package] [-f]
415     */
416    private void runListInstrumentation() {
417        int flags = 0;      // flags != 0 is only used to request meta-data
418        boolean showPackage = false;
419        String targetPackage = null;
420
421        try {
422            String opt;
423            while ((opt=nextArg()) != null) {
424                if (opt.equals("-f")) {
425                    showPackage = true;
426                } else if (opt.charAt(0) != '-') {
427                    targetPackage = opt;
428                } else {
429                    System.err.println("Error: Unknown option: " + opt);
430                    return;
431                }
432            }
433        } catch (RuntimeException ex) {
434            System.err.println("Error: " + ex.toString());
435            return;
436        }
437
438        try {
439            List<InstrumentationInfo> list = mPm.queryInstrumentation(targetPackage, flags);
440
441            // Sort by target package
442            Collections.sort(list, new Comparator<InstrumentationInfo>() {
443                public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
444                    return o1.targetPackage.compareTo(o2.targetPackage);
445                }
446            });
447
448            int count = (list != null) ? list.size() : 0;
449            for (int p = 0; p < count; p++) {
450                InstrumentationInfo ii = list.get(p);
451                System.out.print("instrumentation:");
452                if (showPackage) {
453                    System.out.print(ii.sourceDir);
454                    System.out.print("=");
455                }
456                ComponentName cn = new ComponentName(ii.packageName, ii.name);
457                System.out.print(cn.flattenToShortString());
458                System.out.print(" (target=");
459                System.out.print(ii.targetPackage);
460                System.out.println(")");
461            }
462        } catch (RemoteException e) {
463            System.err.println(e.toString());
464            System.err.println(PM_NOT_RUNNING_ERR);
465        }
466    }
467
468    /**
469     * Lists all the known permission groups.
470     */
471    private void runListPermissionGroups() {
472        try {
473            List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0);
474
475            int count = pgs.size();
476            for (int p = 0 ; p < count ; p++) {
477                PermissionGroupInfo pgi = pgs.get(p);
478                System.out.print("permission group:");
479                System.out.println(pgi.name);
480            }
481        } catch (RemoteException e) {
482            System.err.println(e.toString());
483            System.err.println(PM_NOT_RUNNING_ERR);
484        }
485    }
486
487    private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) {
488        if (nonLocalized != null) {
489            return nonLocalized.toString();
490        }
491        if (res != 0) {
492            Resources r = getResources(pii);
493            if (r != null) {
494                return r.getString(res);
495            }
496        }
497        return null;
498    }
499
500    /**
501     * Lists all the permissions in a group.
502     */
503    private void runListPermissions() {
504        try {
505            boolean labels = false;
506            boolean groups = false;
507            boolean userOnly = false;
508            boolean summary = false;
509            boolean dangerousOnly = false;
510            String opt;
511            while ((opt=nextOption()) != null) {
512                if (opt.equals("-f")) {
513                    labels = true;
514                } else if (opt.equals("-g")) {
515                    groups = true;
516                } else if (opt.equals("-s")) {
517                    groups = true;
518                    labels = true;
519                    summary = true;
520                } else if (opt.equals("-u")) {
521                    userOnly = true;
522                } else if (opt.equals("-d")) {
523                    dangerousOnly = true;
524                } else {
525                    System.err.println("Error: Unknown option: " + opt);
526                    return;
527                }
528            }
529
530            String grp = nextOption();
531            ArrayList<String> groupList = new ArrayList<String>();
532            if (groups) {
533                List<PermissionGroupInfo> infos =
534                        mPm.getAllPermissionGroups(0);
535                for (int i=0; i<infos.size(); i++) {
536                    groupList.add(infos.get(i).name);
537                }
538                groupList.add(null);
539            } else {
540                groupList.add(grp);
541            }
542
543            if (dangerousOnly) {
544                System.out.println("Dangerous Permissions:");
545                System.out.println("");
546                doListPermissions(groupList, groups, labels, summary,
547                        PermissionInfo.PROTECTION_DANGEROUS,
548                        PermissionInfo.PROTECTION_DANGEROUS);
549                if (userOnly) {
550                    System.out.println("Normal Permissions:");
551                    System.out.println("");
552                    doListPermissions(groupList, groups, labels, summary,
553                            PermissionInfo.PROTECTION_NORMAL,
554                            PermissionInfo.PROTECTION_NORMAL);
555                }
556            } else if (userOnly) {
557                System.out.println("Dangerous and Normal Permissions:");
558                System.out.println("");
559                doListPermissions(groupList, groups, labels, summary,
560                        PermissionInfo.PROTECTION_NORMAL,
561                        PermissionInfo.PROTECTION_DANGEROUS);
562            } else {
563                System.out.println("All Permissions:");
564                System.out.println("");
565                doListPermissions(groupList, groups, labels, summary,
566                        -10000, 10000);
567            }
568        } catch (RemoteException e) {
569            System.err.println(e.toString());
570            System.err.println(PM_NOT_RUNNING_ERR);
571        }
572    }
573
574    private void doListPermissions(ArrayList<String> groupList,
575            boolean groups, boolean labels, boolean summary,
576            int startProtectionLevel, int endProtectionLevel)
577            throws RemoteException {
578        for (int i=0; i<groupList.size(); i++) {
579            String groupName = groupList.get(i);
580            String prefix = "";
581            if (groups) {
582                if (i > 0) System.out.println("");
583                if (groupName != null) {
584                    PermissionGroupInfo pgi = mPm.getPermissionGroupInfo(
585                            groupName, 0);
586                    if (summary) {
587                        Resources res = getResources(pgi);
588                        if (res != null) {
589                            System.out.print(loadText(pgi, pgi.labelRes,
590                                    pgi.nonLocalizedLabel) + ": ");
591                        } else {
592                            System.out.print(pgi.name + ": ");
593
594                        }
595                    } else {
596                        System.out.println((labels ? "+ " : "")
597                                + "group:" + pgi.name);
598                        if (labels) {
599                            System.out.println("  package:" + pgi.packageName);
600                            Resources res = getResources(pgi);
601                            if (res != null) {
602                                System.out.println("  label:"
603                                        + loadText(pgi, pgi.labelRes,
604                                                pgi.nonLocalizedLabel));
605                                System.out.println("  description:"
606                                        + loadText(pgi, pgi.descriptionRes,
607                                                pgi.nonLocalizedDescription));
608                            }
609                        }
610                    }
611                } else {
612                    System.out.println(((labels && !summary)
613                            ? "+ " : "") + "ungrouped:");
614                }
615                prefix = "  ";
616            }
617            List<PermissionInfo> ps = mPm.queryPermissionsByGroup(
618                    groupList.get(i), 0);
619            int count = ps.size();
620            boolean first = true;
621            for (int p = 0 ; p < count ; p++) {
622                PermissionInfo pi = ps.get(p);
623                if (groups && groupName == null && pi.group != null) {
624                    continue;
625                }
626                final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
627                if (base < startProtectionLevel
628                        || base > endProtectionLevel) {
629                    continue;
630                }
631                if (summary) {
632                    if (first) {
633                        first = false;
634                    } else {
635                        System.out.print(", ");
636                    }
637                    Resources res = getResources(pi);
638                    if (res != null) {
639                        System.out.print(loadText(pi, pi.labelRes,
640                                pi.nonLocalizedLabel));
641                    } else {
642                        System.out.print(pi.name);
643                    }
644                } else {
645                    System.out.println(prefix + (labels ? "+ " : "")
646                            + "permission:" + pi.name);
647                    if (labels) {
648                        System.out.println(prefix + "  package:" + pi.packageName);
649                        Resources res = getResources(pi);
650                        if (res != null) {
651                            System.out.println(prefix + "  label:"
652                                    + loadText(pi, pi.labelRes,
653                                            pi.nonLocalizedLabel));
654                            System.out.println(prefix + "  description:"
655                                    + loadText(pi, pi.descriptionRes,
656                                            pi.nonLocalizedDescription));
657                        }
658                        System.out.println(prefix + "  protectionLevel:"
659                                + PermissionInfo.protectionToString(pi.protectionLevel));
660                    }
661                }
662            }
663
664            if (summary) {
665                System.out.println("");
666            }
667        }
668    }
669
670    private void runPath() {
671        String pkg = nextArg();
672        if (pkg == null) {
673            System.err.println("Error: no package specified");
674            return;
675        }
676        displayPackageFilePath(pkg);
677    }
678
679    class PackageInstallObserver extends IPackageInstallObserver.Stub {
680        boolean finished;
681        int result;
682
683        public void packageInstalled(String name, int status) {
684            synchronized( this) {
685                finished = true;
686                result = status;
687                notifyAll();
688            }
689        }
690    }
691
692    /**
693     * Converts a failure code into a string by using reflection to find a matching constant
694     * in PackageManager.
695     */
696    private String installFailureToString(int result) {
697        Field[] fields = PackageManager.class.getFields();
698        for (Field f: fields) {
699            if (f.getType() == int.class) {
700                int modifiers = f.getModifiers();
701                // only look at public final static fields.
702                if (((modifiers & Modifier.FINAL) != 0) &&
703                        ((modifiers & Modifier.PUBLIC) != 0) &&
704                        ((modifiers & Modifier.STATIC) != 0)) {
705                    String fieldName = f.getName();
706                    if (fieldName.startsWith("INSTALL_FAILED_") ||
707                            fieldName.startsWith("INSTALL_PARSE_FAILED_")) {
708                        // get the int value and compare it to result.
709                        try {
710                            if (result == f.getInt(null)) {
711                                return fieldName;
712                            }
713                        } catch (IllegalAccessException e) {
714                            // this shouldn't happen since we only look for public static fields.
715                        }
716                    }
717                }
718            }
719        }
720
721        // couldn't find a matching constant? return the value
722        return Integer.toString(result);
723    }
724
725    private void runSetInstallLocation() {
726        int loc;
727
728        String arg = nextArg();
729        if (arg == null) {
730            System.err.println("Error: no install location specified.");
731            return;
732        }
733        try {
734            loc = Integer.parseInt(arg);
735        } catch (NumberFormatException e) {
736            System.err.println("Error: install location has to be a number.");
737            return;
738        }
739        try {
740            if (!mPm.setInstallLocation(loc)) {
741                System.err.println("Error: install location has to be a number.");
742            }
743        } catch (RemoteException e) {
744            System.err.println(e.toString());
745            System.err.println(PM_NOT_RUNNING_ERR);
746        }
747    }
748
749    private void runGetInstallLocation() {
750        try {
751            int loc = mPm.getInstallLocation();
752            String locStr = "invalid";
753            if (loc == PackageHelper.APP_INSTALL_AUTO) {
754                locStr = "auto";
755            } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
756                locStr = "internal";
757            } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
758                locStr = "external";
759            }
760            System.out.println(loc + "[" + locStr + "]");
761        } catch (RemoteException e) {
762            System.err.println(e.toString());
763            System.err.println(PM_NOT_RUNNING_ERR);
764        }
765    }
766
767    private void runInstall() {
768        int installFlags = PackageManager.INSTALL_ALL_USERS;
769        String installerPackageName = null;
770
771        String opt;
772
773        String algo = null;
774        byte[] iv = null;
775        byte[] key = null;
776
777        String macAlgo = null;
778        byte[] macKey = null;
779        byte[] tag = null;
780        String originatingUriString = null;
781        String referrer = null;
782
783        while ((opt=nextOption()) != null) {
784            if (opt.equals("-l")) {
785                installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
786            } else if (opt.equals("-r")) {
787                installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
788            } else if (opt.equals("-i")) {
789                installerPackageName = nextOptionData();
790                if (installerPackageName == null) {
791                    System.err.println("Error: no value specified for -i");
792                    return;
793                }
794            } else if (opt.equals("-t")) {
795                installFlags |= PackageManager.INSTALL_ALLOW_TEST;
796            } else if (opt.equals("-s")) {
797                // Override if -s option is specified.
798                installFlags |= PackageManager.INSTALL_EXTERNAL;
799            } else if (opt.equals("-f")) {
800                // Override if -s option is specified.
801                installFlags |= PackageManager.INSTALL_INTERNAL;
802            } else if (opt.equals("-d")) {
803                installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
804            } else if (opt.equals("--algo")) {
805                algo = nextOptionData();
806                if (algo == null) {
807                    System.err.println("Error: must supply argument for --algo");
808                    return;
809                }
810            } else if (opt.equals("--iv")) {
811                iv = hexToBytes(nextOptionData());
812                if (iv == null) {
813                    System.err.println("Error: must supply argument for --iv");
814                    return;
815                }
816            } else if (opt.equals("--key")) {
817                key = hexToBytes(nextOptionData());
818                if (key == null) {
819                    System.err.println("Error: must supply argument for --key");
820                    return;
821                }
822            } else if (opt.equals("--macalgo")) {
823                macAlgo = nextOptionData();
824                if (macAlgo == null) {
825                    System.err.println("Error: must supply argument for --macalgo");
826                    return;
827                }
828            } else if (opt.equals("--mackey")) {
829                macKey = hexToBytes(nextOptionData());
830                if (macKey == null) {
831                    System.err.println("Error: must supply argument for --mackey");
832                    return;
833                }
834            } else if (opt.equals("--tag")) {
835                tag = hexToBytes(nextOptionData());
836                if (tag == null) {
837                    System.err.println("Error: must supply argument for --tag");
838                    return;
839                }
840            } else if (opt.equals("--originating-uri")) {
841                originatingUriString = nextOptionData();
842                if (originatingUriString == null) {
843                    System.err.println("Error: must supply argument for --originating-uri");
844                    return;
845                }
846            } else if (opt.equals("--referrer")) {
847                referrer = nextOptionData();
848                if (referrer == null) {
849                    System.err.println("Error: must supply argument for --referrer");
850                    return;
851                }
852            } else {
853                System.err.println("Error: Unknown option: " + opt);
854                return;
855            }
856        }
857
858        final ContainerEncryptionParams encryptionParams;
859        if (algo != null || iv != null || key != null || macAlgo != null || macKey != null
860                || tag != null) {
861            if (algo == null || iv == null || key == null) {
862                System.err.println("Error: all of --algo, --iv, and --key must be specified");
863                return;
864            }
865
866            if (macAlgo != null || macKey != null || tag != null) {
867                if (macAlgo == null || macKey == null || tag == null) {
868                    System.err.println("Error: all of --macalgo, --mackey, and --tag must "
869                            + "be specified");
870                    return;
871                }
872            }
873
874            try {
875                final SecretKey encKey = new SecretKeySpec(key, "RAW");
876
877                final SecretKey macSecretKey;
878                if (macKey == null || macKey.length == 0) {
879                    macSecretKey = null;
880                } else {
881                    macSecretKey = new SecretKeySpec(macKey, "RAW");
882                }
883
884                encryptionParams = new ContainerEncryptionParams(algo, new IvParameterSpec(iv),
885                        encKey, macAlgo, null, macSecretKey, tag, -1, -1, -1);
886            } catch (InvalidAlgorithmParameterException e) {
887                e.printStackTrace();
888                return;
889            }
890        } else {
891            encryptionParams = null;
892        }
893
894        final Uri apkURI;
895        final Uri verificationURI;
896        final Uri originatingURI;
897        final Uri referrerURI;
898
899        if (originatingUriString != null) {
900            originatingURI = Uri.parse(originatingUriString);
901        } else {
902            originatingURI = null;
903        }
904
905        if (referrer != null) {
906            referrerURI = Uri.parse(referrer);
907        } else {
908            referrerURI = null;
909        }
910
911        // Populate apkURI, must be present
912        final String apkFilePath = nextArg();
913        System.err.println("\tpkg: " + apkFilePath);
914        if (apkFilePath != null) {
915            apkURI = Uri.fromFile(new File(apkFilePath));
916        } else {
917            System.err.println("Error: no package specified");
918            return;
919        }
920
921        // Populate verificationURI, optionally present
922        final String verificationFilePath = nextArg();
923        if (verificationFilePath != null) {
924            System.err.println("\tver: " + verificationFilePath);
925            verificationURI = Uri.fromFile(new File(verificationFilePath));
926        } else {
927            verificationURI = null;
928        }
929
930        PackageInstallObserver obs = new PackageInstallObserver();
931        try {
932            VerificationParams verificationParams = new VerificationParams(verificationURI,
933                    originatingURI, referrerURI, VerificationParams.NO_UID, null);
934
935            mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
936                    installerPackageName, verificationParams, encryptionParams);
937
938            synchronized (obs) {
939                while (!obs.finished) {
940                    try {
941                        obs.wait();
942                    } catch (InterruptedException e) {
943                    }
944                }
945                if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
946                    System.out.println("Success");
947                } else {
948                    System.err.println("Failure ["
949                            + installFailureToString(obs.result)
950                            + "]");
951                }
952            }
953        } catch (RemoteException e) {
954            System.err.println(e.toString());
955            System.err.println(PM_NOT_RUNNING_ERR);
956        }
957    }
958
959    /**
960     * Convert a string containing hex-encoded bytes to a byte array.
961     *
962     * @param input String containing hex-encoded bytes
963     * @return input as an array of bytes
964     */
965    private byte[] hexToBytes(String input) {
966        if (input == null) {
967            return null;
968        }
969
970        final int inputLength = input.length();
971        if ((inputLength % 2) != 0) {
972            System.err.print("Invalid length; must be multiple of 2");
973            return null;
974        }
975
976        final int byteLength = inputLength / 2;
977        final byte[] output = new byte[byteLength];
978
979        int inputIndex = 0;
980        int byteIndex = 0;
981        while (inputIndex < inputLength) {
982            output[byteIndex++] = (byte) Integer.parseInt(
983                    input.substring(inputIndex, inputIndex + 2), 16);
984            inputIndex += 2;
985        }
986
987        return output;
988    }
989
990    public void runCreateUser() {
991        String name;
992        String arg = nextArg();
993        if (arg == null) {
994            System.err.println("Error: no user name specified.");
995            return;
996        }
997        name = arg;
998        try {
999            final UserInfo info = mUm.createUser(name, 0);
1000            if (info != null) {
1001                System.out.println("Success: created user id " + info.id);
1002            } else {
1003                System.err.println("Error: couldn't create User.");
1004            }
1005        } catch (RemoteException e) {
1006            System.err.println(e.toString());
1007            System.err.println(PM_NOT_RUNNING_ERR);
1008        }
1009
1010    }
1011
1012    public void runRemoveUser() {
1013        int userId;
1014        String arg = nextArg();
1015        if (arg == null) {
1016            System.err.println("Error: no user id specified.");
1017            return;
1018        }
1019        try {
1020            userId = Integer.parseInt(arg);
1021        } catch (NumberFormatException e) {
1022            System.err.println("Error: user id '" + arg + "' is not a number.");
1023            return;
1024        }
1025        try {
1026            if (mUm.removeUser(userId)) {
1027                System.out.println("Success: removed user");
1028            } else {
1029                System.err.println("Error: couldn't remove user id " + userId);
1030            }
1031        } catch (RemoteException e) {
1032            System.err.println(e.toString());
1033            System.err.println(PM_NOT_RUNNING_ERR);
1034        }
1035    }
1036
1037    public void runListUsers() {
1038        try {
1039            List<UserInfo> users = mUm.getUsers(false);
1040            if (users == null) {
1041                System.err.println("Error: couldn't get users");
1042            } else {
1043                System.out.println("Users:");
1044                for (int i = 0; i < users.size(); i++) {
1045                    System.out.println("\t" + users.get(i).toString());
1046                }
1047            }
1048        } catch (RemoteException e) {
1049            System.err.println(e.toString());
1050            System.err.println(PM_NOT_RUNNING_ERR);
1051        }
1052    }
1053
1054    public void runGetMaxUsers() {
1055        System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers());
1056    }
1057
1058    class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
1059        boolean finished;
1060        boolean result;
1061
1062        public void packageDeleted(String packageName, int returnCode) {
1063            synchronized (this) {
1064                finished = true;
1065                result = returnCode == PackageManager.DELETE_SUCCEEDED;
1066                notifyAll();
1067            }
1068        }
1069    }
1070
1071    private void runUninstall() {
1072        int unInstallFlags = PackageManager.DELETE_ALL_USERS;
1073
1074        String opt;
1075        while ((opt=nextOption()) != null) {
1076            if (opt.equals("-k")) {
1077                unInstallFlags |= PackageManager.DELETE_KEEP_DATA;
1078            } else {
1079                System.err.println("Error: Unknown option: " + opt);
1080                return;
1081            }
1082        }
1083
1084        String pkg = nextArg();
1085        if (pkg == null) {
1086            System.err.println("Error: no package specified");
1087            showUsage();
1088            return;
1089        }
1090        boolean result = deletePackage(pkg, unInstallFlags);
1091        if (result) {
1092            System.out.println("Success");
1093        } else {
1094            System.out.println("Failure");
1095        }
1096    }
1097
1098    private boolean deletePackage(String pkg, int unInstallFlags) {
1099        PackageDeleteObserver obs = new PackageDeleteObserver();
1100        try {
1101            mPm.deletePackage(pkg, obs, unInstallFlags);
1102
1103            synchronized (obs) {
1104                while (!obs.finished) {
1105                    try {
1106                        obs.wait();
1107                    } catch (InterruptedException e) {
1108                    }
1109                }
1110            }
1111        } catch (RemoteException e) {
1112            System.err.println(e.toString());
1113            System.err.println(PM_NOT_RUNNING_ERR);
1114        }
1115        return obs.result;
1116    }
1117
1118    static class ClearDataObserver extends IPackageDataObserver.Stub {
1119        boolean finished;
1120        boolean result;
1121
1122        @Override
1123        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1124            synchronized (this) {
1125                finished = true;
1126                result = succeeded;
1127                notifyAll();
1128            }
1129        }
1130
1131    }
1132
1133    private void runClear() {
1134        int userId = 0;
1135        String option = nextOption();
1136        if (option != null && option.equals("--user")) {
1137            String optionData = nextOptionData();
1138            if (optionData == null || !isNumber(optionData)) {
1139                System.err.println("Error: no USER_ID specified");
1140                showUsage();
1141                return;
1142            } else {
1143                userId = Integer.parseInt(optionData);
1144            }
1145        }
1146
1147        String pkg = nextArg();
1148        if (pkg == null) {
1149            System.err.println("Error: no package specified");
1150            showUsage();
1151            return;
1152        }
1153
1154        ClearDataObserver obs = new ClearDataObserver();
1155        try {
1156            if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, userId)) {
1157                System.err.println("Failed");
1158            }
1159
1160            synchronized (obs) {
1161                while (!obs.finished) {
1162                    try {
1163                        obs.wait();
1164                    } catch (InterruptedException e) {
1165                    }
1166                }
1167            }
1168
1169            if (obs.result) {
1170                System.err.println("Success");
1171            } else {
1172                System.err.println("Failed");
1173            }
1174        } catch (RemoteException e) {
1175            System.err.println(e.toString());
1176            System.err.println(PM_NOT_RUNNING_ERR);
1177        }
1178    }
1179
1180    private static String enabledSettingToString(int state) {
1181        switch (state) {
1182            case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
1183                return "default";
1184            case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
1185                return "enabled";
1186            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
1187                return "disabled";
1188            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
1189                return "disabled-user";
1190        }
1191        return "unknown";
1192    }
1193
1194    private static boolean isNumber(String s) {
1195        try {
1196            Integer.parseInt(s);
1197        } catch (NumberFormatException nfe) {
1198            return false;
1199        }
1200        return true;
1201    }
1202
1203    private void runSetEnabledSetting(int state) {
1204        int userId = 0;
1205        String option = nextOption();
1206        if (option != null && option.equals("--user")) {
1207            String optionData = nextOptionData();
1208            if (optionData == null || !isNumber(optionData)) {
1209                System.err.println("Error: no USER_ID specified");
1210                showUsage();
1211                return;
1212            } else {
1213                userId = Integer.parseInt(optionData);
1214            }
1215        }
1216
1217        String pkg = nextArg();
1218        if (pkg == null) {
1219            System.err.println("Error: no package or component specified");
1220            showUsage();
1221            return;
1222        }
1223        ComponentName cn = ComponentName.unflattenFromString(pkg);
1224        if (cn == null) {
1225            try {
1226                mPm.setApplicationEnabledSetting(pkg, state, 0, userId);
1227                System.err.println("Package " + pkg + " new state: "
1228                        + enabledSettingToString(
1229                        mPm.getApplicationEnabledSetting(pkg, userId)));
1230            } catch (RemoteException e) {
1231                System.err.println(e.toString());
1232                System.err.println(PM_NOT_RUNNING_ERR);
1233            }
1234        } else {
1235            try {
1236                mPm.setComponentEnabledSetting(cn, state, 0, userId);
1237                System.err.println("Component " + cn.toShortString() + " new state: "
1238                        + enabledSettingToString(
1239                        mPm.getComponentEnabledSetting(cn, userId)));
1240            } catch (RemoteException e) {
1241                System.err.println(e.toString());
1242                System.err.println(PM_NOT_RUNNING_ERR);
1243            }
1244        }
1245    }
1246
1247    private void runGrantRevokePermission(boolean grant) {
1248        String pkg = nextArg();
1249        if (pkg == null) {
1250            System.err.println("Error: no package specified");
1251            showUsage();
1252            return;
1253        }
1254        String perm = nextArg();
1255        if (perm == null) {
1256            System.err.println("Error: no permission specified");
1257            showUsage();
1258            return;
1259        }
1260        try {
1261            if (grant) {
1262                mPm.grantPermission(pkg, perm);
1263            } else {
1264                mPm.revokePermission(pkg, perm);
1265            }
1266        } catch (RemoteException e) {
1267            System.err.println(e.toString());
1268            System.err.println(PM_NOT_RUNNING_ERR);
1269        } catch (IllegalArgumentException e) {
1270            System.err.println("Bad argument: " + e.toString());
1271            showUsage();
1272        } catch (SecurityException e) {
1273            System.err.println("Operation not allowed: " + e.toString());
1274        }
1275    }
1276
1277    private void runSetPermissionEnforced() {
1278        final String permission = nextArg();
1279        if (permission == null) {
1280            System.err.println("Error: no permission specified");
1281            showUsage();
1282            return;
1283        }
1284        final String enforcedRaw = nextArg();
1285        if (enforcedRaw == null) {
1286            System.err.println("Error: no enforcement specified");
1287            showUsage();
1288            return;
1289        }
1290        final boolean enforced = Boolean.parseBoolean(enforcedRaw);
1291        try {
1292            mPm.setPermissionEnforced(permission, enforced);
1293        } catch (RemoteException e) {
1294            System.err.println(e.toString());
1295            System.err.println(PM_NOT_RUNNING_ERR);
1296        } catch (IllegalArgumentException e) {
1297            System.err.println("Bad argument: " + e.toString());
1298            showUsage();
1299        } catch (SecurityException e) {
1300            System.err.println("Operation not allowed: " + e.toString());
1301        }
1302    }
1303
1304    static class ClearCacheObserver extends IPackageDataObserver.Stub {
1305        boolean finished;
1306        boolean result;
1307
1308        @Override
1309        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1310            synchronized (this) {
1311                finished = true;
1312                result = succeeded;
1313                notifyAll();
1314            }
1315        }
1316
1317    }
1318
1319    private void runTrimCaches() {
1320        String size = nextArg();
1321        if (size == null) {
1322            System.err.println("Error: no size specified");
1323            showUsage();
1324            return;
1325        }
1326        int len = size.length();
1327        long multiplier = 1;
1328        if (len > 1) {
1329            char c = size.charAt(len-1);
1330            if (c == 'K' || c == 'k') {
1331                multiplier = 1024L;
1332            } else if (c == 'M' || c == 'm') {
1333                multiplier = 1024L*1024L;
1334            } else if (c == 'G' || c == 'g') {
1335                multiplier = 1024L*1024L*1024L;
1336            } else {
1337                System.err.println("Invalid suffix: " + c);
1338                showUsage();
1339                return;
1340            }
1341            size = size.substring(0, len-1);
1342        }
1343        long sizeVal;
1344        try {
1345            sizeVal = Long.parseLong(size) * multiplier;
1346        } catch (NumberFormatException e) {
1347            System.err.println("Error: expected number at: " + size);
1348            showUsage();
1349            return;
1350        }
1351        ClearDataObserver obs = new ClearDataObserver();
1352        try {
1353            mPm.freeStorageAndNotify(sizeVal, obs);
1354            synchronized (obs) {
1355                while (!obs.finished) {
1356                    try {
1357                        obs.wait();
1358                    } catch (InterruptedException e) {
1359                    }
1360                }
1361            }
1362        } catch (RemoteException e) {
1363            System.err.println(e.toString());
1364            System.err.println(PM_NOT_RUNNING_ERR);
1365        } catch (IllegalArgumentException e) {
1366            System.err.println("Bad argument: " + e.toString());
1367            showUsage();
1368        } catch (SecurityException e) {
1369            System.err.println("Operation not allowed: " + e.toString());
1370        }
1371    }
1372
1373    /**
1374     * Displays the package file for a package.
1375     * @param pckg
1376     */
1377    private void displayPackageFilePath(String pckg) {
1378        try {
1379            PackageInfo info = mPm.getPackageInfo(pckg, 0, 0);
1380            if (info != null && info.applicationInfo != null) {
1381                System.out.print("package:");
1382                System.out.println(info.applicationInfo.sourceDir);
1383            }
1384        } catch (RemoteException e) {
1385            System.err.println(e.toString());
1386            System.err.println(PM_NOT_RUNNING_ERR);
1387        }
1388    }
1389
1390    private Resources getResources(PackageItemInfo pii) {
1391        Resources res = mResourceCache.get(pii.packageName);
1392        if (res != null) return res;
1393
1394        try {
1395            ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0, 0);
1396            AssetManager am = new AssetManager();
1397            am.addAssetPath(ai.publicSourceDir);
1398            res = new Resources(am, null, null);
1399            mResourceCache.put(pii.packageName, res);
1400            return res;
1401        } catch (RemoteException e) {
1402            System.err.println(e.toString());
1403            System.err.println(PM_NOT_RUNNING_ERR);
1404            return null;
1405        }
1406    }
1407
1408    private String nextOption() {
1409        if (mNextArg >= mArgs.length) {
1410            return null;
1411        }
1412        String arg = mArgs[mNextArg];
1413        if (!arg.startsWith("-")) {
1414            return null;
1415        }
1416        mNextArg++;
1417        if (arg.equals("--")) {
1418            return null;
1419        }
1420        if (arg.length() > 1 && arg.charAt(1) != '-') {
1421            if (arg.length() > 2) {
1422                mCurArgData = arg.substring(2);
1423                return arg.substring(0, 2);
1424            } else {
1425                mCurArgData = null;
1426                return arg;
1427            }
1428        }
1429        mCurArgData = null;
1430        return arg;
1431    }
1432
1433    private String nextOptionData() {
1434        if (mCurArgData != null) {
1435            return mCurArgData;
1436        }
1437        if (mNextArg >= mArgs.length) {
1438            return null;
1439        }
1440        String data = mArgs[mNextArg];
1441        mNextArg++;
1442        return data;
1443    }
1444
1445    private String nextArg() {
1446        if (mNextArg >= mArgs.length) {
1447            return null;
1448        }
1449        String arg = mArgs[mNextArg];
1450        mNextArg++;
1451        return arg;
1452    }
1453
1454    private static void showUsage() {
1455        System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]");
1456        System.err.println("       pm list permission-groups");
1457        System.err.println("       pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
1458        System.err.println("       pm list instrumentation [-f] [TARGET-PACKAGE]");
1459        System.err.println("       pm list features");
1460        System.err.println("       pm list libraries");
1461        System.err.println("       pm list users");
1462        System.err.println("       pm path PACKAGE");
1463        System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]");
1464        System.err.println("                  [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]");
1465        System.err.println("                  [--originating-uri <URI>] [--referrer <URI>] PATH");
1466        System.err.println("       pm uninstall [-k] PACKAGE");
1467        System.err.println("       pm clear [--user USER_ID] PACKAGE");
1468        System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
1469        System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
1470        System.err.println("       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
1471        System.err.println("       pm grant PACKAGE PERMISSION");
1472        System.err.println("       pm revoke PACKAGE PERMISSION");
1473        System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
1474        System.err.println("       pm get-install-location");
1475        System.err.println("       pm set-permission-enforced PERMISSION [true|false]");
1476        System.err.println("       pm trim-caches DESIRED_FREE_SPACE");
1477        System.err.println("       pm create-user USER_NAME");
1478        System.err.println("       pm remove-user USER_ID");
1479        System.err.println("       pm get-max-users");
1480        System.err.println("");
1481        System.err.println("pm list packages: prints all packages, optionally only");
1482        System.err.println("  those whose package name contains the text in FILTER.  Options:");
1483        System.err.println("    -f: see their associated file.");
1484        System.err.println("    -d: filter to only show disbled packages.");
1485        System.err.println("    -e: filter to only show enabled packages.");
1486        System.err.println("    -s: filter to only show system packages.");
1487        System.err.println("    -3: filter to only show third party packages.");
1488        System.err.println("    -i: see the installer for the packages.");
1489        System.err.println("    -u: also include uninstalled packages.");
1490        System.err.println("");
1491        System.err.println("pm list permission-groups: prints all known permission groups.");
1492        System.err.println("");
1493        System.err.println("pm list permissions: prints all known permissions, optionally only");
1494        System.err.println("  those in GROUP.  Options:");
1495        System.err.println("    -g: organize by group.");
1496        System.err.println("    -f: print all information.");
1497        System.err.println("    -s: short summary.");
1498        System.err.println("    -d: only list dangerous permissions.");
1499        System.err.println("    -u: list only the permissions users will see.");
1500        System.err.println("");
1501        System.err.println("pm list instrumentation: use to list all test packages; optionally");
1502        System.err.println("  supply <TARGET-PACKAGE> to list the test packages for a particular");
1503        System.err.println("  application.  Options:");
1504        System.err.println("    -f: list the .apk file for the test package.");
1505        System.err.println("");
1506        System.err.println("pm list features: prints all features of the system.");
1507        System.err.println("");
1508        System.err.println("pm list users: prints all users on the system.");
1509        System.err.println("");
1510        System.err.println("pm path: print the path to the .apk of the given PACKAGE.");
1511        System.err.println("");
1512        System.err.println("pm install: installs a package to the system.  Options:");
1513        System.err.println("    -l: install the package with FORWARD_LOCK.");
1514        System.err.println("    -r: reinstall an exisiting app, keeping its data.");
1515        System.err.println("    -t: allow test .apks to be installed.");
1516        System.err.println("    -i: specify the installer package name.");
1517        System.err.println("    -s: install package on sdcard.");
1518        System.err.println("    -f: install package on internal flash.");
1519        System.err.println("    -d: allow version code downgrade.");
1520        System.err.println("");
1521        System.err.println("pm uninstall: removes a package from the system. Options:");
1522        System.err.println("    -k: keep the data and cache directories around after package removal.");
1523        System.err.println("");
1524        System.err.println("pm clear: deletes all data associated with a package.");
1525        System.err.println("");
1526        System.err.println("pm enable, disable, disable-user: these commands change the enabled state");
1527        System.err.println("  of a given package or component (written as \"package/class\").");
1528        System.err.println("");
1529        System.err.println("pm grant, revoke: these commands either grant or revoke permissions");
1530        System.err.println("  to applications.  Only optional permissions the application has");
1531        System.err.println("  declared can be granted or revoked.");
1532        System.err.println("");
1533        System.err.println("pm get-install-location: returns the current install location.");
1534        System.err.println("    0 [auto]: Let system decide the best location");
1535        System.err.println("    1 [internal]: Install on internal device storage");
1536        System.err.println("    2 [external]: Install on external media");
1537        System.err.println("");
1538        System.err.println("pm set-install-location: changes the default install location.");
1539        System.err.println("  NOTE: this is only intended for debugging; using this can cause");
1540        System.err.println("  applications to break and other undersireable behavior.");
1541        System.err.println("    0 [auto]: Let system decide the best location");
1542        System.err.println("    1 [internal]: Install on internal device storage");
1543        System.err.println("    2 [external]: Install on external media");
1544        System.err.println("");
1545        System.err.println("pm trim-caches: trim cache files to reach the given free space.");
1546        System.err.println("");
1547        System.err.println("pm create-user: create a new user with the given USER_NAME,");
1548        System.err.println("  printing the new user identifier of the user.");
1549        System.err.println("");
1550        System.err.println("pm remove-user: remove the user with the given USER_IDENTIFIER,");
1551        System.err.println("  deleting all data associated with that user");
1552    }
1553}
1554