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