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