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