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