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