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