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