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