Pm.java revision a0907436c01fd8c545a6b5c7b28bc3bc9db59270
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 android.app.ActivityManager;
20import android.app.ActivityManagerNative;
21import android.app.IActivityManager;
22import android.app.PackageInstallObserver;
23import android.content.ComponentName;
24import android.content.IIntentReceiver;
25import android.content.IIntentSender;
26import android.content.Intent;
27import android.content.IntentSender;
28import android.content.pm.ApplicationInfo;
29import android.content.pm.FeatureInfo;
30import android.content.pm.IPackageDataObserver;
31import android.content.pm.IPackageInstaller;
32import android.content.pm.IPackageManager;
33import android.content.pm.InstrumentationInfo;
34import android.content.pm.PackageInfo;
35import android.content.pm.PackageInstaller;
36import android.content.pm.PackageInstaller.SessionInfo;
37import android.content.pm.PackageInstaller.SessionParams;
38import android.content.pm.PackageItemInfo;
39import android.content.pm.PackageManager;
40import android.content.pm.ParceledListSlice;
41import android.content.pm.PermissionGroupInfo;
42import android.content.pm.PermissionInfo;
43import android.content.pm.UserInfo;
44import android.content.pm.VerificationParams;
45import android.content.res.AssetManager;
46import android.content.res.Resources;
47import android.net.Uri;
48import android.os.Build;
49import android.os.Bundle;
50import android.os.IUserManager;
51import android.os.Process;
52import android.os.RemoteException;
53import android.os.ServiceManager;
54import android.os.UserHandle;
55import android.os.UserManager;
56import android.text.TextUtils;
57import android.util.Log;
58
59import com.android.internal.content.PackageHelper;
60import com.android.internal.util.ArrayUtils;
61import com.android.internal.util.SizedInputStream;
62
63import libcore.io.IoUtils;
64
65import java.io.File;
66import java.io.FileDescriptor;
67import java.io.FileInputStream;
68import java.io.IOException;
69import java.io.InputStream;
70import java.io.OutputStream;
71import java.lang.reflect.Field;
72import java.lang.reflect.Modifier;
73import java.util.ArrayList;
74import java.util.Collections;
75import java.util.Comparator;
76import java.util.List;
77import java.util.WeakHashMap;
78import java.util.concurrent.SynchronousQueue;
79import java.util.concurrent.TimeUnit;
80
81public final class Pm {
82    private static final String TAG = "Pm";
83
84    IPackageManager mPm;
85    IPackageInstaller mInstaller;
86    IUserManager mUm;
87
88    private WeakHashMap<String, Resources> mResourceCache
89            = new WeakHashMap<String, Resources>();
90
91    private String[] mArgs;
92    private int mNextArg;
93    private String mCurArgData;
94
95    private static final String PM_NOT_RUNNING_ERR =
96        "Error: Could not access the Package Manager.  Is the system running?";
97
98    public static void main(String[] args) {
99        try {
100            new Pm().run(args);
101        } catch (Exception e) {
102            Log.e(TAG, "Error", e);
103            System.err.println("Error: " + e);
104            if (e instanceof RemoteException) {
105                System.err.println(PM_NOT_RUNNING_ERR);
106            }
107        }
108    }
109
110    public void run(String[] args) throws IOException, RemoteException {
111        boolean validCommand = false;
112        if (args.length < 1) {
113            showUsage();
114            return;
115        }
116
117        mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user"));
118        mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
119        if (mPm == null) {
120            System.err.println(PM_NOT_RUNNING_ERR);
121            return;
122        }
123        mInstaller = mPm.getPackageInstaller();
124
125        mArgs = args;
126        String op = args[0];
127        mNextArg = 1;
128
129        if ("list".equals(op)) {
130            runList();
131            return;
132        }
133
134        if ("path".equals(op)) {
135            runPath();
136            return;
137        }
138
139        if ("dump".equals(op)) {
140            runDump();
141            return;
142        }
143
144        if ("install".equals(op)) {
145            runInstall();
146            return;
147        }
148
149        if ("install-create".equals(op)) {
150            runInstallCreate();
151            return;
152        }
153
154        if ("install-write".equals(op)) {
155            runInstallWrite();
156            return;
157        }
158
159        if ("install-commit".equals(op)) {
160            runInstallCommit();
161            return;
162        }
163
164        if ("install-abandon".equals(op) || "install-destroy".equals(op)) {
165            runInstallAbandon();
166            return;
167        }
168
169        if ("set-installer".equals(op)) {
170            runSetInstaller();
171            return;
172        }
173
174        if ("uninstall".equals(op)) {
175            runUninstall();
176            return;
177        }
178
179        if ("clear".equals(op)) {
180            runClear();
181            return;
182        }
183
184        if ("enable".equals(op)) {
185            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
186            return;
187        }
188
189        if ("disable".equals(op)) {
190            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
191            return;
192        }
193
194        if ("disable-user".equals(op)) {
195            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
196            return;
197        }
198
199        if ("disable-until-used".equals(op)) {
200            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
201            return;
202        }
203
204        if ("hide".equals(op)) {
205            runSetHiddenSetting(true);
206            return;
207        }
208
209        if ("unhide".equals(op)) {
210            runSetHiddenSetting(false);
211            return;
212        }
213
214        if ("grant".equals(op)) {
215            runGrantRevokePermission(true);
216            return;
217        }
218
219        if ("revoke".equals(op)) {
220            runGrantRevokePermission(false);
221            return;
222        }
223
224        if ("set-permission-enforced".equals(op)) {
225            runSetPermissionEnforced();
226            return;
227        }
228
229        if ("set-install-location".equals(op)) {
230            runSetInstallLocation();
231            return;
232        }
233
234        if ("get-install-location".equals(op)) {
235            runGetInstallLocation();
236            return;
237        }
238
239        if ("trim-caches".equals(op)) {
240            runTrimCaches();
241            return;
242        }
243
244        if ("create-user".equals(op)) {
245            runCreateUser();
246            return;
247        }
248
249        if ("remove-user".equals(op)) {
250            runRemoveUser();
251            return;
252        }
253
254        if ("get-max-users".equals(op)) {
255            runGetMaxUsers();
256            return;
257        }
258
259        if ("force-dex-opt".equals(op)) {
260            runForceDexOpt();
261            return;
262        }
263
264        try {
265            if (args.length == 1) {
266                if (args[0].equalsIgnoreCase("-l")) {
267                    validCommand = true;
268                    runListPackages(false);
269                } else if (args[0].equalsIgnoreCase("-lf")){
270                    validCommand = true;
271                    runListPackages(true);
272                }
273            } else if (args.length == 2) {
274                if (args[0].equalsIgnoreCase("-p")) {
275                    validCommand = true;
276                    displayPackageFilePath(args[1]);
277                }
278            }
279        } finally {
280            if (validCommand == false) {
281                if (op != null) {
282                    System.err.println("Error: unknown command '" + op + "'");
283                }
284                showUsage();
285            }
286        }
287    }
288
289    /**
290     * Execute the list sub-command.
291     *
292     * pm list [package | packages]
293     * pm list permission-groups
294     * pm list permissions
295     * pm list features
296     * pm list libraries
297     * pm list instrumentation
298     */
299    private void runList() {
300        String type = nextArg();
301        if (type == null) {
302            System.err.println("Error: didn't specify type of data to list");
303            return;
304        }
305        if ("package".equals(type) || "packages".equals(type)) {
306            runListPackages(false);
307        } else if ("permission-groups".equals(type)) {
308            runListPermissionGroups();
309        } else if ("permissions".equals(type)) {
310            runListPermissions();
311        } else if ("features".equals(type)) {
312            runListFeatures();
313        } else if ("libraries".equals(type)) {
314            runListLibraries();
315        } else if ("instrumentation".equals(type)) {
316            runListInstrumentation();
317        } else if ("users".equals(type)) {
318            runListUsers();
319        } else {
320            System.err.println("Error: unknown list type '" + type + "'");
321        }
322    }
323
324    /**
325     * Lists all the installed packages.
326     */
327    private void runListPackages(boolean showApplicationPackage) {
328        int getFlags = 0;
329        boolean listDisabled = false, listEnabled = false;
330        boolean listSystem = false, listThirdParty = false;
331        boolean listInstaller = false;
332        int userId = UserHandle.USER_OWNER;
333        try {
334            String opt;
335            while ((opt=nextOption()) != null) {
336                if (opt.equals("-l")) {
337                    // old compat
338                } else if (opt.equals("-lf")) {
339                    showApplicationPackage = true;
340                } else if (opt.equals("-f")) {
341                    showApplicationPackage = true;
342                } else if (opt.equals("-d")) {
343                    listDisabled = true;
344                } else if (opt.equals("-e")) {
345                    listEnabled = true;
346                } else if (opt.equals("-s")) {
347                    listSystem = true;
348                } else if (opt.equals("-3")) {
349                    listThirdParty = true;
350                } else if (opt.equals("-i")) {
351                    listInstaller = true;
352                } else if (opt.equals("--user")) {
353                    userId = Integer.parseInt(nextArg());
354                } else if (opt.equals("-u")) {
355                    getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
356                } else {
357                    System.err.println("Error: Unknown option: " + opt);
358                    return;
359                }
360            }
361        } catch (RuntimeException ex) {
362            System.err.println("Error: " + ex.toString());
363            return;
364        }
365
366        String filter = nextArg();
367
368        try {
369            final List<PackageInfo> packages = getInstalledPackages(mPm, getFlags, userId);
370
371            int count = packages.size();
372            for (int p = 0 ; p < count ; p++) {
373                PackageInfo info = packages.get(p);
374                if (filter != null && !info.packageName.contains(filter)) {
375                    continue;
376                }
377                final boolean isSystem =
378                        (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
379                if ((!listDisabled || !info.applicationInfo.enabled) &&
380                        (!listEnabled || info.applicationInfo.enabled) &&
381                        (!listSystem || isSystem) &&
382                        (!listThirdParty || !isSystem)) {
383                    System.out.print("package:");
384                    if (showApplicationPackage) {
385                        System.out.print(info.applicationInfo.sourceDir);
386                        System.out.print("=");
387                    }
388                    System.out.print(info.packageName);
389                    if (listInstaller) {
390                        System.out.print("  installer=");
391                        System.out.print(mPm.getInstallerPackageName(info.packageName));
392                    }
393                    System.out.println();
394                }
395            }
396        } catch (RemoteException e) {
397            System.err.println(e.toString());
398            System.err.println(PM_NOT_RUNNING_ERR);
399        }
400    }
401
402    @SuppressWarnings("unchecked")
403    private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags, int userId)
404            throws RemoteException {
405        ParceledListSlice<PackageInfo> slice = pm.getInstalledPackages(flags, userId);
406        return slice.getList();
407    }
408
409    /**
410     * Lists all of the features supported by the current device.
411     *
412     * pm list features
413     */
414    private void runListFeatures() {
415        try {
416            List<FeatureInfo> list = new ArrayList<FeatureInfo>();
417            FeatureInfo[] rawList = mPm.getSystemAvailableFeatures();
418            for (int i=0; i<rawList.length; i++) {
419                list.add(rawList[i]);
420            }
421
422
423            // Sort by name
424            Collections.sort(list, new Comparator<FeatureInfo>() {
425                public int compare(FeatureInfo o1, FeatureInfo o2) {
426                    if (o1.name == o2.name) return 0;
427                    if (o1.name == null) return -1;
428                    if (o2.name == null) return 1;
429                    return o1.name.compareTo(o2.name);
430                }
431            });
432
433            int count = (list != null) ? list.size() : 0;
434            for (int p = 0; p < count; p++) {
435                FeatureInfo fi = list.get(p);
436                System.out.print("feature:");
437                if (fi.name != null) System.out.println(fi.name);
438                else System.out.println("reqGlEsVersion=0x"
439                        + Integer.toHexString(fi.reqGlEsVersion));
440            }
441        } catch (RemoteException e) {
442            System.err.println(e.toString());
443            System.err.println(PM_NOT_RUNNING_ERR);
444        }
445    }
446
447    /**
448     * Lists all of the libraries supported by the current device.
449     *
450     * pm list libraries
451     */
452    private void runListLibraries() {
453        try {
454            List<String> list = new ArrayList<String>();
455            String[] rawList = mPm.getSystemSharedLibraryNames();
456            for (int i=0; i<rawList.length; i++) {
457                list.add(rawList[i]);
458            }
459
460
461            // Sort by name
462            Collections.sort(list, new Comparator<String>() {
463                public int compare(String o1, String o2) {
464                    if (o1 == o2) return 0;
465                    if (o1 == null) return -1;
466                    if (o2 == null) return 1;
467                    return o1.compareTo(o2);
468                }
469            });
470
471            int count = (list != null) ? list.size() : 0;
472            for (int p = 0; p < count; p++) {
473                String lib = list.get(p);
474                System.out.print("library:");
475                System.out.println(lib);
476            }
477        } catch (RemoteException e) {
478            System.err.println(e.toString());
479            System.err.println(PM_NOT_RUNNING_ERR);
480        }
481    }
482
483    /**
484     * Lists all of the installed instrumentation, or all for a given package
485     *
486     * pm list instrumentation [package] [-f]
487     */
488    private void runListInstrumentation() {
489        int flags = 0;      // flags != 0 is only used to request meta-data
490        boolean showPackage = false;
491        String targetPackage = null;
492
493        try {
494            String opt;
495            while ((opt=nextArg()) != null) {
496                if (opt.equals("-f")) {
497                    showPackage = true;
498                } else if (opt.charAt(0) != '-') {
499                    targetPackage = opt;
500                } else {
501                    System.err.println("Error: Unknown option: " + opt);
502                    return;
503                }
504            }
505        } catch (RuntimeException ex) {
506            System.err.println("Error: " + ex.toString());
507            return;
508        }
509
510        try {
511            List<InstrumentationInfo> list = mPm.queryInstrumentation(targetPackage, flags);
512
513            // Sort by target package
514            Collections.sort(list, new Comparator<InstrumentationInfo>() {
515                public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
516                    return o1.targetPackage.compareTo(o2.targetPackage);
517                }
518            });
519
520            int count = (list != null) ? list.size() : 0;
521            for (int p = 0; p < count; p++) {
522                InstrumentationInfo ii = list.get(p);
523                System.out.print("instrumentation:");
524                if (showPackage) {
525                    System.out.print(ii.sourceDir);
526                    System.out.print("=");
527                }
528                ComponentName cn = new ComponentName(ii.packageName, ii.name);
529                System.out.print(cn.flattenToShortString());
530                System.out.print(" (target=");
531                System.out.print(ii.targetPackage);
532                System.out.println(")");
533            }
534        } catch (RemoteException e) {
535            System.err.println(e.toString());
536            System.err.println(PM_NOT_RUNNING_ERR);
537        }
538    }
539
540    /**
541     * Lists all the known permission groups.
542     */
543    private void runListPermissionGroups() {
544        try {
545            List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0);
546
547            int count = pgs.size();
548            for (int p = 0 ; p < count ; p++) {
549                PermissionGroupInfo pgi = pgs.get(p);
550                System.out.print("permission group:");
551                System.out.println(pgi.name);
552            }
553        } catch (RemoteException e) {
554            System.err.println(e.toString());
555            System.err.println(PM_NOT_RUNNING_ERR);
556        }
557    }
558
559    private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) {
560        if (nonLocalized != null) {
561            return nonLocalized.toString();
562        }
563        if (res != 0) {
564            Resources r = getResources(pii);
565            if (r != null) {
566                return r.getString(res);
567            }
568        }
569        return null;
570    }
571
572    /**
573     * Lists all the permissions in a group.
574     */
575    private void runListPermissions() {
576        try {
577            boolean labels = false;
578            boolean groups = false;
579            boolean userOnly = false;
580            boolean summary = false;
581            boolean dangerousOnly = false;
582            String opt;
583            while ((opt=nextOption()) != null) {
584                if (opt.equals("-f")) {
585                    labels = true;
586                } else if (opt.equals("-g")) {
587                    groups = true;
588                } else if (opt.equals("-s")) {
589                    groups = true;
590                    labels = true;
591                    summary = true;
592                } else if (opt.equals("-u")) {
593                    userOnly = true;
594                } else if (opt.equals("-d")) {
595                    dangerousOnly = true;
596                } else {
597                    System.err.println("Error: Unknown option: " + opt);
598                    return;
599                }
600            }
601
602            String grp = nextOption();
603            ArrayList<String> groupList = new ArrayList<String>();
604            if (groups) {
605                List<PermissionGroupInfo> infos =
606                        mPm.getAllPermissionGroups(0);
607                for (int i=0; i<infos.size(); i++) {
608                    groupList.add(infos.get(i).name);
609                }
610                groupList.add(null);
611            } else {
612                groupList.add(grp);
613            }
614
615            if (dangerousOnly) {
616                System.out.println("Dangerous Permissions:");
617                System.out.println("");
618                doListPermissions(groupList, groups, labels, summary,
619                        PermissionInfo.PROTECTION_DANGEROUS,
620                        PermissionInfo.PROTECTION_DANGEROUS);
621                if (userOnly) {
622                    System.out.println("Normal Permissions:");
623                    System.out.println("");
624                    doListPermissions(groupList, groups, labels, summary,
625                            PermissionInfo.PROTECTION_NORMAL,
626                            PermissionInfo.PROTECTION_NORMAL);
627                }
628            } else if (userOnly) {
629                System.out.println("Dangerous and Normal Permissions:");
630                System.out.println("");
631                doListPermissions(groupList, groups, labels, summary,
632                        PermissionInfo.PROTECTION_NORMAL,
633                        PermissionInfo.PROTECTION_DANGEROUS);
634            } else {
635                System.out.println("All Permissions:");
636                System.out.println("");
637                doListPermissions(groupList, groups, labels, summary,
638                        -10000, 10000);
639            }
640        } catch (RemoteException e) {
641            System.err.println(e.toString());
642            System.err.println(PM_NOT_RUNNING_ERR);
643        }
644    }
645
646    private void doListPermissions(ArrayList<String> groupList,
647            boolean groups, boolean labels, boolean summary,
648            int startProtectionLevel, int endProtectionLevel)
649            throws RemoteException {
650        for (int i=0; i<groupList.size(); i++) {
651            String groupName = groupList.get(i);
652            String prefix = "";
653            if (groups) {
654                if (i > 0) System.out.println("");
655                if (groupName != null) {
656                    PermissionGroupInfo pgi = mPm.getPermissionGroupInfo(
657                            groupName, 0);
658                    if (summary) {
659                        Resources res = getResources(pgi);
660                        if (res != null) {
661                            System.out.print(loadText(pgi, pgi.labelRes,
662                                    pgi.nonLocalizedLabel) + ": ");
663                        } else {
664                            System.out.print(pgi.name + ": ");
665
666                        }
667                    } else {
668                        System.out.println((labels ? "+ " : "")
669                                + "group:" + pgi.name);
670                        if (labels) {
671                            System.out.println("  package:" + pgi.packageName);
672                            Resources res = getResources(pgi);
673                            if (res != null) {
674                                System.out.println("  label:"
675                                        + loadText(pgi, pgi.labelRes,
676                                                pgi.nonLocalizedLabel));
677                                System.out.println("  description:"
678                                        + loadText(pgi, pgi.descriptionRes,
679                                                pgi.nonLocalizedDescription));
680                            }
681                        }
682                    }
683                } else {
684                    System.out.println(((labels && !summary)
685                            ? "+ " : "") + "ungrouped:");
686                }
687                prefix = "  ";
688            }
689            List<PermissionInfo> ps = mPm.queryPermissionsByGroup(
690                    groupList.get(i), 0);
691            int count = ps.size();
692            boolean first = true;
693            for (int p = 0 ; p < count ; p++) {
694                PermissionInfo pi = ps.get(p);
695                if (groups && groupName == null && pi.group != null) {
696                    continue;
697                }
698                final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
699                if (base < startProtectionLevel
700                        || base > endProtectionLevel) {
701                    continue;
702                }
703                if (summary) {
704                    if (first) {
705                        first = false;
706                    } else {
707                        System.out.print(", ");
708                    }
709                    Resources res = getResources(pi);
710                    if (res != null) {
711                        System.out.print(loadText(pi, pi.labelRes,
712                                pi.nonLocalizedLabel));
713                    } else {
714                        System.out.print(pi.name);
715                    }
716                } else {
717                    System.out.println(prefix + (labels ? "+ " : "")
718                            + "permission:" + pi.name);
719                    if (labels) {
720                        System.out.println(prefix + "  package:" + pi.packageName);
721                        Resources res = getResources(pi);
722                        if (res != null) {
723                            System.out.println(prefix + "  label:"
724                                    + loadText(pi, pi.labelRes,
725                                            pi.nonLocalizedLabel));
726                            System.out.println(prefix + "  description:"
727                                    + loadText(pi, pi.descriptionRes,
728                                            pi.nonLocalizedDescription));
729                        }
730                        System.out.println(prefix + "  protectionLevel:"
731                                + PermissionInfo.protectionToString(pi.protectionLevel));
732                    }
733                }
734            }
735
736            if (summary) {
737                System.out.println("");
738            }
739        }
740    }
741
742    private void runPath() {
743        String pkg = nextArg();
744        if (pkg == null) {
745            System.err.println("Error: no package specified");
746            return;
747        }
748        displayPackageFilePath(pkg);
749    }
750
751    private void runDump() {
752        String pkg = nextArg();
753        if (pkg == null) {
754            System.err.println("Error: no package specified");
755            return;
756        }
757        ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg);
758    }
759
760    class LocalPackageInstallObserver extends PackageInstallObserver {
761        boolean finished;
762        int result;
763        String extraPermission;
764        String extraPackage;
765
766        @Override
767        public void onPackageInstalled(String name, int status, String msg, Bundle extras) {
768            synchronized (this) {
769                finished = true;
770                result = status;
771                if (status == PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION) {
772                    extraPermission = extras.getString(
773                            PackageManager.EXTRA_FAILURE_EXISTING_PERMISSION);
774                    extraPackage = extras.getString(
775                            PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
776                }
777                notifyAll();
778            }
779        }
780    }
781
782    /**
783     * Converts a failure code into a string by using reflection to find a matching constant
784     * in PackageManager.
785     */
786    private String installFailureToString(LocalPackageInstallObserver obs) {
787        final int result = obs.result;
788        Field[] fields = PackageManager.class.getFields();
789        for (Field f: fields) {
790            if (f.getType() == int.class) {
791                int modifiers = f.getModifiers();
792                // only look at public final static fields.
793                if (((modifiers & Modifier.FINAL) != 0) &&
794                        ((modifiers & Modifier.PUBLIC) != 0) &&
795                        ((modifiers & Modifier.STATIC) != 0)) {
796                    String fieldName = f.getName();
797                    if (fieldName.startsWith("INSTALL_FAILED_") ||
798                            fieldName.startsWith("INSTALL_PARSE_FAILED_")) {
799                        // get the int value and compare it to result.
800                        try {
801                            if (result == f.getInt(null)) {
802                                StringBuilder sb = new StringBuilder(64);
803                                sb.append(fieldName);
804                                if (obs.extraPermission != null) {
805                                    sb.append(" perm=");
806                                    sb.append(obs.extraPermission);
807                                }
808                                if (obs.extraPackage != null) {
809                                    sb.append(" pkg=" + obs.extraPackage);
810                                }
811                                return sb.toString();
812                            }
813                        } catch (IllegalAccessException e) {
814                            // this shouldn't happen since we only look for public static fields.
815                        }
816                    }
817                }
818            }
819        }
820
821        // couldn't find a matching constant? return the value
822        return Integer.toString(result);
823    }
824
825    private void runSetInstallLocation() {
826        int loc;
827
828        String arg = nextArg();
829        if (arg == null) {
830            System.err.println("Error: no install location specified.");
831            return;
832        }
833        try {
834            loc = Integer.parseInt(arg);
835        } catch (NumberFormatException e) {
836            System.err.println("Error: install location has to be a number.");
837            return;
838        }
839        try {
840            if (!mPm.setInstallLocation(loc)) {
841                System.err.println("Error: install location has to be a number.");
842            }
843        } catch (RemoteException e) {
844            System.err.println(e.toString());
845            System.err.println(PM_NOT_RUNNING_ERR);
846        }
847    }
848
849    private void runGetInstallLocation() {
850        try {
851            int loc = mPm.getInstallLocation();
852            String locStr = "invalid";
853            if (loc == PackageHelper.APP_INSTALL_AUTO) {
854                locStr = "auto";
855            } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
856                locStr = "internal";
857            } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
858                locStr = "external";
859            }
860            System.out.println(loc + "[" + locStr + "]");
861        } catch (RemoteException e) {
862            System.err.println(e.toString());
863            System.err.println(PM_NOT_RUNNING_ERR);
864        }
865    }
866
867    private void runInstall() {
868        int installFlags = PackageManager.INSTALL_ALL_USERS;
869        String installerPackageName = null;
870
871        String opt;
872
873        String originatingUriString = null;
874        String referrer = null;
875        String abi = null;
876
877        while ((opt=nextOption()) != null) {
878            if (opt.equals("-l")) {
879                installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
880            } else if (opt.equals("-r")) {
881                installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
882            } else if (opt.equals("-i")) {
883                installerPackageName = nextOptionData();
884                if (installerPackageName == null) {
885                    System.err.println("Error: no value specified for -i");
886                    return;
887                }
888            } else if (opt.equals("-t")) {
889                installFlags |= PackageManager.INSTALL_ALLOW_TEST;
890            } else if (opt.equals("-s")) {
891                // Override if -s option is specified.
892                installFlags |= PackageManager.INSTALL_EXTERNAL;
893            } else if (opt.equals("-f")) {
894                // Override if -s option is specified.
895                installFlags |= PackageManager.INSTALL_INTERNAL;
896            } else if (opt.equals("-d")) {
897                installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
898            } else if (opt.equals("--originating-uri")) {
899                originatingUriString = nextOptionData();
900                if (originatingUriString == null) {
901                    System.err.println("Error: must supply argument for --originating-uri");
902                    return;
903                }
904            } else if (opt.equals("--referrer")) {
905                referrer = nextOptionData();
906                if (referrer == null) {
907                    System.err.println("Error: must supply argument for --referrer");
908                    return;
909                }
910            } else if (opt.equals("--abi")) {
911                abi = checkAbiArgument(nextOptionData());
912            } else {
913                System.err.println("Error: Unknown option: " + opt);
914                return;
915            }
916        }
917
918        final Uri verificationURI;
919        final Uri originatingURI;
920        final Uri referrerURI;
921
922        if (originatingUriString != null) {
923            originatingURI = Uri.parse(originatingUriString);
924        } else {
925            originatingURI = null;
926        }
927
928        if (referrer != null) {
929            referrerURI = Uri.parse(referrer);
930        } else {
931            referrerURI = null;
932        }
933
934        // Populate apkURI, must be present
935        final String apkFilePath = nextArg();
936        System.err.println("\tpkg: " + apkFilePath);
937        if (apkFilePath == null) {
938            System.err.println("Error: no package specified");
939            return;
940        }
941
942        // Populate verificationURI, optionally present
943        final String verificationFilePath = nextArg();
944        if (verificationFilePath != null) {
945            System.err.println("\tver: " + verificationFilePath);
946            verificationURI = Uri.fromFile(new File(verificationFilePath));
947        } else {
948            verificationURI = null;
949        }
950
951        LocalPackageInstallObserver obs = new LocalPackageInstallObserver();
952        try {
953            VerificationParams verificationParams = new VerificationParams(verificationURI,
954                    originatingURI, referrerURI, VerificationParams.NO_UID, null);
955
956            mPm.installPackage(apkFilePath, obs.getBinder(), installFlags, installerPackageName,
957                    verificationParams, abi);
958
959            synchronized (obs) {
960                while (!obs.finished) {
961                    try {
962                        obs.wait();
963                    } catch (InterruptedException e) {
964                    }
965                }
966                if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
967                    System.out.println("Success");
968                } else {
969                    System.err.println("Failure ["
970                            + installFailureToString(obs)
971                            + "]");
972                }
973            }
974        } catch (RemoteException e) {
975            System.err.println(e.toString());
976            System.err.println(PM_NOT_RUNNING_ERR);
977        }
978    }
979
980    private void runInstallCreate() throws RemoteException {
981        String installerPackageName = null;
982
983        final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
984        params.installFlags = PackageManager.INSTALL_ALL_USERS;
985
986        String opt;
987        while ((opt = nextOption()) != null) {
988            if (opt.equals("-l")) {
989                params.installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
990            } else if (opt.equals("-r")) {
991                params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
992            } else if (opt.equals("-i")) {
993                installerPackageName = nextArg();
994                if (installerPackageName == null) {
995                    throw new IllegalArgumentException("Missing installer package");
996                }
997            } else if (opt.equals("-t")) {
998                params.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
999            } else if (opt.equals("-s")) {
1000                params.installFlags |= PackageManager.INSTALL_EXTERNAL;
1001            } else if (opt.equals("-f")) {
1002                params.installFlags |= PackageManager.INSTALL_INTERNAL;
1003            } else if (opt.equals("-d")) {
1004                params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
1005            } else if (opt.equals("-p")) {
1006                params.mode = SessionParams.MODE_INHERIT_EXISTING;
1007            } else if (opt.equals("-S")) {
1008                params.setSize(Long.parseLong(nextOptionData()));
1009            } else if (opt.equals("--abi")) {
1010                params.abiOverride = checkAbiArgument(nextOptionData());
1011            } else {
1012                throw new IllegalArgumentException("Unknown option " + opt);
1013            }
1014        }
1015
1016        final int sessionId = mInstaller.createSession(params, installerPackageName,
1017                UserHandle.USER_OWNER);
1018
1019        // NOTE: adb depends on parsing this string
1020        System.out.println("Success: created install session [" + sessionId + "]");
1021    }
1022
1023    private void runInstallWrite() throws IOException, RemoteException {
1024        long sizeBytes = -1;
1025
1026        String opt;
1027        while ((opt = nextOption()) != null) {
1028            if (opt.equals("-S")) {
1029                sizeBytes = Long.parseLong(nextOptionData());
1030            } else {
1031                throw new IllegalArgumentException("Unknown option: " + opt);
1032            }
1033        }
1034
1035        final int sessionId = Integer.parseInt(nextArg());
1036        final String splitName = nextArg();
1037
1038        String path = nextArg();
1039        if ("-".equals(path)) {
1040            path = null;
1041        } else if (path != null) {
1042            final File file = new File(path);
1043            if (file.isFile()) {
1044                sizeBytes = file.length();
1045            }
1046        }
1047
1048        final SessionInfo info = mInstaller.getSessionInfo(sessionId);
1049
1050        PackageInstaller.Session session = null;
1051        InputStream in = null;
1052        OutputStream out = null;
1053        try {
1054            session = new PackageInstaller.Session(mInstaller.openSession(sessionId));
1055
1056            if (path != null) {
1057                in = new FileInputStream(path);
1058            } else {
1059                in = new SizedInputStream(System.in, sizeBytes);
1060            }
1061            out = session.openWrite(splitName, 0, sizeBytes);
1062
1063            int total = 0;
1064            byte[] buffer = new byte[65536];
1065            int c;
1066            while ((c = in.read(buffer)) != -1) {
1067                total += c;
1068                out.write(buffer, 0, c);
1069
1070                if (info.sizeBytes > 0) {
1071                    final float fraction = ((float) c / (float) info.sizeBytes);
1072                    session.addProgress(fraction);
1073                }
1074            }
1075            session.fsync(out);
1076
1077            System.out.println("Success: streamed " + total + " bytes");
1078        } finally {
1079            IoUtils.closeQuietly(out);
1080            IoUtils.closeQuietly(in);
1081            IoUtils.closeQuietly(session);
1082        }
1083    }
1084
1085    private void runInstallCommit() throws RemoteException {
1086        final int sessionId = Integer.parseInt(nextArg());
1087
1088        PackageInstaller.Session session = null;
1089        try {
1090            session = new PackageInstaller.Session(mInstaller.openSession(sessionId));
1091
1092            final LocalIntentReceiver receiver = new LocalIntentReceiver();
1093            session.commit(receiver.getIntentSender());
1094
1095            final Intent result = receiver.getResult();
1096            final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1097                    PackageInstaller.STATUS_FAILURE);
1098            if (status == PackageInstaller.STATUS_SUCCESS) {
1099                System.out.println("Success");
1100            } else {
1101                Log.e(TAG, "Failure details: " + result.getExtras());
1102                System.out.println("Failure ["
1103                        + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
1104                return;
1105            }
1106        } finally {
1107            IoUtils.closeQuietly(session);
1108        }
1109    }
1110
1111    private void runInstallAbandon() throws RemoteException {
1112        final int sessionId = Integer.parseInt(nextArg());
1113
1114        PackageInstaller.Session session = null;
1115        try {
1116            session = new PackageInstaller.Session(mInstaller.openSession(sessionId));
1117            session.abandon();
1118            System.out.println("Success");
1119        } finally {
1120            IoUtils.closeQuietly(session);
1121        }
1122    }
1123
1124    private void runSetInstaller() throws RemoteException {
1125        final String targetPackage = nextArg();
1126        final String installerPackageName = nextArg();
1127
1128        if (targetPackage == null || installerPackageName == null) {
1129            throw new IllegalArgumentException(
1130                    "must provide both target and installer package names");
1131        }
1132
1133        mPm.setInstallerPackageName(targetPackage, installerPackageName);
1134        System.out.println("Success");
1135    }
1136
1137    public void runCreateUser() {
1138        String name;
1139        int userId = -1;
1140        int flags = 0;
1141        String opt;
1142        while ((opt = nextOption()) != null) {
1143            if ("--profileOf".equals(opt)) {
1144                String optionData = nextOptionData();
1145                if (optionData == null || !isNumber(optionData)) {
1146                    System.err.println("Error: no USER_ID specified");
1147                    showUsage();
1148                    return;
1149                } else {
1150                    userId = Integer.parseInt(optionData);
1151                }
1152            } else if ("--managed".equals(opt)) {
1153                flags |= UserInfo.FLAG_MANAGED_PROFILE;
1154            } else {
1155                System.err.println("Error: unknown option " + opt);
1156                showUsage();
1157                return;
1158            }
1159        }
1160        String arg = nextArg();
1161        if (arg == null) {
1162            System.err.println("Error: no user name specified.");
1163            return;
1164        }
1165        name = arg;
1166        try {
1167            UserInfo info = null;
1168            if (userId < 0) {
1169                info = mUm.createUser(name, flags);
1170            } else {
1171                if (Process.myUid() != 0) {
1172                    System.err.println("Error: not running as root.");
1173                    return;
1174                }
1175                info = mUm.createProfileForUser(name, flags, userId);
1176            }
1177            if (info != null) {
1178                System.out.println("Success: created user id " + info.id);
1179            } else {
1180                System.err.println("Error: couldn't create User.");
1181            }
1182        } catch (RemoteException e) {
1183            System.err.println(e.toString());
1184            System.err.println(PM_NOT_RUNNING_ERR);
1185        }
1186
1187    }
1188
1189    public void runRemoveUser() {
1190        int userId;
1191        String arg = nextArg();
1192        if (arg == null) {
1193            System.err.println("Error: no user id specified.");
1194            return;
1195        }
1196        try {
1197            userId = Integer.parseInt(arg);
1198        } catch (NumberFormatException e) {
1199            System.err.println("Error: user id '" + arg + "' is not a number.");
1200            return;
1201        }
1202        try {
1203            if (mUm.removeUser(userId)) {
1204                System.out.println("Success: removed user");
1205            } else {
1206                System.err.println("Error: couldn't remove user id " + userId);
1207            }
1208        } catch (RemoteException e) {
1209            System.err.println(e.toString());
1210            System.err.println(PM_NOT_RUNNING_ERR);
1211        }
1212    }
1213
1214    public void runListUsers() {
1215        try {
1216            IActivityManager am = ActivityManagerNative.getDefault();
1217
1218            List<UserInfo> users = mUm.getUsers(false);
1219            if (users == null) {
1220                System.err.println("Error: couldn't get users");
1221            } else {
1222                System.out.println("Users:");
1223                for (int i = 0; i < users.size(); i++) {
1224                    String running = am.isUserRunning(users.get(i).id, false) ? " running" : "";
1225                    System.out.println("\t" + users.get(i).toString() + running);
1226                }
1227            }
1228        } catch (RemoteException e) {
1229            System.err.println(e.toString());
1230            System.err.println(PM_NOT_RUNNING_ERR);
1231        }
1232    }
1233
1234    public void runGetMaxUsers() {
1235        System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers());
1236    }
1237
1238    public void runForceDexOpt() {
1239        final String packageName = nextArg();
1240        try {
1241            mPm.forceDexOpt(packageName);
1242        } catch (RemoteException e) {
1243            throw e.rethrowAsRuntimeException();
1244        }
1245    }
1246
1247    private void runUninstall() throws RemoteException {
1248        int flags = 0;
1249        int userId = UserHandle.USER_ALL;
1250
1251        String opt;
1252        while ((opt=nextOption()) != null) {
1253            if (opt.equals("-k")) {
1254                flags |= PackageManager.DELETE_KEEP_DATA;
1255            } else if (opt.equals("--user")) {
1256                String param = nextArg();
1257                if (isNumber(param)) {
1258                    userId = Integer.parseInt(param);
1259                } else {
1260                    showUsage();
1261                    System.err.println("Error: Invalid user: " + param);
1262                    return;
1263                }
1264            } else {
1265                System.err.println("Error: Unknown option: " + opt);
1266                return;
1267            }
1268        }
1269
1270        String pkg = nextArg();
1271        if (pkg == null) {
1272            System.err.println("Error: no package specified");
1273            showUsage();
1274            return;
1275        }
1276
1277        if (userId == UserHandle.USER_ALL) {
1278            userId = UserHandle.USER_OWNER;
1279            flags |= PackageManager.DELETE_ALL_USERS;
1280        } else {
1281            PackageInfo info;
1282            try {
1283                info = mPm.getPackageInfo(pkg, 0, userId);
1284            } catch (RemoteException e) {
1285                System.err.println(e.toString());
1286                System.err.println(PM_NOT_RUNNING_ERR);
1287                return;
1288            }
1289            if (info == null) {
1290                System.err.println("Failure - not installed for " + userId);
1291                return;
1292            }
1293            final boolean isSystem =
1294                    (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
1295            // If we are being asked to delete a system app for just one
1296            // user set flag so it disables rather than reverting to system
1297            // version of the app.
1298            if (isSystem) {
1299                flags |= PackageManager.DELETE_SYSTEM_APP;
1300            }
1301        }
1302
1303        final LocalIntentReceiver receiver = new LocalIntentReceiver();
1304        mInstaller.uninstall(pkg, flags, receiver.getIntentSender(), userId);
1305
1306        final Intent result = receiver.getResult();
1307        final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1308                PackageInstaller.STATUS_FAILURE);
1309        if (status == PackageInstaller.STATUS_SUCCESS) {
1310            System.out.println("Success");
1311        } else {
1312            Log.e(TAG, "Failure details: " + result.getExtras());
1313            System.out.println("Failure ["
1314                    + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
1315        }
1316    }
1317
1318    static class ClearDataObserver extends IPackageDataObserver.Stub {
1319        boolean finished;
1320        boolean result;
1321
1322        @Override
1323        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1324            synchronized (this) {
1325                finished = true;
1326                result = succeeded;
1327                notifyAll();
1328            }
1329        }
1330    }
1331
1332    private void runClear() {
1333        int userId = 0;
1334        String option = nextOption();
1335        if (option != null && option.equals("--user")) {
1336            String optionData = nextOptionData();
1337            if (optionData == null || !isNumber(optionData)) {
1338                System.err.println("Error: no USER_ID specified");
1339                showUsage();
1340                return;
1341            } else {
1342                userId = Integer.parseInt(optionData);
1343            }
1344        }
1345
1346        String pkg = nextArg();
1347        if (pkg == null) {
1348            System.err.println("Error: no package specified");
1349            showUsage();
1350            return;
1351        }
1352
1353        ClearDataObserver obs = new ClearDataObserver();
1354        try {
1355            ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, userId);
1356            synchronized (obs) {
1357                while (!obs.finished) {
1358                    try {
1359                        obs.wait();
1360                    } catch (InterruptedException e) {
1361                    }
1362                }
1363            }
1364
1365            if (obs.result) {
1366                System.err.println("Success");
1367            } else {
1368                System.err.println("Failed");
1369            }
1370        } catch (RemoteException e) {
1371            System.err.println(e.toString());
1372            System.err.println(PM_NOT_RUNNING_ERR);
1373        }
1374    }
1375
1376    private static String enabledSettingToString(int state) {
1377        switch (state) {
1378            case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
1379                return "default";
1380            case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
1381                return "enabled";
1382            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
1383                return "disabled";
1384            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
1385                return "disabled-user";
1386            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
1387                return "disabled-until-used";
1388        }
1389        return "unknown";
1390    }
1391
1392    private static boolean isNumber(String s) {
1393        try {
1394            Integer.parseInt(s);
1395        } catch (NumberFormatException nfe) {
1396            return false;
1397        }
1398        return true;
1399    }
1400
1401    private void runSetEnabledSetting(int state) {
1402        int userId = 0;
1403        String option = nextOption();
1404        if (option != null && option.equals("--user")) {
1405            String optionData = nextOptionData();
1406            if (optionData == null || !isNumber(optionData)) {
1407                System.err.println("Error: no USER_ID specified");
1408                showUsage();
1409                return;
1410            } else {
1411                userId = Integer.parseInt(optionData);
1412            }
1413        }
1414
1415        String pkg = nextArg();
1416        if (pkg == null) {
1417            System.err.println("Error: no package or component specified");
1418            showUsage();
1419            return;
1420        }
1421        ComponentName cn = ComponentName.unflattenFromString(pkg);
1422        if (cn == null) {
1423            try {
1424                mPm.setApplicationEnabledSetting(pkg, state, 0, userId,
1425                        "shell:" + android.os.Process.myUid());
1426                System.err.println("Package " + pkg + " new state: "
1427                        + enabledSettingToString(
1428                        mPm.getApplicationEnabledSetting(pkg, userId)));
1429            } catch (RemoteException e) {
1430                System.err.println(e.toString());
1431                System.err.println(PM_NOT_RUNNING_ERR);
1432            }
1433        } else {
1434            try {
1435                mPm.setComponentEnabledSetting(cn, state, 0, userId);
1436                System.err.println("Component " + cn.toShortString() + " new state: "
1437                        + enabledSettingToString(
1438                        mPm.getComponentEnabledSetting(cn, userId)));
1439            } catch (RemoteException e) {
1440                System.err.println(e.toString());
1441                System.err.println(PM_NOT_RUNNING_ERR);
1442            }
1443        }
1444    }
1445
1446    private void runSetHiddenSetting(boolean state) {
1447        int userId = 0;
1448        String option = nextOption();
1449        if (option != null && option.equals("--user")) {
1450            String optionData = nextOptionData();
1451            if (optionData == null || !isNumber(optionData)) {
1452                System.err.println("Error: no USER_ID specified");
1453                showUsage();
1454                return;
1455            } else {
1456                userId = Integer.parseInt(optionData);
1457            }
1458        }
1459
1460        String pkg = nextArg();
1461        if (pkg == null) {
1462            System.err.println("Error: no package or component specified");
1463            showUsage();
1464            return;
1465        }
1466        try {
1467            mPm.setApplicationHiddenSettingAsUser(pkg, state, userId);
1468            System.err.println("Package " + pkg + " new hidden state: "
1469                    + mPm.getApplicationHiddenSettingAsUser(pkg, userId));
1470        } catch (RemoteException e) {
1471            System.err.println(e.toString());
1472            System.err.println(PM_NOT_RUNNING_ERR);
1473        }
1474    }
1475
1476    private void runGrantRevokePermission(boolean grant) {
1477        String pkg = nextArg();
1478        if (pkg == null) {
1479            System.err.println("Error: no package specified");
1480            showUsage();
1481            return;
1482        }
1483        String perm = nextArg();
1484        if (perm == null) {
1485            System.err.println("Error: no permission specified");
1486            showUsage();
1487            return;
1488        }
1489        try {
1490            if (grant) {
1491                mPm.grantPermission(pkg, perm);
1492            } else {
1493                mPm.revokePermission(pkg, perm);
1494            }
1495        } catch (RemoteException e) {
1496            System.err.println(e.toString());
1497            System.err.println(PM_NOT_RUNNING_ERR);
1498        } catch (IllegalArgumentException e) {
1499            System.err.println("Bad argument: " + e.toString());
1500            showUsage();
1501        } catch (SecurityException e) {
1502            System.err.println("Operation not allowed: " + e.toString());
1503        }
1504    }
1505
1506    private void runSetPermissionEnforced() {
1507        final String permission = nextArg();
1508        if (permission == null) {
1509            System.err.println("Error: no permission specified");
1510            showUsage();
1511            return;
1512        }
1513        final String enforcedRaw = nextArg();
1514        if (enforcedRaw == null) {
1515            System.err.println("Error: no enforcement specified");
1516            showUsage();
1517            return;
1518        }
1519        final boolean enforced = Boolean.parseBoolean(enforcedRaw);
1520        try {
1521            mPm.setPermissionEnforced(permission, enforced);
1522        } catch (RemoteException e) {
1523            System.err.println(e.toString());
1524            System.err.println(PM_NOT_RUNNING_ERR);
1525        } catch (IllegalArgumentException e) {
1526            System.err.println("Bad argument: " + e.toString());
1527            showUsage();
1528        } catch (SecurityException e) {
1529            System.err.println("Operation not allowed: " + e.toString());
1530        }
1531    }
1532
1533    static class ClearCacheObserver extends IPackageDataObserver.Stub {
1534        boolean finished;
1535        boolean result;
1536
1537        @Override
1538        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1539            synchronized (this) {
1540                finished = true;
1541                result = succeeded;
1542                notifyAll();
1543            }
1544        }
1545
1546    }
1547
1548    private void runTrimCaches() {
1549        String size = nextArg();
1550        if (size == null) {
1551            System.err.println("Error: no size specified");
1552            showUsage();
1553            return;
1554        }
1555        int len = size.length();
1556        long multiplier = 1;
1557        if (len > 1) {
1558            char c = size.charAt(len-1);
1559            if (c == 'K' || c == 'k') {
1560                multiplier = 1024L;
1561            } else if (c == 'M' || c == 'm') {
1562                multiplier = 1024L*1024L;
1563            } else if (c == 'G' || c == 'g') {
1564                multiplier = 1024L*1024L*1024L;
1565            } else {
1566                System.err.println("Invalid suffix: " + c);
1567                showUsage();
1568                return;
1569            }
1570            size = size.substring(0, len-1);
1571        }
1572        long sizeVal;
1573        try {
1574            sizeVal = Long.parseLong(size) * multiplier;
1575        } catch (NumberFormatException e) {
1576            System.err.println("Error: expected number at: " + size);
1577            showUsage();
1578            return;
1579        }
1580        ClearDataObserver obs = new ClearDataObserver();
1581        try {
1582            mPm.freeStorageAndNotify(sizeVal, obs);
1583            synchronized (obs) {
1584                while (!obs.finished) {
1585                    try {
1586                        obs.wait();
1587                    } catch (InterruptedException e) {
1588                    }
1589                }
1590            }
1591        } catch (RemoteException e) {
1592            System.err.println(e.toString());
1593            System.err.println(PM_NOT_RUNNING_ERR);
1594        } catch (IllegalArgumentException e) {
1595            System.err.println("Bad argument: " + e.toString());
1596            showUsage();
1597        } catch (SecurityException e) {
1598            System.err.println("Operation not allowed: " + e.toString());
1599        }
1600    }
1601
1602    /**
1603     * Displays the package file for a package.
1604     * @param pckg
1605     */
1606    private void displayPackageFilePath(String pckg) {
1607        try {
1608            PackageInfo info = mPm.getPackageInfo(pckg, 0, 0);
1609            if (info != null && info.applicationInfo != null) {
1610                System.out.print("package:");
1611                System.out.println(info.applicationInfo.sourceDir);
1612                if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
1613                    for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
1614                        System.out.print("package:");
1615                        System.out.println(splitSourceDir);
1616                    }
1617                }
1618            }
1619        } catch (RemoteException e) {
1620            System.err.println(e.toString());
1621            System.err.println(PM_NOT_RUNNING_ERR);
1622        }
1623    }
1624
1625    private Resources getResources(PackageItemInfo pii) {
1626        Resources res = mResourceCache.get(pii.packageName);
1627        if (res != null) return res;
1628
1629        try {
1630            ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0, 0);
1631            AssetManager am = new AssetManager();
1632            am.addAssetPath(ai.publicSourceDir);
1633            res = new Resources(am, null, null);
1634            mResourceCache.put(pii.packageName, res);
1635            return res;
1636        } catch (RemoteException e) {
1637            System.err.println(e.toString());
1638            System.err.println(PM_NOT_RUNNING_ERR);
1639            return null;
1640        }
1641    }
1642
1643    private static String checkAbiArgument(String abi) {
1644        if (TextUtils.isEmpty(abi)) {
1645            throw new IllegalArgumentException("Missing ABI argument");
1646        }
1647
1648        if ("-".equals(abi)) {
1649            return abi;
1650        }
1651
1652        final String[] supportedAbis = Build.SUPPORTED_ABIS;
1653        for (String supportedAbi : supportedAbis) {
1654            if (supportedAbi.equals(abi)) {
1655                return abi;
1656            }
1657        }
1658
1659        throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
1660    }
1661
1662    private static class LocalIntentReceiver {
1663        private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
1664
1665        private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
1666            @Override
1667            public int send(int code, Intent intent, String resolvedType,
1668                    IIntentReceiver finishedReceiver, String requiredPermission) {
1669                try {
1670                    mResult.offer(intent, 5, TimeUnit.SECONDS);
1671                } catch (InterruptedException e) {
1672                    throw new RuntimeException(e);
1673                }
1674                return 0;
1675            }
1676        };
1677
1678        public IntentSender getIntentSender() {
1679            return new IntentSender((IIntentSender) mLocalSender);
1680        }
1681
1682        public Intent getResult() {
1683            try {
1684                return mResult.poll(30, TimeUnit.SECONDS);
1685            } catch (InterruptedException e) {
1686                throw new RuntimeException(e);
1687            }
1688        }
1689    }
1690
1691    private String nextOption() {
1692        if (mNextArg >= mArgs.length) {
1693            return null;
1694        }
1695        String arg = mArgs[mNextArg];
1696        if (!arg.startsWith("-")) {
1697            return null;
1698        }
1699        mNextArg++;
1700        if (arg.equals("--")) {
1701            return null;
1702        }
1703        if (arg.length() > 1 && arg.charAt(1) != '-') {
1704            if (arg.length() > 2) {
1705                mCurArgData = arg.substring(2);
1706                return arg.substring(0, 2);
1707            } else {
1708                mCurArgData = null;
1709                return arg;
1710            }
1711        }
1712        mCurArgData = null;
1713        return arg;
1714    }
1715
1716    private String nextOptionData() {
1717        if (mCurArgData != null) {
1718            return mCurArgData;
1719        }
1720        if (mNextArg >= mArgs.length) {
1721            return null;
1722        }
1723        String data = mArgs[mNextArg];
1724        mNextArg++;
1725        return data;
1726    }
1727
1728    private String nextArg() {
1729        if (mNextArg >= mArgs.length) {
1730            return null;
1731        }
1732        String arg = mArgs[mNextArg];
1733        mNextArg++;
1734        return arg;
1735    }
1736
1737    private static void showUsage() {
1738        System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]");
1739        System.err.println("       pm list permission-groups");
1740        System.err.println("       pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
1741        System.err.println("       pm list instrumentation [-f] [TARGET-PACKAGE]");
1742        System.err.println("       pm list features");
1743        System.err.println("       pm list libraries");
1744        System.err.println("       pm list users");
1745        System.err.println("       pm path PACKAGE");
1746        System.err.println("       pm dump PACKAGE");
1747        System.err.println("       pm install [-lrtsfd] [-i PACKAGE] [PATH]");
1748        System.err.println("       pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]");
1749        System.err.println("       pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]");
1750        System.err.println("       pm install-commit SESSION_ID");
1751        System.err.println("       pm install-abandon SESSION_ID");
1752        System.err.println("       pm uninstall [-k] [--user USER_ID] PACKAGE");
1753        System.err.println("       pm set-installer PACKAGE INSTALLER");
1754        System.err.println("       pm clear [--user USER_ID] PACKAGE");
1755        System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
1756        System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
1757        System.err.println("       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
1758        System.err.println("       pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
1759        System.err.println("       pm hide [--user USER_ID] PACKAGE_OR_COMPONENT");
1760        System.err.println("       pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
1761        System.err.println("       pm grant PACKAGE PERMISSION");
1762        System.err.println("       pm revoke PACKAGE PERMISSION");
1763        System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
1764        System.err.println("       pm get-install-location");
1765        System.err.println("       pm set-permission-enforced PERMISSION [true|false]");
1766        System.err.println("       pm trim-caches DESIRED_FREE_SPACE");
1767        System.err.println("       pm create-user [--profileOf USER_ID] [--managed] USER_NAME");
1768        System.err.println("       pm remove-user USER_ID");
1769        System.err.println("       pm get-max-users");
1770        System.err.println("");
1771        System.err.println("pm list packages: prints all packages, optionally only");
1772        System.err.println("  those whose package name contains the text in FILTER.  Options:");
1773        System.err.println("    -f: see their associated file.");
1774        System.err.println("    -d: filter to only show disbled packages.");
1775        System.err.println("    -e: filter to only show enabled packages.");
1776        System.err.println("    -s: filter to only show system packages.");
1777        System.err.println("    -3: filter to only show third party packages.");
1778        System.err.println("    -i: see the installer for the packages.");
1779        System.err.println("    -u: also include uninstalled packages.");
1780        System.err.println("");
1781        System.err.println("pm list permission-groups: prints all known permission groups.");
1782        System.err.println("");
1783        System.err.println("pm list permissions: prints all known permissions, optionally only");
1784        System.err.println("  those in GROUP.  Options:");
1785        System.err.println("    -g: organize by group.");
1786        System.err.println("    -f: print all information.");
1787        System.err.println("    -s: short summary.");
1788        System.err.println("    -d: only list dangerous permissions.");
1789        System.err.println("    -u: list only the permissions users will see.");
1790        System.err.println("");
1791        System.err.println("pm list instrumentation: use to list all test packages; optionally");
1792        System.err.println("  supply <TARGET-PACKAGE> to list the test packages for a particular");
1793        System.err.println("  application.  Options:");
1794        System.err.println("    -f: list the .apk file for the test package.");
1795        System.err.println("");
1796        System.err.println("pm list features: prints all features of the system.");
1797        System.err.println("");
1798        System.err.println("pm list users: prints all users on the system.");
1799        System.err.println("");
1800        System.err.println("pm path: print the path to the .apk of the given PACKAGE.");
1801        System.err.println("");
1802        System.err.println("pm dump: print system state associated with the given PACKAGE.");
1803        System.err.println("");
1804        System.err.println("pm install: install a single legacy package");
1805        System.err.println("pm install-create: create an install session");
1806        System.err.println("    -l: forward lock application");
1807        System.err.println("    -r: replace existing application");
1808        System.err.println("    -t: allow test packages");
1809        System.err.println("    -i: specify the installer package name");
1810        System.err.println("    -s: install application on sdcard");
1811        System.err.println("    -f: install application on internal flash");
1812        System.err.println("    -d: allow version code downgrade");
1813        System.err.println("    -p: partial application install");
1814        System.err.println("    -S: size in bytes of entire session");
1815        System.err.println("");
1816        System.err.println("pm install-write: write a package into existing session; path may");
1817        System.err.println("  be '-' to read from stdin");
1818        System.err.println("    -S: size in bytes of package, required for stdin");
1819        System.err.println("");
1820        System.err.println("pm install-commit: perform install of fully staged session");
1821        System.err.println("pm install-abandon: abandon session");
1822        System.err.println("");
1823        System.err.println("pm set-installer: set installer package name");
1824        System.err.println("");
1825        System.err.println("pm uninstall: removes a package from the system. Options:");
1826        System.err.println("    -k: keep the data and cache directories around after package removal.");
1827        System.err.println("");
1828        System.err.println("pm clear: deletes all data associated with a package.");
1829        System.err.println("");
1830        System.err.println("pm enable, disable, disable-user, disable-until-used: these commands");
1831        System.err.println("  change the enabled state of a given package or component (written");
1832        System.err.println("  as \"package/class\").");
1833        System.err.println("");
1834        System.err.println("pm grant, revoke: these commands either grant or revoke permissions");
1835        System.err.println("  to applications.  Only optional permissions the application has");
1836        System.err.println("  declared can be granted or revoked.");
1837        System.err.println("");
1838        System.err.println("pm get-install-location: returns the current install location.");
1839        System.err.println("    0 [auto]: Let system decide the best location");
1840        System.err.println("    1 [internal]: Install on internal device storage");
1841        System.err.println("    2 [external]: Install on external media");
1842        System.err.println("");
1843        System.err.println("pm set-install-location: changes the default install location.");
1844        System.err.println("  NOTE: this is only intended for debugging; using this can cause");
1845        System.err.println("  applications to break and other undersireable behavior.");
1846        System.err.println("    0 [auto]: Let system decide the best location");
1847        System.err.println("    1 [internal]: Install on internal device storage");
1848        System.err.println("    2 [external]: Install on external media");
1849        System.err.println("");
1850        System.err.println("pm trim-caches: trim cache files to reach the given free space.");
1851        System.err.println("");
1852        System.err.println("pm create-user: create a new user with the given USER_NAME,");
1853        System.err.println("  printing the new user identifier of the user.");
1854        System.err.println("");
1855        System.err.println("pm remove-user: remove the user with the given USER_IDENTIFIER,");
1856        System.err.println("  deleting all data associated with that user");
1857        System.err.println("");
1858    }
1859}
1860