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