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