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