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