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