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