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