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