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