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