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