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