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