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