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