Pm.java revision f013e1afd1e68af5e3b868c26a653bbfb39538f8
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 android.content.ComponentName;
20import android.content.pm.ApplicationInfo;
21import android.content.pm.IPackageDeleteObserver;
22import android.content.pm.IPackageInstallObserver;
23import android.content.pm.IPackageManager;
24import android.content.pm.InstrumentationInfo;
25import android.content.pm.PackageInfo;
26import android.content.pm.PackageItemInfo;
27import android.content.pm.PackageManager;
28import android.content.pm.PermissionGroupInfo;
29import android.content.pm.PermissionInfo;
30import android.content.res.AssetManager;
31import android.content.res.Resources;
32import android.net.Uri;
33import android.os.RemoteException;
34import android.os.ServiceManager;
35
36import java.io.File;
37import java.util.ArrayList;
38import java.util.Collections;
39import java.util.Comparator;
40import java.util.List;
41import java.util.WeakHashMap;
42
43public final class Pm {
44    IPackageManager mPm;
45
46    private WeakHashMap<String, Resources> mResourceCache
47            = new WeakHashMap<String, Resources>();
48
49    private String[] mArgs;
50    private int mNextArg;
51    private String mCurArgData;
52
53    private static final String PM_NOT_RUNNING_ERR =
54        "Error: Could not access the Package Manager.  Is the system running?";
55
56    public static void main(String[] args) {
57        new Pm().run(args);
58    }
59
60    public void run(String[] args) {
61        boolean validCommand = false;
62        if (args.length < 1) {
63            showUsage();
64            return;
65        }
66
67        mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
68        if (mPm == null) {
69            System.err.println(PM_NOT_RUNNING_ERR);
70            return;
71        }
72
73        mArgs = args;
74        String op = args[0];
75        mNextArg = 1;
76
77        if ("list".equals(op)) {
78            runList();
79            return;
80        }
81
82        if ("path".equals(op)) {
83            runPath();
84            return;
85        }
86
87        if ("install".equals(op)) {
88            runInstall();
89            return;
90        }
91
92        if ("uninstall".equals(op)) {
93            runUninstall();
94            return;
95        }
96
97        try {
98            if (args.length == 1) {
99                if (args[0].equalsIgnoreCase("-l")) {
100                    validCommand = true;
101                    runListPackages(false);
102                } else if (args[0].equalsIgnoreCase("-lf")){
103                    validCommand = true;
104                    runListPackages(true);
105                }
106            } else if (args.length == 2) {
107                if (args[0].equalsIgnoreCase("-p")) {
108                    validCommand = true;
109                    displayPackageFilePath(args[1]);
110                }
111            }
112        } finally {
113            if (validCommand == false) {
114                showUsage();
115            }
116        }
117    }
118
119    /**
120     * Execute the list sub-command.
121     *
122     * pm list [package | packages]
123     * pm list permission-groups
124     * pm list permissions
125     * pm list instrumentation
126     */
127    private void runList() {
128        String type = nextArg();
129        if (type == null) {
130            System.err.println("Error: didn't specify type of data to list");
131            showUsage();
132            return;
133        }
134        if ("package".equals(type) || "packages".equals(type)) {
135            runListPackages(false);
136        } else if ("permission-groups".equals(type)) {
137            runListPermissionGroups();
138        } else if ("permissions".equals(type)) {
139            runListPermissions();
140        } else if ("instrumentation".equals(type)) {
141            runListInstrumentation();
142        } else {
143            System.err.println("Error: unknown list type '" + type + "'");
144            showUsage();
145        }
146    }
147
148    /**
149     * Lists all the installed packages.
150     */
151    private void runListPackages(boolean showApplicationPackage) {
152        try {
153            String opt;
154            while ((opt=nextOption()) != null) {
155                if (opt.equals("-l")) {
156                    // old compat
157                } else if (opt.equals("-lf")) {
158                    showApplicationPackage = true;
159                } else if (opt.equals("-f")) {
160                    showApplicationPackage = true;
161                } else {
162                    System.err.println("Error: Unknown option: " + opt);
163                    showUsage();
164                    return;
165                }
166            }
167        } catch (RuntimeException ex) {
168            System.err.println("Error: " + ex.toString());
169            showUsage();
170            return;
171        }
172
173        try {
174            List<PackageInfo> packages = mPm.getInstalledPackages(0 /* all */);
175
176            int count = packages.size();
177            for (int p = 0 ; p < count ; p++) {
178                PackageInfo info = packages.get(p);
179                System.out.print("package:");
180                if (showApplicationPackage) {
181                    System.out.print(info.applicationInfo.sourceDir);
182                    System.out.print("=");
183                }
184                System.out.println(info.packageName);
185            }
186        } catch (RemoteException e) {
187            System.err.println(e.toString());
188            System.err.println(PM_NOT_RUNNING_ERR);
189        }
190    }
191
192    /**
193     * Lists all of the installed instrumentation, or all for a given package
194     *
195     * pm list instrumentation [package] [-f]
196     */
197    private void runListInstrumentation() {
198        int flags = 0;      // flags != 0 is only used to request meta-data
199        boolean showPackage = false;
200        String targetPackage = null;
201
202        try {
203            String opt;
204            while ((opt=nextArg()) != null) {
205                if (opt.equals("-f")) {
206                    showPackage = true;
207                } else if (opt.charAt(0) != '-') {
208                    targetPackage = opt;
209                } else {
210                    System.err.println("Error: Unknown option: " + opt);
211                    showUsage();
212                    return;
213                }
214            }
215        } catch (RuntimeException ex) {
216            System.err.println("Error: " + ex.toString());
217            showUsage();
218            return;
219        }
220
221        try {
222            List<InstrumentationInfo> list = mPm.queryInstrumentation(targetPackage, flags);
223
224            // Sort by target package
225            Collections.sort(list, new Comparator<InstrumentationInfo>() {
226                public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
227                    return o1.targetPackage.compareTo(o2.targetPackage);
228                }
229            });
230
231            int count = (list != null) ? list.size() : 0;
232            for (int p = 0; p < count; p++) {
233                InstrumentationInfo ii = list.get(p);
234                System.out.print("instrumentation:");
235                if (showPackage) {
236                    System.out.print(ii.sourceDir);
237                    System.out.print("=");
238                }
239                ComponentName cn = new ComponentName(ii.packageName, ii.name);
240                System.out.print(cn.flattenToShortString());
241                System.out.print(" (target=");
242                System.out.print(ii.targetPackage);
243                System.out.println(")");
244            }
245        } catch (RemoteException e) {
246            System.err.println(e.toString());
247            System.err.println(PM_NOT_RUNNING_ERR);
248        }
249    }
250
251    /**
252     * Lists all the known permission groups.
253     */
254    private void runListPermissionGroups() {
255        try {
256            List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0);
257
258            int count = pgs.size();
259            for (int p = 0 ; p < count ; p++) {
260                PermissionGroupInfo pgi = pgs.get(p);
261                System.out.print("permission group:");
262                System.out.println(pgi.name);
263            }
264        } catch (RemoteException e) {
265            System.err.println(e.toString());
266            System.err.println(PM_NOT_RUNNING_ERR);
267        }
268    }
269
270    private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) {
271        if (nonLocalized != null) {
272            return nonLocalized.toString();
273        }
274        Resources r = getResources(pii);
275        if (r != null) {
276            return r.getString(res);
277        }
278        return null;
279    }
280
281    /**
282     * Lists all the permissions in a group.
283     */
284    private void runListPermissions() {
285        try {
286            boolean labels = false;
287            boolean groups = false;
288            boolean userOnly = false;
289            boolean summary = false;
290            boolean dangerousOnly = false;
291            String opt;
292            while ((opt=nextOption()) != null) {
293                if (opt.equals("-f")) {
294                    labels = true;
295                } else if (opt.equals("-g")) {
296                    groups = true;
297                } else if (opt.equals("-s")) {
298                    groups = true;
299                    labels = true;
300                    summary = true;
301                } else if (opt.equals("-u")) {
302                    userOnly = true;
303                } else if (opt.equals("-d")) {
304                    dangerousOnly = true;
305                } else {
306                    System.err.println("Error: Unknown option: " + opt);
307                    showUsage();
308                    return;
309                }
310            }
311
312            String grp = nextOption();
313            ArrayList<String> groupList = new ArrayList<String>();
314            if (groups) {
315                List<PermissionGroupInfo> infos =
316                        mPm.getAllPermissionGroups(0);
317                for (int i=0; i<infos.size(); i++) {
318                    groupList.add(infos.get(i).name);
319                }
320                groupList.add(null);
321            } else {
322                groupList.add(grp);
323            }
324
325            if (dangerousOnly) {
326                System.out.println("Dangerous Permissions:");
327                System.out.println("");
328                doListPermissions(groupList, groups, labels, summary,
329                        PermissionInfo.PROTECTION_DANGEROUS,
330                        PermissionInfo.PROTECTION_DANGEROUS);
331                if (userOnly) {
332                    System.out.println("Normal Permissions:");
333                    System.out.println("");
334                    doListPermissions(groupList, groups, labels, summary,
335                            PermissionInfo.PROTECTION_NORMAL,
336                            PermissionInfo.PROTECTION_NORMAL);
337                }
338            } else if (userOnly) {
339                System.out.println("Dangerous and Normal Permissions:");
340                System.out.println("");
341                doListPermissions(groupList, groups, labels, summary,
342                        PermissionInfo.PROTECTION_NORMAL,
343                        PermissionInfo.PROTECTION_DANGEROUS);
344            } else {
345                System.out.println("All Permissions:");
346                System.out.println("");
347                doListPermissions(groupList, groups, labels, summary,
348                        -10000, 10000);
349            }
350        } catch (RemoteException e) {
351            System.err.println(e.toString());
352            System.err.println(PM_NOT_RUNNING_ERR);
353        }
354    }
355
356    private void doListPermissions(ArrayList<String> groupList,
357            boolean groups, boolean labels, boolean summary,
358            int startProtectionLevel, int endProtectionLevel)
359            throws RemoteException {
360        for (int i=0; i<groupList.size(); i++) {
361            String groupName = groupList.get(i);
362            String prefix = "";
363            if (groups) {
364                if (i > 0) System.out.println("");
365                if (groupName != null) {
366                    PermissionGroupInfo pgi = mPm.getPermissionGroupInfo(
367                            groupName, 0);
368                    if (summary) {
369                        Resources res = getResources(pgi);
370                        if (res != null) {
371                            System.out.print(loadText(pgi, pgi.labelRes,
372                                    pgi.nonLocalizedLabel) + ": ");
373                        } else {
374                            System.out.print(pgi.name + ": ");
375
376                        }
377                    } else {
378                        System.out.println((labels ? "+ " : "")
379                                + "group:" + pgi.name);
380                        if (labels) {
381                            System.out.println("  package:" + pgi.packageName);
382                            Resources res = getResources(pgi);
383                            if (res != null) {
384                                System.out.println("  label:"
385                                        + loadText(pgi, pgi.labelRes,
386                                                pgi.nonLocalizedLabel));
387                                System.out.println("  description:"
388                                        + loadText(pgi, pgi.descriptionRes,
389                                                pgi.nonLocalizedDescription));
390                            }
391                        }
392                    }
393                } else {
394                    System.out.println(((labels && !summary)
395                            ? "+ " : "") + "ungrouped:");
396                }
397                prefix = "  ";
398            }
399            List<PermissionInfo> ps = mPm.queryPermissionsByGroup(
400                    groupList.get(i), 0);
401            int count = ps.size();
402            boolean first = true;
403            for (int p = 0 ; p < count ; p++) {
404                PermissionInfo pi = ps.get(p);
405                if (groups && groupName == null && pi.group != null) {
406                    continue;
407                }
408                if (pi.protectionLevel < startProtectionLevel
409                        || pi.protectionLevel > endProtectionLevel) {
410                    continue;
411                }
412                if (summary) {
413                    if (first) {
414                        first = false;
415                    } else {
416                        System.out.print(", ");
417                    }
418                    Resources res = getResources(pi);
419                    if (res != null) {
420                        System.out.print(loadText(pi, pi.labelRes,
421                                pi.nonLocalizedLabel));
422                    } else {
423                        System.out.print(pi.name);
424                    }
425                } else {
426                    System.out.println(prefix + (labels ? "+ " : "")
427                            + "permission:" + pi.name);
428                    if (labels) {
429                        System.out.println(prefix + "  package:" + pi.packageName);
430                        Resources res = getResources(pi);
431                        if (res != null) {
432                            System.out.println(prefix + "  label:"
433                                    + loadText(pi, pi.labelRes,
434                                            pi.nonLocalizedLabel));
435                            System.out.println(prefix + "  description:"
436                                    + loadText(pi, pi.descriptionRes,
437                                            pi.nonLocalizedDescription));
438                        }
439                        String protLevel = "unknown";
440                        switch(pi.protectionLevel) {
441                            case PermissionInfo.PROTECTION_DANGEROUS:
442                                protLevel = "dangerous";
443                                break;
444                            case PermissionInfo.PROTECTION_NORMAL:
445                                protLevel = "normal";
446                                break;
447                            case PermissionInfo.PROTECTION_SIGNATURE:
448                                protLevel = "signature";
449                                break;
450                            case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM:
451                                protLevel = "signatureOrSystem";
452                                break;
453                        }
454                        System.out.println(prefix + "  protectionLevel:" + protLevel);
455                    }
456                }
457            }
458
459            if (summary) {
460                System.out.println("");
461            }
462        }
463    }
464
465    private void runPath() {
466        String pkg = nextArg();
467        if (pkg == null) {
468            System.err.println("Error: no package specified");
469            showUsage();
470            return;
471        }
472        displayPackageFilePath(pkg);
473    }
474
475    class PackageInstallObserver extends IPackageInstallObserver.Stub {
476        boolean finished;
477        int result;
478
479        public void packageInstalled(String name, int status) {
480            synchronized( this) {
481                finished = true;
482                result = status;
483                notifyAll();
484            }
485        }
486    }
487
488    private String installFailureToString(int result) {
489        String s;
490        switch (result) {
491        case PackageManager.INSTALL_FAILED_ALREADY_EXISTS:
492            s = "INSTALL_FAILED_ALREADY_EXISTS";
493            break;
494        case PackageManager.INSTALL_FAILED_INVALID_APK:
495            s = "INSTALL_FAILED_INVALID_APK";
496            break;
497        case PackageManager.INSTALL_FAILED_INVALID_URI:
498            s = "INSTALL_FAILED_INVALID_URI";
499            break;
500        case PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE:
501            s = "INSTALL_FAILED_INSUFFICIENT_STORAGE";
502            break;
503        case PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE:
504            s = "INSTALL_FAILED_DUPLICATE_PACKAGE";
505            break;
506        case PackageManager.INSTALL_FAILED_NO_SHARED_USER:
507            s = "INSTALL_FAILED_NO_SHARED_USER";
508            break;
509        case PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE:
510            s = "INSTALL_FAILED_UPDATE_INCOMPATIBLE";
511            break;
512        case PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE:
513            s = "INSTALL_FAILED_SHARED_USER_INCOMPATIBLE";
514            break;
515        case PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY:
516            s = "INSTALL_FAILED_MISSING_SHARED_LIBRARY";
517            break;
518        case PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE:
519            s = "INSTALL_FAILED_REPLACE_COULDNT_DELETE";
520            break;
521        case PackageManager.INSTALL_PARSE_FAILED_NOT_APK:
522            s = "INSTALL_PARSE_FAILED_NOT_APK";
523            break;
524        case PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST:
525            s = "INSTALL_PARSE_FAILED_BAD_MANIFEST";
526            break;
527        case PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION:
528            s = "INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION";
529            break;
530        case PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES:
531            s = "INSTALL_PARSE_FAILED_NO_CERTIFICATES";
532            break;
533        case PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES:
534            s = "INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES";
535            break;
536        case PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING:
537            s = "INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING";
538            break;
539        case PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME:
540            s = "INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME";
541            break;
542        case PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID:
543            s = "INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID";
544            break;
545        case PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED:
546            s = "INSTALL_PARSE_FAILED_MANIFEST_MALFORMED";
547            break;
548        case PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY:
549            s = "INSTALL_PARSE_FAILED_MANIFEST_EMPTY";
550            break;
551        case PackageManager.INSTALL_FAILED_OLDER_SDK:
552            s = "INSTALL_FAILED_OLDER_SDK";
553            break;
554        default:
555            s = Integer.toString(result);
556        break;
557        }
558        return s;
559    }
560
561    private void runInstall() {
562        int installFlags = 0;
563
564        String opt;
565        while ((opt=nextOption()) != null) {
566            if (opt.equals("-l")) {
567                installFlags |= PackageManager.FORWARD_LOCK_PACKAGE;
568            } else if (opt.equals("-r")) {
569                installFlags |= PackageManager.REPLACE_EXISTING_PACKAGE;
570            } else {
571                System.err.println("Error: Unknown option: " + opt);
572                showUsage();
573                return;
574            }
575        }
576
577        String apkFilePath = nextArg();
578        System.err.println("\tpkg: " + apkFilePath);
579        if (apkFilePath == null) {
580            System.err.println("Error: no package specified");
581            showUsage();
582            return;
583        }
584
585        PackageInstallObserver obs = new PackageInstallObserver();
586        try {
587            mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags);
588
589            synchronized (obs) {
590                while (!obs.finished) {
591                    try {
592                        obs.wait();
593                    } catch (InterruptedException e) {
594                    }
595                }
596                if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
597                    System.out.println("Success");
598                } else {
599                    System.err.println("Failure ["
600                            + installFailureToString(obs.result)
601                            + "]");
602                }
603            }
604        } catch (RemoteException e) {
605            System.err.println(e.toString());
606            System.err.println(PM_NOT_RUNNING_ERR);
607        }
608    }
609
610    class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
611        boolean finished;
612        boolean result;
613
614        public void packageDeleted(boolean succeeded) {
615            synchronized (this) {
616                finished = true;
617                result = succeeded;
618                notifyAll();
619            }
620        }
621    }
622
623    private void runUninstall() {
624        int unInstallFlags = 0;
625
626        String opt = nextOption();
627        if (opt != null && opt.equals("-k")) {
628            unInstallFlags = PackageManager.DONT_DELETE_DATA;
629        }
630
631        String pkg = nextArg();
632        if (pkg == null) {
633            System.err.println("Error: no package specified");
634            showUsage();
635            return;
636        }
637        boolean result = deletePackage(pkg, unInstallFlags);
638        if (result) {
639            System.out.println("Success");
640        } else {
641            System.out.println("Failure");
642        }
643    }
644
645    private boolean deletePackage(String pkg, int unInstallFlags) {
646        PackageDeleteObserver obs = new PackageDeleteObserver();
647        try {
648            mPm.deletePackage(pkg, obs, unInstallFlags);
649
650            synchronized (obs) {
651                while (!obs.finished) {
652                    try {
653                        obs.wait();
654                    } catch (InterruptedException e) {
655                    }
656                }
657            }
658        } catch (RemoteException e) {
659            System.err.println(e.toString());
660            System.err.println(PM_NOT_RUNNING_ERR);
661        }
662        return obs.result;
663    }
664
665    /**
666     * Displays the package file for a package.
667     * @param pckg
668     */
669    private void displayPackageFilePath(String pckg) {
670        try {
671            PackageInfo info = mPm.getPackageInfo(pckg, 0);
672            if (info != null && info.applicationInfo != null) {
673                System.out.print("package:");
674                System.out.println(info.applicationInfo.sourceDir);
675            }
676        } catch (RemoteException e) {
677            System.err.println(e.toString());
678            System.err.println(PM_NOT_RUNNING_ERR);
679        }
680    }
681
682    private Resources getResources(PackageItemInfo pii) {
683        Resources res = mResourceCache.get(pii.packageName);
684        if (res != null) return res;
685
686        try {
687            ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0);
688            AssetManager am = new AssetManager();
689            am.addAssetPath(ai.publicSourceDir);
690            res = new Resources(am, null, null);
691            mResourceCache.put(pii.packageName, res);
692            return res;
693        } catch (RemoteException e) {
694            System.err.println(e.toString());
695            System.err.println(PM_NOT_RUNNING_ERR);
696            return null;
697        }
698    }
699
700    private String nextOption() {
701        if (mNextArg >= mArgs.length) {
702            return null;
703        }
704        String arg = mArgs[mNextArg];
705        if (!arg.startsWith("-")) {
706            return null;
707        }
708        mNextArg++;
709        if (arg.equals("--")) {
710            return null;
711        }
712        if (arg.length() > 1 && arg.charAt(1) != '-') {
713            if (arg.length() > 2) {
714                mCurArgData = arg.substring(2);
715                return arg.substring(0, 2);
716            } else {
717                mCurArgData = null;
718                return arg;
719            }
720        }
721        mCurArgData = null;
722        return arg;
723    }
724
725    private String nextOptionData() {
726        if (mCurArgData != null) {
727            return mCurArgData;
728        }
729        if (mNextArg >= mArgs.length) {
730            return null;
731        }
732        String data = mArgs[mNextArg];
733        mNextArg++;
734        return data;
735    }
736
737    private String nextArg() {
738        if (mNextArg >= mArgs.length) {
739            return null;
740        }
741        String arg = mArgs[mNextArg];
742        mNextArg++;
743        return arg;
744    }
745
746    private static void showUsage() {
747        System.err.println("usage: pm [list|path|install|uninstall]");
748        System.err.println("       pm list packages [-f]");
749        System.err.println("       pm list permission-groups");
750        System.err.println("       pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
751        System.err.println("       pm list instrumentation [-f] [TARGET-PACKAGE]");
752        System.err.println("       pm path PACKAGE");
753        System.err.println("       pm install [-l] [-r] PATH");
754        System.err.println("       pm uninstall [-k] PACKAGE");
755        System.err.println("");
756        System.err.println("The list packages command prints all packages.  Use");
757        System.err.println("the -f option to see their associated file.");
758        System.err.println("");
759        System.err.println("The list permission-groups command prints all known");
760        System.err.println("permission groups.");
761        System.err.println("");
762        System.err.println("The list permissions command prints all known");
763        System.err.println("permissions, optionally only those in GROUP.  Use");
764        System.err.println("the -g option to organize by group.  Use");
765        System.err.println("the -f option to print all information.  Use");
766        System.err.println("the -s option for a short summary.  Use");
767        System.err.println("the -d option to only list dangerous permissions.  Use");
768        System.err.println("the -u option to list only the permissions users will see.");
769        System.err.println("");
770        System.err.println("The list instrumentation command prints all instrumentations,");
771        System.err.println("or only those that target a specified package.  Use the -f option");
772        System.err.println("to see their associated file.");
773        System.err.println("");
774        System.err.println("The path command prints the path to the .apk of a package.");
775        System.err.println("");
776        System.err.println("The install command installs a package to the system.  Use");
777        System.err.println("the -l option to install the package with FORWARD_LOCK. Use");
778        System.err.println("the -r option to reinstall an exisiting app, keeping its data.");
779        System.err.println("");
780        System.err.println("The uninstall command removes a package from the system. Use");
781        System.err.println("the -k option to keep the data and cache directories around");
782        System.err.println("after the package removal.");
783    }
784}
785