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