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