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