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