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