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