PackageManagerShellCommand.java revision 4f26cb5a36487b3f5b497804faebe16241c15d54
1/*
2 * Copyright (C) 2015 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.server.pm;
18
19import android.app.ActivityManager;
20import android.content.ComponentName;
21import android.content.IIntentReceiver;
22import android.content.IIntentSender;
23import android.content.Intent;
24import android.content.IntentSender;
25import android.content.pm.ApplicationInfo;
26import android.content.pm.FeatureInfo;
27import android.content.pm.IPackageManager;
28import android.content.pm.InstrumentationInfo;
29import android.content.pm.PackageInfo;
30import android.content.pm.PackageInstaller;
31import android.content.pm.PackageItemInfo;
32import android.content.pm.PackageManager;
33import android.content.pm.PackageParser;
34import android.content.pm.PackageParser.ApkLite;
35import android.content.pm.PackageParser.PackageLite;
36import android.content.pm.PackageParser.PackageParserException;
37import android.content.pm.ParceledListSlice;
38import android.content.pm.PermissionGroupInfo;
39import android.content.pm.PermissionInfo;
40import android.content.pm.PackageInstaller.SessionInfo;
41import android.content.pm.PackageInstaller.SessionParams;
42import android.content.pm.ResolveInfo;
43import android.content.res.AssetManager;
44import android.content.res.Resources;
45import android.net.Uri;
46import android.os.Binder;
47import android.os.Build;
48import android.os.Bundle;
49import android.os.RemoteException;
50import android.os.ShellCommand;
51import android.os.SystemProperties;
52import android.os.UserHandle;
53import android.text.TextUtils;
54import android.util.PrintWriterPrinter;
55import com.android.internal.content.PackageHelper;
56import com.android.internal.util.SizedInputStream;
57
58import dalvik.system.DexFile;
59
60import libcore.io.IoUtils;
61
62import java.io.File;
63import java.io.FileInputStream;
64import java.io.IOException;
65import java.io.InputStream;
66import java.io.OutputStream;
67import java.io.PrintWriter;
68import java.net.URISyntaxException;
69import java.util.ArrayList;
70import java.util.Collections;
71import java.util.Comparator;
72import java.util.List;
73import java.util.WeakHashMap;
74import java.util.concurrent.SynchronousQueue;
75import java.util.concurrent.TimeUnit;
76
77class PackageManagerShellCommand extends ShellCommand {
78    final IPackageManager mInterface;
79    final private WeakHashMap<String, Resources> mResourceCache =
80            new WeakHashMap<String, Resources>();
81    int mTargetUser;
82    boolean mBrief;
83    boolean mComponents;
84
85    PackageManagerShellCommand(PackageManagerService service) {
86        mInterface = service;
87    }
88
89    @Override
90    public int onCommand(String cmd) {
91        if (cmd == null) {
92            return handleDefaultCommands(cmd);
93        }
94
95        final PrintWriter pw = getOutPrintWriter();
96        try {
97            switch(cmd) {
98                case "install":
99                    return runInstall();
100                case "install-abandon":
101                case "install-destroy":
102                    return runInstallAbandon();
103                case "install-commit":
104                    return runInstallCommit();
105                case "install-create":
106                    return runInstallCreate();
107                case "install-remove":
108                    return runInstallRemove();
109                case "install-write":
110                    return runInstallWrite();
111                case "compile":
112                    return runCompile();
113                case "dump-profiles":
114                    return runDumpProfiles();
115                case "list":
116                    return runList();
117                case "uninstall":
118                    return runUninstall();
119                case "resolve-activity":
120                    return runResolveActivity();
121                case "query-activities":
122                    return runQueryIntentActivities();
123                case "query-services":
124                    return runQueryIntentServices();
125                case "query-receivers":
126                    return runQueryIntentReceivers();
127                case "suspend":
128                    return runSuspend(true);
129                case "unsuspend":
130                    return runSuspend(false);
131                case "set-home-activity":
132                    return runSetHomeActivity();
133                default:
134                    return handleDefaultCommands(cmd);
135            }
136        } catch (RemoteException e) {
137            pw.println("Remote exception: " + e);
138        }
139        return -1;
140    }
141
142    private int runInstall() throws RemoteException {
143        final PrintWriter pw = getOutPrintWriter();
144        final InstallParams params = makeInstallParams();
145        final String inPath = getNextArg();
146        if (params.sessionParams.sizeBytes < 0 && inPath != null) {
147            File file = new File(inPath);
148            if (file.isFile()) {
149                try {
150                    ApkLite baseApk = PackageParser.parseApkLite(file, 0);
151                    PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null);
152                    params.sessionParams.setSize(
153                            PackageHelper.calculateInstalledSize(pkgLite,false, params.sessionParams.abiOverride));
154                } catch (PackageParserException | IOException e) {
155                    pw.println("Error: Failed to parse APK file : " + e);
156                    return 1;
157                }
158            }
159        }
160
161        final int sessionId = doCreateSession(params.sessionParams,
162                params.installerPackageName, params.userId);
163        boolean abandonSession = true;
164        try {
165            if (inPath == null && params.sessionParams.sizeBytes == 0) {
166                pw.println("Error: must either specify a package size or an APK file");
167                return 1;
168            }
169            if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
170                    false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
171                return 1;
172            }
173            if (doCommitSession(sessionId, false /*logSuccess*/)
174                    != PackageInstaller.STATUS_SUCCESS) {
175                return 1;
176            }
177            abandonSession = false;
178            pw.println("Success");
179            return 0;
180        } finally {
181            if (abandonSession) {
182                try {
183                    doAbandonSession(sessionId, false /*logSuccess*/);
184                } catch (Exception ignore) {
185                }
186            }
187        }
188    }
189
190    private int runSuspend(boolean suspendedState) {
191        final PrintWriter pw = getOutPrintWriter();
192        int userId = UserHandle.USER_SYSTEM;
193        String opt;
194        while ((opt = getNextOption()) != null) {
195            switch (opt) {
196                case "--user":
197                    userId = UserHandle.parseUserArg(getNextArgRequired());
198                    break;
199                default:
200                    pw.println("Error: Unknown option: " + opt);
201                    return 1;
202            }
203        }
204
205        String packageName = getNextArg();
206        if (packageName == null) {
207            pw.println("Error: package name not specified");
208            return 1;
209        }
210
211        try {
212            mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
213                    userId);
214            pw.println("Package " + packageName + " new suspended state: "
215                    + mInterface.isPackageSuspendedForUser(packageName, userId));
216            return 0;
217        } catch (RemoteException | IllegalArgumentException e) {
218            pw.println(e.toString());
219            return 1;
220        }
221    }
222
223    private int runInstallAbandon() throws RemoteException {
224        final int sessionId = Integer.parseInt(getNextArg());
225        return doAbandonSession(sessionId, true /*logSuccess*/);
226    }
227
228    private int runInstallCommit() throws RemoteException {
229        final int sessionId = Integer.parseInt(getNextArg());
230        return doCommitSession(sessionId, true /*logSuccess*/);
231    }
232
233    private int runInstallCreate() throws RemoteException {
234        final PrintWriter pw = getOutPrintWriter();
235        final InstallParams installParams = makeInstallParams();
236        final int sessionId = doCreateSession(installParams.sessionParams,
237                installParams.installerPackageName, installParams.userId);
238
239        // NOTE: adb depends on parsing this string
240        pw.println("Success: created install session [" + sessionId + "]");
241        return 0;
242    }
243
244    private int runInstallWrite() throws RemoteException {
245        long sizeBytes = -1;
246
247        String opt;
248        while ((opt = getNextOption()) != null) {
249            if (opt.equals("-S")) {
250                sizeBytes = Long.parseLong(getNextArg());
251            } else {
252                throw new IllegalArgumentException("Unknown option: " + opt);
253            }
254        }
255
256        final int sessionId = Integer.parseInt(getNextArg());
257        final String splitName = getNextArg();
258        final String path = getNextArg();
259        return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
260    }
261
262    private int runInstallRemove() throws RemoteException {
263        final PrintWriter pw = getOutPrintWriter();
264
265        final int sessionId = Integer.parseInt(getNextArg());
266
267        final String splitName = getNextArg();
268        if (splitName == null) {
269            pw.println("Error: split name not specified");
270            return 1;
271        }
272        return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
273    }
274
275    private int runCompile() throws RemoteException {
276        final PrintWriter pw = getOutPrintWriter();
277        boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
278        boolean forceCompilation = false;
279        boolean allPackages = false;
280        boolean clearProfileData = false;
281        String compilerFilter = null;
282        String compilationReason = null;
283        String checkProfilesRaw = null;
284
285        String opt;
286        while ((opt = getNextOption()) != null) {
287            switch (opt) {
288                case "-a":
289                    allPackages = true;
290                    break;
291                case "-c":
292                    clearProfileData = true;
293                    break;
294                case "-f":
295                    forceCompilation = true;
296                    break;
297                case "-m":
298                    compilerFilter = getNextArgRequired();
299                    break;
300                case "-r":
301                    compilationReason = getNextArgRequired();
302                    break;
303                case "--check-prof":
304                    checkProfilesRaw = getNextArgRequired();
305                    break;
306                case "--reset":
307                    forceCompilation = true;
308                    clearProfileData = true;
309                    compilationReason = "install";
310                    break;
311                default:
312                    pw.println("Error: Unknown option: " + opt);
313                    return 1;
314            }
315        }
316
317        if (checkProfilesRaw != null) {
318            if ("true".equals(checkProfilesRaw)) {
319                checkProfiles = true;
320            } else if ("false".equals(checkProfilesRaw)) {
321                checkProfiles = false;
322            } else {
323                pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
324                return 1;
325            }
326        }
327
328        if (compilerFilter != null && compilationReason != null) {
329            pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " +
330                    "at the same time");
331            return 1;
332        }
333        if (compilerFilter == null && compilationReason == null) {
334            pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " +
335                    "reason (\"-r\") at the same time");
336            return 1;
337        }
338
339        String targetCompilerFilter;
340        if (compilerFilter != null) {
341            if (!DexFile.isValidCompilerFilter(compilerFilter)) {
342                pw.println("Error: \"" + compilerFilter +
343                        "\" is not a valid compilation filter.");
344                return 1;
345            }
346            targetCompilerFilter = compilerFilter;
347        } else {
348            int reason = -1;
349            for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
350                if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
351                        compilationReason)) {
352                    reason = i;
353                    break;
354                }
355            }
356            if (reason == -1) {
357                pw.println("Error: Unknown compilation reason: " + compilationReason);
358                return 1;
359            }
360            targetCompilerFilter =
361                    PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
362        }
363
364
365        List<String> packageNames = null;
366        if (allPackages) {
367            packageNames = mInterface.getAllPackages();
368        } else {
369            String packageName = getNextArg();
370            if (packageName == null) {
371                pw.println("Error: package name not specified");
372                return 1;
373            }
374            packageNames = Collections.singletonList(packageName);
375        }
376
377        List<String> failedPackages = new ArrayList<>();
378        for (String packageName : packageNames) {
379            if (clearProfileData) {
380                mInterface.clearApplicationProfileData(packageName);
381            }
382
383            boolean result = mInterface.performDexOptMode(packageName,
384                    checkProfiles, targetCompilerFilter, forceCompilation);
385            if (!result) {
386                failedPackages.add(packageName);
387            }
388        }
389
390        if (failedPackages.isEmpty()) {
391            pw.println("Success");
392            return 0;
393        } else if (failedPackages.size() == 1) {
394            pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
395            return 1;
396        } else {
397            pw.print("Failure: the following packages could not be compiled: ");
398            boolean is_first = true;
399            for (String packageName : failedPackages) {
400                if (is_first) {
401                    is_first = false;
402                } else {
403                    pw.print(", ");
404                }
405                pw.print(packageName);
406            }
407            pw.println();
408            return 1;
409        }
410    }
411
412    private int runDumpProfiles() throws RemoteException {
413        String packageName = getNextArg();
414        mInterface.dumpProfiles(packageName);
415        return 0;
416    }
417
418    private int runList() throws RemoteException {
419        final PrintWriter pw = getOutPrintWriter();
420        final String type = getNextArg();
421        if (type == null) {
422            pw.println("Error: didn't specify type of data to list");
423            return -1;
424        }
425        switch(type) {
426            case "features":
427                return runListFeatures();
428            case "instrumentation":
429                return runListInstrumentation();
430            case "libraries":
431                return runListLibraries();
432            case "package":
433            case "packages":
434                return runListPackages(false /*showSourceDir*/);
435            case "permission-groups":
436                return runListPermissionGroups();
437            case "permissions":
438                return runListPermissions();
439        }
440        pw.println("Error: unknown list type '" + type + "'");
441        return -1;
442    }
443
444    private int runListFeatures() throws RemoteException {
445        final PrintWriter pw = getOutPrintWriter();
446        final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
447
448        // sort by name
449        Collections.sort(list, new Comparator<FeatureInfo>() {
450            public int compare(FeatureInfo o1, FeatureInfo o2) {
451                if (o1.name == o2.name) return 0;
452                if (o1.name == null) return -1;
453                if (o2.name == null) return 1;
454                return o1.name.compareTo(o2.name);
455            }
456        });
457
458        final int count = (list != null) ? list.size() : 0;
459        for (int p = 0; p < count; p++) {
460            FeatureInfo fi = list.get(p);
461            pw.print("feature:");
462            if (fi.name != null) {
463                pw.print(fi.name);
464                if (fi.version > 0) {
465                    pw.print("=");
466                    pw.print(fi.version);
467                }
468                pw.println();
469            } else {
470                pw.println("reqGlEsVersion=0x"
471                    + Integer.toHexString(fi.reqGlEsVersion));
472            }
473        }
474        return 0;
475    }
476
477    private int runListInstrumentation() throws RemoteException {
478        final PrintWriter pw = getOutPrintWriter();
479        boolean showSourceDir = false;
480        String targetPackage = null;
481
482        try {
483            String opt;
484            while ((opt = getNextArg()) != null) {
485                switch (opt) {
486                    case "-f":
487                        showSourceDir = true;
488                        break;
489                    default:
490                        if (opt.charAt(0) != '-') {
491                            targetPackage = opt;
492                        } else {
493                            pw.println("Error: Unknown option: " + opt);
494                            return -1;
495                        }
496                        break;
497                }
498            }
499        } catch (RuntimeException ex) {
500            pw.println("Error: " + ex.toString());
501            return -1;
502        }
503
504        final List<InstrumentationInfo> list =
505                mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
506
507        // sort by target package
508        Collections.sort(list, new Comparator<InstrumentationInfo>() {
509            public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
510                return o1.targetPackage.compareTo(o2.targetPackage);
511            }
512        });
513
514        final int count = (list != null) ? list.size() : 0;
515        for (int p = 0; p < count; p++) {
516            final InstrumentationInfo ii = list.get(p);
517            pw.print("instrumentation:");
518            if (showSourceDir) {
519                pw.print(ii.sourceDir);
520                pw.print("=");
521            }
522            final ComponentName cn = new ComponentName(ii.packageName, ii.name);
523            pw.print(cn.flattenToShortString());
524            pw.print(" (target=");
525            pw.print(ii.targetPackage);
526            pw.println(")");
527        }
528        return 0;
529    }
530
531    private int runListLibraries() throws RemoteException {
532        final PrintWriter pw = getOutPrintWriter();
533        final List<String> list = new ArrayList<String>();
534        final String[] rawList = mInterface.getSystemSharedLibraryNames();
535        for (int i = 0; i < rawList.length; i++) {
536            list.add(rawList[i]);
537        }
538
539        // sort by name
540        Collections.sort(list, new Comparator<String>() {
541            public int compare(String o1, String o2) {
542                if (o1 == o2) return 0;
543                if (o1 == null) return -1;
544                if (o2 == null) return 1;
545                return o1.compareTo(o2);
546            }
547        });
548
549        final int count = (list != null) ? list.size() : 0;
550        for (int p = 0; p < count; p++) {
551            String lib = list.get(p);
552            pw.print("library:");
553            pw.println(lib);
554        }
555        return 0;
556    }
557
558    private int runListPackages(boolean showSourceDir) throws RemoteException {
559        final PrintWriter pw = getOutPrintWriter();
560        int getFlags = 0;
561        boolean listDisabled = false, listEnabled = false;
562        boolean listSystem = false, listThirdParty = false;
563        boolean listInstaller = false;
564        int userId = UserHandle.USER_SYSTEM;
565        try {
566            String opt;
567            while ((opt = getNextOption()) != null) {
568                switch (opt) {
569                    case "-d":
570                        listDisabled = true;
571                        break;
572                    case "-e":
573                        listEnabled = true;
574                        break;
575                    case "-f":
576                        showSourceDir = true;
577                        break;
578                    case "-i":
579                        listInstaller = true;
580                        break;
581                    case "-l":
582                        // old compat
583                        break;
584                    case "-lf":
585                        showSourceDir = true;
586                        break;
587                    case "-s":
588                        listSystem = true;
589                        break;
590                    case "-u":
591                        getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
592                        break;
593                    case "-3":
594                        listThirdParty = true;
595                        break;
596                    case "--user":
597                        userId = UserHandle.parseUserArg(getNextArgRequired());
598                        break;
599                    default:
600                        pw.println("Error: Unknown option: " + opt);
601                        return -1;
602                }
603            }
604        } catch (RuntimeException ex) {
605            pw.println("Error: " + ex.toString());
606            return -1;
607        }
608
609        final String filter = getNextArg();
610
611        @SuppressWarnings("unchecked")
612        final ParceledListSlice<PackageInfo> slice =
613                mInterface.getInstalledPackages(getFlags, userId);
614        final List<PackageInfo> packages = slice.getList();
615
616        final int count = packages.size();
617        for (int p = 0; p < count; p++) {
618            final PackageInfo info = packages.get(p);
619            if (filter != null && !info.packageName.contains(filter)) {
620                continue;
621            }
622            final boolean isSystem =
623                    (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
624            if ((!listDisabled || !info.applicationInfo.enabled) &&
625                    (!listEnabled || info.applicationInfo.enabled) &&
626                    (!listSystem || isSystem) &&
627                    (!listThirdParty || !isSystem)) {
628                pw.print("package:");
629                if (showSourceDir) {
630                    pw.print(info.applicationInfo.sourceDir);
631                    pw.print("=");
632                }
633                pw.print(info.packageName);
634                if (listInstaller) {
635                    pw.print("  installer=");
636                    pw.print(mInterface.getInstallerPackageName(info.packageName));
637                }
638                pw.println();
639            }
640        }
641        return 0;
642    }
643
644    private int runListPermissionGroups() throws RemoteException {
645        final PrintWriter pw = getOutPrintWriter();
646        final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList();
647
648        final int count = pgs.size();
649        for (int p = 0; p < count ; p++) {
650            final PermissionGroupInfo pgi = pgs.get(p);
651            pw.print("permission group:");
652            pw.println(pgi.name);
653        }
654        return 0;
655    }
656
657    private int runListPermissions() throws RemoteException {
658        final PrintWriter pw = getOutPrintWriter();
659        boolean labels = false;
660        boolean groups = false;
661        boolean userOnly = false;
662        boolean summary = false;
663        boolean dangerousOnly = false;
664        String opt;
665        while ((opt = getNextOption()) != null) {
666            switch (opt) {
667                case "-d":
668                    dangerousOnly = true;
669                    break;
670                case "-f":
671                    labels = true;
672                    break;
673                case "-g":
674                    groups = true;
675                    break;
676                case "-s":
677                    groups = true;
678                    labels = true;
679                    summary = true;
680                    break;
681                case "-u":
682                    userOnly = true;
683                    break;
684                default:
685                    pw.println("Error: Unknown option: " + opt);
686                    return 1;
687            }
688        }
689
690        final ArrayList<String> groupList = new ArrayList<String>();
691        if (groups) {
692            final List<PermissionGroupInfo> infos =
693                    mInterface.getAllPermissionGroups(0 /*flags*/).getList();
694            final int count = infos.size();
695            for (int i = 0; i < count; i++) {
696                groupList.add(infos.get(i).name);
697            }
698            groupList.add(null);
699        } else {
700            final String grp = getNextArg();
701            groupList.add(grp);
702        }
703
704        if (dangerousOnly) {
705            pw.println("Dangerous Permissions:");
706            pw.println("");
707            doListPermissions(groupList, groups, labels, summary,
708                    PermissionInfo.PROTECTION_DANGEROUS,
709                    PermissionInfo.PROTECTION_DANGEROUS);
710            if (userOnly) {
711                pw.println("Normal Permissions:");
712                pw.println("");
713                doListPermissions(groupList, groups, labels, summary,
714                        PermissionInfo.PROTECTION_NORMAL,
715                        PermissionInfo.PROTECTION_NORMAL);
716            }
717        } else if (userOnly) {
718            pw.println("Dangerous and Normal Permissions:");
719            pw.println("");
720            doListPermissions(groupList, groups, labels, summary,
721                    PermissionInfo.PROTECTION_NORMAL,
722                    PermissionInfo.PROTECTION_DANGEROUS);
723        } else {
724            pw.println("All Permissions:");
725            pw.println("");
726            doListPermissions(groupList, groups, labels, summary,
727                    -10000, 10000);
728        }
729        return 0;
730    }
731
732    private int runUninstall() throws RemoteException {
733        final PrintWriter pw = getOutPrintWriter();
734        int flags = 0;
735        int userId = UserHandle.USER_ALL;
736
737        String opt;
738        while ((opt = getNextOption()) != null) {
739            switch (opt) {
740                case "-k":
741                    flags |= PackageManager.DELETE_KEEP_DATA;
742                    break;
743                case "--user":
744                    userId = UserHandle.parseUserArg(getNextArgRequired());
745                    break;
746                default:
747                    pw.println("Error: Unknown option: " + opt);
748                    return 1;
749            }
750        }
751
752        final String packageName = getNextArg();
753        if (packageName == null) {
754            pw.println("Error: package name not specified");
755            return 1;
756        }
757
758        // if a split is specified, just remove it and not the whole package
759        final String splitName = getNextArg();
760        if (splitName != null) {
761            return runRemoveSplit(packageName, splitName);
762        }
763
764        userId = translateUserId(userId, "runUninstall");
765        if (userId == UserHandle.USER_ALL) {
766            userId = UserHandle.USER_SYSTEM;
767            flags |= PackageManager.DELETE_ALL_USERS;
768        } else {
769            final PackageInfo info = mInterface.getPackageInfo(packageName, 0, userId);
770            if (info == null) {
771                pw.println("Failure [not installed for " + userId + "]");
772                return 1;
773            }
774            final boolean isSystem =
775                    (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
776            // If we are being asked to delete a system app for just one
777            // user set flag so it disables rather than reverting to system
778            // version of the app.
779            if (isSystem) {
780                flags |= PackageManager.DELETE_SYSTEM_APP;
781            }
782        }
783
784        final LocalIntentReceiver receiver = new LocalIntentReceiver();
785        mInterface.getPackageInstaller().uninstall(packageName, null /*callerPackageName*/, flags,
786                receiver.getIntentSender(), userId);
787
788        final Intent result = receiver.getResult();
789        final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
790                PackageInstaller.STATUS_FAILURE);
791        if (status == PackageInstaller.STATUS_SUCCESS) {
792            pw.println("Success");
793            return 0;
794        } else {
795            pw.println("Failure ["
796                    + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
797            return 1;
798        }
799    }
800
801    private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
802        final PrintWriter pw = getOutPrintWriter();
803        final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
804        sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
805        sessionParams.appPackageName = packageName;
806        final int sessionId =
807                doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
808        boolean abandonSession = true;
809        try {
810            if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
811                    != PackageInstaller.STATUS_SUCCESS) {
812                return 1;
813            }
814            if (doCommitSession(sessionId, false /*logSuccess*/)
815                    != PackageInstaller.STATUS_SUCCESS) {
816                return 1;
817            }
818            abandonSession = false;
819            pw.println("Success");
820            return 0;
821        } finally {
822            if (abandonSession) {
823                try {
824                    doAbandonSession(sessionId, false /*logSuccess*/);
825                } catch (Exception ignore) {
826                }
827            }
828        }
829    }
830
831    private Intent parseIntentAndUser() throws URISyntaxException {
832        mTargetUser = UserHandle.USER_CURRENT;
833        mBrief = false;
834        mComponents = false;
835        Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
836            @Override
837            public boolean handleOption(String opt, ShellCommand cmd) {
838                if ("--user".equals(opt)) {
839                    mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
840                    return true;
841                } else if ("--brief".equals(opt)) {
842                    mBrief = true;
843                    return true;
844                } else if ("--components".equals(opt)) {
845                    mComponents = true;
846                    return true;
847                }
848                return false;
849            }
850        });
851        mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
852                Binder.getCallingUid(), mTargetUser, false, false, null, null);
853        return intent;
854    }
855
856    private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri,
857            boolean brief, boolean components) {
858        if (brief || components) {
859            final ComponentName comp;
860            if (ri.activityInfo != null) {
861                comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
862            } else if (ri.serviceInfo != null) {
863                comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
864            } else if (ri.providerInfo != null) {
865                comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name);
866            } else {
867                comp = null;
868            }
869            if (comp != null) {
870                if (!components) {
871                    pr.println(prefix + "priority=" + ri.priority
872                            + " preferredOrder=" + ri.preferredOrder
873                            + " match=0x" + Integer.toHexString(ri.match)
874                            + " specificIndex=" + ri.specificIndex
875                            + " isDefault=" + ri.isDefault);
876                }
877                pr.println(prefix + comp.flattenToShortString());
878                return;
879            }
880        }
881        ri.dump(pr, prefix);
882    }
883
884    private int runResolveActivity() {
885        Intent intent;
886        try {
887            intent = parseIntentAndUser();
888        } catch (URISyntaxException e) {
889            throw new RuntimeException(e.getMessage(), e);
890        }
891        try {
892            ResolveInfo ri = mInterface.resolveIntent(intent, null, 0, mTargetUser);
893            PrintWriter pw = getOutPrintWriter();
894            if (ri == null) {
895                pw.println("No activity found");
896            } else {
897                PrintWriterPrinter pr = new PrintWriterPrinter(pw);
898                printResolveInfo(pr, "", ri, mBrief, mComponents);
899            }
900        } catch (RemoteException e) {
901            throw new RuntimeException("Failed calling service", e);
902        }
903        return 0;
904    }
905
906    private int runQueryIntentActivities() {
907        Intent intent;
908        try {
909            intent = parseIntentAndUser();
910        } catch (URISyntaxException e) {
911            throw new RuntimeException(e.getMessage(), e);
912        }
913        try {
914            List<ResolveInfo> result = mInterface.queryIntentActivities(intent, null, 0,
915                    mTargetUser).getList();
916            PrintWriter pw = getOutPrintWriter();
917            if (result == null || result.size() <= 0) {
918                pw.println("No activities found");
919            } else {
920                if (!mComponents) {
921                    pw.print(result.size()); pw.println(" activities found:");
922                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
923                    for (int i = 0; i < result.size(); i++) {
924                        pw.print("  Activity #"); pw.print(i); pw.println(":");
925                        printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
926                    }
927                } else {
928                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
929                    for (int i = 0; i < result.size(); i++) {
930                        printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
931                    }
932                }
933            }
934        } catch (RemoteException e) {
935            throw new RuntimeException("Failed calling service", e);
936        }
937        return 0;
938    }
939
940    private int runQueryIntentServices() {
941        Intent intent;
942        try {
943            intent = parseIntentAndUser();
944        } catch (URISyntaxException e) {
945            throw new RuntimeException(e.getMessage(), e);
946        }
947        try {
948            List<ResolveInfo> result = mInterface.queryIntentServices(intent, null, 0,
949                    mTargetUser).getList();
950            PrintWriter pw = getOutPrintWriter();
951            if (result == null || result.size() <= 0) {
952                pw.println("No services found");
953            } else {
954                if (!mComponents) {
955                    pw.print(result.size()); pw.println(" services found:");
956                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
957                    for (int i = 0; i < result.size(); i++) {
958                        pw.print("  Service #"); pw.print(i); pw.println(":");
959                        printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
960                    }
961                } else {
962                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
963                    for (int i = 0; i < result.size(); i++) {
964                        printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
965                    }
966                }
967            }
968        } catch (RemoteException e) {
969            throw new RuntimeException("Failed calling service", e);
970        }
971        return 0;
972    }
973
974    private int runQueryIntentReceivers() {
975        Intent intent;
976        try {
977            intent = parseIntentAndUser();
978        } catch (URISyntaxException e) {
979            throw new RuntimeException(e.getMessage(), e);
980        }
981        try {
982            List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, null, 0,
983                    mTargetUser).getList();
984            PrintWriter pw = getOutPrintWriter();
985            if (result == null || result.size() <= 0) {
986                pw.println("No receivers found");
987            } else {
988                if (!mComponents) {
989                    pw.print(result.size()); pw.println(" receivers found:");
990                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
991                    for (int i = 0; i < result.size(); i++) {
992                        pw.print("  Receiver #"); pw.print(i); pw.println(":");
993                        printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
994                    }
995                } else {
996                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
997                    for (int i = 0; i < result.size(); i++) {
998                        printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
999                    }
1000                }
1001            }
1002        } catch (RemoteException e) {
1003            throw new RuntimeException("Failed calling service", e);
1004        }
1005        return 0;
1006    }
1007
1008    private static class InstallParams {
1009        SessionParams sessionParams;
1010        String installerPackageName;
1011        int userId = UserHandle.USER_ALL;
1012    }
1013
1014    private InstallParams makeInstallParams() {
1015        final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
1016        final InstallParams params = new InstallParams();
1017        params.sessionParams = sessionParams;
1018        String opt;
1019        while ((opt = getNextOption()) != null) {
1020            switch (opt) {
1021                case "-l":
1022                    sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
1023                    break;
1024                case "-r":
1025                    sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1026                    break;
1027                case "-i":
1028                    params.installerPackageName = getNextArg();
1029                    if (params.installerPackageName == null) {
1030                        throw new IllegalArgumentException("Missing installer package");
1031                    }
1032                    break;
1033                case "-t":
1034                    sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
1035                    break;
1036                case "-s":
1037                    sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL;
1038                    break;
1039                case "-f":
1040                    sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
1041                    break;
1042                case "-d":
1043                    sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
1044                    break;
1045                case "-g":
1046                    sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1047                    break;
1048                case "--dont-kill":
1049                    sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
1050                    break;
1051                case "--originating-uri":
1052                    sessionParams.originatingUri = Uri.parse(getNextArg());
1053                    break;
1054                case "--referrer":
1055                    sessionParams.referrerUri = Uri.parse(getNextArg());
1056                    break;
1057                case "-p":
1058                    sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
1059                    sessionParams.appPackageName = getNextArg();
1060                    if (sessionParams.appPackageName == null) {
1061                        throw new IllegalArgumentException("Missing inherit package name");
1062                    }
1063                    break;
1064                case "-S":
1065                    sessionParams.setSize(Long.parseLong(getNextArg()));
1066                    break;
1067                case "--abi":
1068                    sessionParams.abiOverride = checkAbiArgument(getNextArg());
1069                    break;
1070                case "--ephemeral":
1071                    sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL;
1072                    break;
1073                case "--user":
1074                    params.userId = UserHandle.parseUserArg(getNextArgRequired());
1075                    break;
1076                case "--install-location":
1077                    sessionParams.installLocation = Integer.parseInt(getNextArg());
1078                    break;
1079                case "--force-uuid":
1080                    sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
1081                    sessionParams.volumeUuid = getNextArg();
1082                    if ("internal".equals(sessionParams.volumeUuid)) {
1083                        sessionParams.volumeUuid = null;
1084                    }
1085                    break;
1086                case "--force-sdk":
1087                    sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK;
1088                    break;
1089                default:
1090                    throw new IllegalArgumentException("Unknown option " + opt);
1091            }
1092        }
1093        return params;
1094    }
1095
1096    private int runSetHomeActivity() {
1097        final PrintWriter pw = getOutPrintWriter();
1098        int userId = UserHandle.USER_SYSTEM;
1099        String opt;
1100        while ((opt = getNextOption()) != null) {
1101            switch (opt) {
1102                case "--user":
1103                    userId = UserHandle.parseUserArg(getNextArgRequired());
1104                    break;
1105                default:
1106                    pw.println("Error: Unknown option: " + opt);
1107                    return 1;
1108            }
1109        }
1110
1111        String component = getNextArg();
1112        ComponentName componentName =
1113                component != null ? ComponentName.unflattenFromString(component) : null;
1114
1115        if (componentName == null) {
1116            pw.println("Error: component name not specified or invalid");
1117            return 1;
1118        }
1119
1120        try {
1121            mInterface.setHomeActivity(componentName, userId);
1122            pw.println("Success");
1123            return 0;
1124        } catch (Exception e) {
1125            pw.println(e.toString());
1126            return 1;
1127        }
1128    }
1129
1130    private static String checkAbiArgument(String abi) {
1131        if (TextUtils.isEmpty(abi)) {
1132            throw new IllegalArgumentException("Missing ABI argument");
1133        }
1134
1135        if ("-".equals(abi)) {
1136            return abi;
1137        }
1138
1139        final String[] supportedAbis = Build.SUPPORTED_ABIS;
1140        for (String supportedAbi : supportedAbis) {
1141            if (supportedAbi.equals(abi)) {
1142                return abi;
1143            }
1144        }
1145
1146        throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
1147    }
1148
1149    private int translateUserId(int userId, String logContext) {
1150        return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
1151                userId, true, true, logContext, "pm command");
1152    }
1153
1154    private int doCreateSession(SessionParams params, String installerPackageName, int userId)
1155            throws RemoteException {
1156        userId = translateUserId(userId, "runInstallCreate");
1157        if (userId == UserHandle.USER_ALL) {
1158            userId = UserHandle.USER_SYSTEM;
1159            params.installFlags |= PackageManager.INSTALL_ALL_USERS;
1160        }
1161
1162        final int sessionId = mInterface.getPackageInstaller()
1163                .createSession(params, installerPackageName, userId);
1164        return sessionId;
1165    }
1166
1167    private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
1168            boolean logSuccess) throws RemoteException {
1169        final PrintWriter pw = getOutPrintWriter();
1170        if (sizeBytes <= 0) {
1171            pw.println("Error: must specify a APK size");
1172            return 1;
1173        }
1174        if (inPath != null && !"-".equals(inPath)) {
1175            pw.println("Error: APK content must be streamed");
1176            return 1;
1177        }
1178        inPath = null;
1179
1180        final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId);
1181
1182        PackageInstaller.Session session = null;
1183        InputStream in = null;
1184        OutputStream out = null;
1185        try {
1186            session = new PackageInstaller.Session(
1187                    mInterface.getPackageInstaller().openSession(sessionId));
1188
1189            if (inPath != null) {
1190                in = new FileInputStream(inPath);
1191            } else {
1192                in = new SizedInputStream(getRawInputStream(), sizeBytes);
1193            }
1194            out = session.openWrite(splitName, 0, sizeBytes);
1195
1196            int total = 0;
1197            byte[] buffer = new byte[65536];
1198            int c;
1199            while ((c = in.read(buffer)) != -1) {
1200                total += c;
1201                out.write(buffer, 0, c);
1202
1203                if (info.sizeBytes > 0) {
1204                    final float fraction = ((float) c / (float) info.sizeBytes);
1205                    session.addProgress(fraction);
1206                }
1207            }
1208            session.fsync(out);
1209
1210            if (logSuccess) {
1211                pw.println("Success: streamed " + total + " bytes");
1212            }
1213            return 0;
1214        } catch (IOException e) {
1215            pw.println("Error: failed to write; " + e.getMessage());
1216            return 1;
1217        } finally {
1218            IoUtils.closeQuietly(out);
1219            IoUtils.closeQuietly(in);
1220            IoUtils.closeQuietly(session);
1221        }
1222    }
1223
1224    private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
1225            throws RemoteException {
1226        final PrintWriter pw = getOutPrintWriter();
1227        PackageInstaller.Session session = null;
1228        try {
1229            session = new PackageInstaller.Session(
1230                    mInterface.getPackageInstaller().openSession(sessionId));
1231            session.removeSplit(splitName);
1232
1233            if (logSuccess) {
1234                pw.println("Success");
1235            }
1236            return 0;
1237        } catch (IOException e) {
1238            pw.println("Error: failed to remove split; " + e.getMessage());
1239            return 1;
1240        } finally {
1241            IoUtils.closeQuietly(session);
1242        }
1243    }
1244
1245    private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
1246        final PrintWriter pw = getOutPrintWriter();
1247        PackageInstaller.Session session = null;
1248        try {
1249            session = new PackageInstaller.Session(
1250                    mInterface.getPackageInstaller().openSession(sessionId));
1251
1252            final LocalIntentReceiver receiver = new LocalIntentReceiver();
1253            session.commit(receiver.getIntentSender());
1254
1255            final Intent result = receiver.getResult();
1256            final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1257                    PackageInstaller.STATUS_FAILURE);
1258            if (status == PackageInstaller.STATUS_SUCCESS) {
1259                if (logSuccess) {
1260                    pw.println("Success");
1261                }
1262            } else {
1263                pw.println("Failure ["
1264                        + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
1265            }
1266            return status;
1267        } finally {
1268            IoUtils.closeQuietly(session);
1269        }
1270    }
1271
1272    private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
1273        final PrintWriter pw = getOutPrintWriter();
1274        PackageInstaller.Session session = null;
1275        try {
1276            session = new PackageInstaller.Session(
1277                    mInterface.getPackageInstaller().openSession(sessionId));
1278            session.abandon();
1279            if (logSuccess) {
1280                pw.println("Success");
1281            }
1282            return 0;
1283        } finally {
1284            IoUtils.closeQuietly(session);
1285        }
1286    }
1287
1288    private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
1289            boolean summary, int startProtectionLevel, int endProtectionLevel)
1290                    throws RemoteException {
1291        final PrintWriter pw = getOutPrintWriter();
1292        final int groupCount = groupList.size();
1293        for (int i = 0; i < groupCount; i++) {
1294            String groupName = groupList.get(i);
1295            String prefix = "";
1296            if (groups) {
1297                if (i > 0) {
1298                    pw.println("");
1299                }
1300                if (groupName != null) {
1301                    PermissionGroupInfo pgi =
1302                            mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
1303                    if (summary) {
1304                        Resources res = getResources(pgi);
1305                        if (res != null) {
1306                            pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
1307                        } else {
1308                            pw.print(pgi.name + ": ");
1309
1310                        }
1311                    } else {
1312                        pw.println((labels ? "+ " : "") + "group:" + pgi.name);
1313                        if (labels) {
1314                            pw.println("  package:" + pgi.packageName);
1315                            Resources res = getResources(pgi);
1316                            if (res != null) {
1317                                pw.println("  label:"
1318                                        + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
1319                                pw.println("  description:"
1320                                        + loadText(pgi, pgi.descriptionRes,
1321                                                pgi.nonLocalizedDescription));
1322                            }
1323                        }
1324                    }
1325                } else {
1326                    pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
1327                }
1328                prefix = "  ";
1329            }
1330            List<PermissionInfo> ps =
1331                    mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
1332            final int count = ps.size();
1333            boolean first = true;
1334            for (int p = 0 ; p < count ; p++) {
1335                PermissionInfo pi = ps.get(p);
1336                if (groups && groupName == null && pi.group != null) {
1337                    continue;
1338                }
1339                final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
1340                if (base < startProtectionLevel
1341                        || base > endProtectionLevel) {
1342                    continue;
1343                }
1344                if (summary) {
1345                    if (first) {
1346                        first = false;
1347                    } else {
1348                        pw.print(", ");
1349                    }
1350                    Resources res = getResources(pi);
1351                    if (res != null) {
1352                        pw.print(loadText(pi, pi.labelRes,
1353                                pi.nonLocalizedLabel));
1354                    } else {
1355                        pw.print(pi.name);
1356                    }
1357                } else {
1358                    pw.println(prefix + (labels ? "+ " : "")
1359                            + "permission:" + pi.name);
1360                    if (labels) {
1361                        pw.println(prefix + "  package:" + pi.packageName);
1362                        Resources res = getResources(pi);
1363                        if (res != null) {
1364                            pw.println(prefix + "  label:"
1365                                    + loadText(pi, pi.labelRes,
1366                                            pi.nonLocalizedLabel));
1367                            pw.println(prefix + "  description:"
1368                                    + loadText(pi, pi.descriptionRes,
1369                                            pi.nonLocalizedDescription));
1370                        }
1371                        pw.println(prefix + "  protectionLevel:"
1372                                + PermissionInfo.protectionToString(pi.protectionLevel));
1373                    }
1374                }
1375            }
1376
1377            if (summary) {
1378                pw.println("");
1379            }
1380        }
1381    }
1382
1383    private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
1384            throws RemoteException {
1385        if (nonLocalized != null) {
1386            return nonLocalized.toString();
1387        }
1388        if (res != 0) {
1389            Resources r = getResources(pii);
1390            if (r != null) {
1391                try {
1392                    return r.getString(res);
1393                } catch (Resources.NotFoundException e) {
1394                }
1395            }
1396        }
1397        return null;
1398    }
1399
1400    private Resources getResources(PackageItemInfo pii) throws RemoteException {
1401        Resources res = mResourceCache.get(pii.packageName);
1402        if (res != null) return res;
1403
1404        ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0);
1405        AssetManager am = new AssetManager();
1406        am.addAssetPath(ai.publicSourceDir);
1407        res = new Resources(am, null, null);
1408        mResourceCache.put(pii.packageName, res);
1409        return res;
1410    }
1411
1412    @Override
1413    public void onHelp() {
1414        final PrintWriter pw = getOutPrintWriter();
1415        pw.println("Package manager (package) commands:");
1416        pw.println("  help");
1417        pw.println("    Print this help text.");
1418        pw.println("");
1419        pw.println("  compile [-m MODE | -r REASON] [-f] [-c]");
1420        pw.println("          [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
1421        pw.println("    Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".");
1422        pw.println("    Options:");
1423        pw.println("      -a: compile all packages");
1424        pw.println("      -c: clear profile data before compiling");
1425        pw.println("      -f: force compilation even if not needed");
1426        pw.println("      -m: select compilation mode");
1427        pw.println("          MODE is one of the dex2oat compiler filters:");
1428        pw.println("            verify-none");
1429        pw.println("            verify-at-runtime");
1430        pw.println("            verify-profile");
1431        pw.println("            interpret-only");
1432        pw.println("            space-profile");
1433        pw.println("            space");
1434        pw.println("            speed-profile");
1435        pw.println("            speed");
1436        pw.println("            everything");
1437        pw.println("      -r: select compilation reason");
1438        pw.println("          REASON is one of:");
1439        for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
1440            pw.println("            " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
1441        }
1442        pw.println("      --reset: restore package to its post-install state");
1443        pw.println("      --check-prof (true | false): look at profiles when doing dexopt?");
1444        pw.println("  list features");
1445        pw.println("    Prints all features of the system.");
1446        pw.println("  list instrumentation [-f] [TARGET-PACKAGE]");
1447        pw.println("    Prints all test packages; optionally only those targeting TARGET-PACKAGE");
1448        pw.println("    Options:");
1449        pw.println("      -f: dump the name of the .apk file containing the test package");
1450        pw.println("  list libraries");
1451        pw.println("    Prints all system libraries.");
1452        pw.println("  list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]");
1453        pw.println("    Prints all packages; optionally only those whose name contains");
1454        pw.println("    the text in FILTER.");
1455        pw.println("    Options:");
1456        pw.println("      -f: see their associated file");
1457        pw.println("      -d: filter to only show disabled packages");
1458        pw.println("      -e: filter to only show enabled packages");
1459        pw.println("      -s: filter to only show system packages");
1460        pw.println("      -3: filter to only show third party packages");
1461        pw.println("      -i: see the installer for the packages");
1462        pw.println("      -u: also include uninstalled packages");
1463        pw.println("  list permission-groups");
1464        pw.println("    Prints all known permission groups.");
1465        pw.println("  list permissions [-g] [-f] [-d] [-u] [GROUP]");
1466        pw.println("    Prints all known permissions; optionally only those in GROUP.");
1467        pw.println("    Options:");
1468        pw.println("      -g: organize by group");
1469        pw.println("      -f: print all information");
1470        pw.println("      -s: short summary");
1471        pw.println("      -d: only list dangerous permissions");
1472        pw.println("      -u: list only the permissions users will see");
1473        pw.println("  dump-profiles TARGET-PACKAGE");
1474        pw.println("    Dumps method/class profile files to");
1475        pw.println("    /data/misc/profman/TARGET-PACKAGE.txt");
1476        pw.println("  resolve-activity [--brief] [--components] [--user USER_ID] INTENT");
1477        pw.println("    Prints the activity that resolves to the given Intent.");
1478        pw.println("  query-activities [--brief] [--components] [--user USER_ID] INTENT");
1479        pw.println("    Prints all activities that can handle the given Intent.");
1480        pw.println("  query-services [--brief] [--components] [--user USER_ID] INTENT");
1481        pw.println("    Prints all services that can handle the given Intent.");
1482        pw.println("  query-receivers [--brief] [--components] [--user USER_ID] INTENT");
1483        pw.println("    Prints all broadcast receivers that can handle the given Intent.");
1484        pw.println("  suspend [--user USER_ID] TARGET-PACKAGE");
1485        pw.println("    Suspends the specified package (as user).");
1486        pw.println("  unsuspend [--user USER_ID] TARGET-PACKAGE");
1487        pw.println("    Unsuspends the specified package (as user).");
1488        pw.println("  set-home-activity [--user USER_ID] TARGET-COMPONENT");
1489        pw.println("    set the default home activity (aka launcher).");
1490        pw.println();
1491        Intent.printIntentArgsHelp(pw , "");
1492    }
1493
1494    private static class LocalIntentReceiver {
1495        private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
1496
1497        private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
1498            @Override
1499            public void send(int code, Intent intent, String resolvedType,
1500                    IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
1501                try {
1502                    mResult.offer(intent, 5, TimeUnit.SECONDS);
1503                } catch (InterruptedException e) {
1504                    throw new RuntimeException(e);
1505                }
1506            }
1507        };
1508
1509        public IntentSender getIntentSender() {
1510            return new IntentSender((IIntentSender) mLocalSender);
1511        }
1512
1513        public Intent getResult() {
1514            try {
1515                return mResult.take();
1516            } catch (InterruptedException e) {
1517                throw new RuntimeException(e);
1518            }
1519        }
1520    }
1521}
1522