PackageManagerShellCommand.java revision 115d2c189a46f535778d9dd0923f703ff2f888fe
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.ParceledListSlice;
34import android.content.pm.PermissionGroupInfo;
35import android.content.pm.PermissionInfo;
36import android.content.pm.PackageInstaller.SessionInfo;
37import android.content.pm.PackageInstaller.SessionParams;
38import android.content.pm.ResolveInfo;
39import android.content.res.AssetManager;
40import android.content.res.Resources;
41import android.net.Uri;
42import android.os.Binder;
43import android.os.Build;
44import android.os.Bundle;
45import android.os.RemoteException;
46import android.os.ShellCommand;
47import android.os.SystemProperties;
48import android.os.UserHandle;
49import android.text.TextUtils;
50import android.util.PrintWriterPrinter;
51import com.android.internal.util.SizedInputStream;
52
53import libcore.io.IoUtils;
54
55import java.io.File;
56import java.io.FileInputStream;
57import java.io.IOException;
58import java.io.InputStream;
59import java.io.OutputStream;
60import java.io.PrintWriter;
61import java.net.URISyntaxException;
62import java.util.ArrayList;
63import java.util.Collections;
64import java.util.Comparator;
65import java.util.List;
66import java.util.WeakHashMap;
67import java.util.concurrent.SynchronousQueue;
68import java.util.concurrent.TimeUnit;
69
70class PackageManagerShellCommand extends ShellCommand {
71    final IPackageManager mInterface;
72    final private WeakHashMap<String, Resources> mResourceCache =
73            new WeakHashMap<String, Resources>();
74    int mTargetUser;
75
76    PackageManagerShellCommand(PackageManagerService service) {
77        mInterface = service;
78    }
79
80    @Override
81    public int onCommand(String cmd) {
82        if (cmd == null) {
83            return handleDefaultCommands(cmd);
84        }
85
86        final PrintWriter pw = getOutPrintWriter();
87        try {
88            switch(cmd) {
89                case "install":
90                    return runInstall();
91                case "install-abandon":
92                case "install-destroy":
93                    return runInstallAbandon();
94                case "install-commit":
95                    return runInstallCommit();
96                case "install-create":
97                    return runInstallCreate();
98                case "install-write":
99                    return runInstallWrite();
100                case "compile":
101                    return runCompile();
102                case "list":
103                    return runList();
104                case "uninstall":
105                    return runUninstall();
106                case "resolve-activity":
107                    return runResolveActivity();
108                case "query-activities":
109                    return runQueryIntentActivities();
110                case "query-services":
111                    return runQueryIntentServices();
112                case "query-receivers":
113                    return runQueryIntentReceivers();
114                case "suspend":
115                    return runSuspend(true);
116                case "unsuspend":
117                    return runSuspend(false);
118                default:
119                    return handleDefaultCommands(cmd);
120            }
121        } catch (RemoteException e) {
122            pw.println("Remote exception: " + e);
123        }
124        return -1;
125    }
126
127    private int runInstall() throws RemoteException {
128        final PrintWriter pw = getOutPrintWriter();
129        final InstallParams params = makeInstallParams();
130        final int sessionId = doCreateSession(params.sessionParams,
131                params.installerPackageName, params.userId);
132        boolean abandonSession = true;
133        try {
134            final String inPath = getNextArg();
135            if (inPath == null && params.sessionParams.sizeBytes == 0) {
136                pw.println("Error: must either specify a package size or an APK file");
137                return 1;
138            }
139            if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
140                    false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
141                return 1;
142            }
143            if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
144                return 1;
145            }
146            abandonSession = false;
147            pw.println("Success");
148            return 0;
149        } finally {
150            if (abandonSession) {
151                try {
152                    doAbandonSession(sessionId, false /*logSuccess*/);
153                } catch (Exception ignore) {
154                }
155            }
156        }
157    }
158
159    private int runSuspend(boolean suspendedState) {
160        final PrintWriter pw = getOutPrintWriter();
161        int userId = UserHandle.USER_SYSTEM;
162        String opt;
163        while ((opt = getNextOption()) != null) {
164            switch (opt) {
165                case "--user":
166                    userId = UserHandle.parseUserArg(getNextArgRequired());
167                    break;
168                default:
169                    pw.println("Error: Unknown option: " + opt);
170                    return 1;
171            }
172        }
173
174        String packageName = getNextArg();
175        if (packageName == null) {
176            pw.println("Error: package name not specified");
177            return 1;
178        }
179
180        try {
181            mInterface.setPackageSuspendedAsUser(packageName, suspendedState, userId);
182            ApplicationInfo appInfo = mInterface.getApplicationInfo(
183                    packageName, 0, userId);
184
185            pw.println("Package " + packageName + " new suspended state: "
186                    + ((appInfo.flags & ApplicationInfo.FLAG_SUSPENDED) != 0));
187            return 0;
188        } catch (RemoteException e) {
189            pw.println(e.toString());
190            return 1;
191        }
192    }
193
194    private int runInstallAbandon() throws RemoteException {
195        final int sessionId = Integer.parseInt(getNextArg());
196        return doAbandonSession(sessionId, true /*logSuccess*/);
197    }
198
199    private int runInstallCommit() throws RemoteException {
200        final int sessionId = Integer.parseInt(getNextArg());
201        return doCommitSession(sessionId, true /*logSuccess*/);
202    }
203
204    private int runInstallCreate() throws RemoteException {
205        final PrintWriter pw = getOutPrintWriter();
206        final InstallParams installParams = makeInstallParams();
207        final int sessionId = doCreateSession(installParams.sessionParams,
208                installParams.installerPackageName, installParams.userId);
209
210        // NOTE: adb depends on parsing this string
211        pw.println("Success: created install session [" + sessionId + "]");
212        return 0;
213    }
214
215    private int runInstallWrite() throws RemoteException {
216        long sizeBytes = -1;
217
218        String opt;
219        while ((opt = getNextOption()) != null) {
220            if (opt.equals("-S")) {
221                sizeBytes = Long.parseLong(getNextArg());
222            } else {
223                throw new IllegalArgumentException("Unknown option: " + opt);
224            }
225        }
226
227        final int sessionId = Integer.parseInt(getNextArg());
228        final String splitName = getNextArg();
229        final String path = getNextArg();
230        return doWriteSession(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
231    }
232
233    private int runCompile() throws RemoteException {
234        final PrintWriter pw = getOutPrintWriter();
235        boolean useJitProfiles = false;
236        boolean extractOnly = false;
237        boolean forceCompilation = false;
238        String compilationMode = "default";
239
240        String opt;
241        while ((opt = getNextOption()) != null) {
242            switch (opt) {
243                case "-m":
244                    compilationMode = getNextArgRequired();
245                    break;
246                case "-f":
247                    forceCompilation = true;
248                    break;
249                default:
250                    pw.println("Error: Unknown option: " + opt);
251                    return 1;
252            }
253        }
254
255        switch (compilationMode) {
256            case "default":
257                useJitProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
258                extractOnly = false;
259                break;
260            case "all":
261                useJitProfiles = false;
262                extractOnly = false;
263                break;
264            case "profile":
265                useJitProfiles = true;
266                extractOnly = false;
267                break;
268            case "extract":
269                useJitProfiles = false;
270                extractOnly = true;
271                break;
272            default:
273                pw.println("Error: Unknown compilation mode: " + compilationMode);
274                return 1;
275        }
276
277        String packageName = getNextArg();
278        if (packageName == null) {
279            pw.println("Error: package name not specified");
280            return 1;
281        }
282
283        boolean success = mInterface.performDexOpt(packageName, null /* instructionSet */,
284                useJitProfiles, extractOnly, forceCompilation);
285        if (success) {
286            pw.println("Success");
287            return 0;
288        } else {
289            pw.println("Failure: package " + packageName + " could not be compiled");
290            return 1;
291        }
292    }
293
294    private int runList() throws RemoteException {
295        final PrintWriter pw = getOutPrintWriter();
296        final String type = getNextArg();
297        if (type == null) {
298            pw.println("Error: didn't specify type of data to list");
299            return -1;
300        }
301        switch(type) {
302            case "features":
303                return runListFeatures();
304            case "instrumentation":
305                return runListInstrumentation();
306            case "libraries":
307                return runListLibraries();
308            case "package":
309            case "packages":
310                return runListPackages(false /*showSourceDir*/);
311            case "permission-groups":
312                return runListPermissionGroups();
313            case "permissions":
314                return runListPermissions();
315        }
316        pw.println("Error: unknown list type '" + type + "'");
317        return -1;
318    }
319
320    private int runListFeatures() throws RemoteException {
321        final PrintWriter pw = getOutPrintWriter();
322        final List<FeatureInfo> list = new ArrayList<FeatureInfo>();
323        final FeatureInfo[] rawList = mInterface.getSystemAvailableFeatures();
324        for (int i=0; i<rawList.length; i++) {
325            list.add(rawList[i]);
326        }
327
328        // sort by name
329        Collections.sort(list, new Comparator<FeatureInfo>() {
330            public int compare(FeatureInfo o1, FeatureInfo o2) {
331                if (o1.name == o2.name) return 0;
332                if (o1.name == null) return -1;
333                if (o2.name == null) return 1;
334                return o1.name.compareTo(o2.name);
335            }
336        });
337
338        final int count = (list != null) ? list.size() : 0;
339        for (int p = 0; p < count; p++) {
340            FeatureInfo fi = list.get(p);
341            pw.print("feature:");
342            if (fi.name != null) {
343                pw.print(fi.name);
344                if (fi.version > 0) {
345                    pw.print("=");
346                    pw.print(fi.version);
347                }
348                pw.println();
349            } else {
350                pw.println("reqGlEsVersion=0x"
351                    + Integer.toHexString(fi.reqGlEsVersion));
352            }
353        }
354        return 0;
355    }
356
357    private int runListInstrumentation() throws RemoteException {
358        final PrintWriter pw = getOutPrintWriter();
359        boolean showSourceDir = false;
360        String targetPackage = null;
361
362        try {
363            String opt;
364            while ((opt = getNextArg()) != null) {
365                switch (opt) {
366                    case "-f":
367                        showSourceDir = true;
368                        break;
369                    default:
370                        if (opt.charAt(0) != '-') {
371                            targetPackage = opt;
372                        } else {
373                            pw.println("Error: Unknown option: " + opt);
374                            return -1;
375                        }
376                        break;
377                }
378            }
379        } catch (RuntimeException ex) {
380            pw.println("Error: " + ex.toString());
381            return -1;
382        }
383
384        final List<InstrumentationInfo> list =
385                mInterface.queryInstrumentation(targetPackage, 0 /*flags*/);
386
387        // sort by target package
388        Collections.sort(list, new Comparator<InstrumentationInfo>() {
389            public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
390                return o1.targetPackage.compareTo(o2.targetPackage);
391            }
392        });
393
394        final int count = (list != null) ? list.size() : 0;
395        for (int p = 0; p < count; p++) {
396            final InstrumentationInfo ii = list.get(p);
397            pw.print("instrumentation:");
398            if (showSourceDir) {
399                pw.print(ii.sourceDir);
400                pw.print("=");
401            }
402            final ComponentName cn = new ComponentName(ii.packageName, ii.name);
403            pw.print(cn.flattenToShortString());
404            pw.print(" (target=");
405            pw.print(ii.targetPackage);
406            pw.println(")");
407        }
408        return 0;
409    }
410
411    private int runListLibraries() throws RemoteException {
412        final PrintWriter pw = getOutPrintWriter();
413        final List<String> list = new ArrayList<String>();
414        final String[] rawList = mInterface.getSystemSharedLibraryNames();
415        for (int i = 0; i < rawList.length; i++) {
416            list.add(rawList[i]);
417        }
418
419        // sort by name
420        Collections.sort(list, new Comparator<String>() {
421            public int compare(String o1, String o2) {
422                if (o1 == o2) return 0;
423                if (o1 == null) return -1;
424                if (o2 == null) return 1;
425                return o1.compareTo(o2);
426            }
427        });
428
429        final int count = (list != null) ? list.size() : 0;
430        for (int p = 0; p < count; p++) {
431            String lib = list.get(p);
432            pw.print("library:");
433            pw.println(lib);
434        }
435        return 0;
436    }
437
438    private int runListPackages(boolean showSourceDir) throws RemoteException {
439        final PrintWriter pw = getOutPrintWriter();
440        int getFlags = 0;
441        boolean listDisabled = false, listEnabled = false;
442        boolean listSystem = false, listThirdParty = false;
443        boolean listInstaller = false;
444        int userId = UserHandle.USER_SYSTEM;
445        try {
446            String opt;
447            while ((opt = getNextOption()) != null) {
448                switch (opt) {
449                    case "-d":
450                        listDisabled = true;
451                        break;
452                    case "-e":
453                        listEnabled = true;
454                        break;
455                    case "-f":
456                        showSourceDir = true;
457                        break;
458                    case "-i":
459                        listInstaller = true;
460                        break;
461                    case "-l":
462                        // old compat
463                        break;
464                    case "-lf":
465                        showSourceDir = true;
466                        break;
467                    case "-s":
468                        listSystem = true;
469                        break;
470                    case "-u":
471                        getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
472                        break;
473                    case "-3":
474                        listThirdParty = true;
475                        break;
476                    case "--user":
477                        userId = UserHandle.parseUserArg(getNextArgRequired());
478                        break;
479                    default:
480                        pw.println("Error: Unknown option: " + opt);
481                        return -1;
482                }
483            }
484        } catch (RuntimeException ex) {
485            pw.println("Error: " + ex.toString());
486            return -1;
487        }
488
489        final String filter = getNextArg();
490
491        @SuppressWarnings("unchecked")
492        final ParceledListSlice<PackageInfo> slice =
493                mInterface.getInstalledPackages(getFlags, userId);
494        final List<PackageInfo> packages = slice.getList();
495
496        final int count = packages.size();
497        for (int p = 0; p < count; p++) {
498            final PackageInfo info = packages.get(p);
499            if (filter != null && !info.packageName.contains(filter)) {
500                continue;
501            }
502            final boolean isSystem =
503                    (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
504            if ((!listDisabled || !info.applicationInfo.enabled) &&
505                    (!listEnabled || info.applicationInfo.enabled) &&
506                    (!listSystem || isSystem) &&
507                    (!listThirdParty || !isSystem)) {
508                pw.print("package:");
509                if (showSourceDir) {
510                    pw.print(info.applicationInfo.sourceDir);
511                    pw.print("=");
512                }
513                pw.print(info.packageName);
514                if (listInstaller) {
515                    pw.print("  installer=");
516                    pw.print(mInterface.getInstallerPackageName(info.packageName));
517                }
518                pw.println();
519            }
520        }
521        return 0;
522    }
523
524    private int runListPermissionGroups() throws RemoteException {
525        final PrintWriter pw = getOutPrintWriter();
526        final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0);
527
528        final int count = pgs.size();
529        for (int p = 0; p < count ; p++) {
530            final PermissionGroupInfo pgi = pgs.get(p);
531            pw.print("permission group:");
532            pw.println(pgi.name);
533        }
534        return 0;
535    }
536
537    private int runListPermissions() throws RemoteException {
538        final PrintWriter pw = getOutPrintWriter();
539        boolean labels = false;
540        boolean groups = false;
541        boolean userOnly = false;
542        boolean summary = false;
543        boolean dangerousOnly = false;
544        String opt;
545        while ((opt = getNextOption()) != null) {
546            switch (opt) {
547                case "-d":
548                    dangerousOnly = true;
549                    break;
550                case "-f":
551                    labels = true;
552                    break;
553                case "-g":
554                    groups = true;
555                    break;
556                case "-s":
557                    groups = true;
558                    labels = true;
559                    summary = true;
560                    break;
561                case "-u":
562                    userOnly = true;
563                    break;
564                default:
565                    pw.println("Error: Unknown option: " + opt);
566                    return 1;
567            }
568        }
569
570        final ArrayList<String> groupList = new ArrayList<String>();
571        if (groups) {
572            final List<PermissionGroupInfo> infos =
573                    mInterface.getAllPermissionGroups(0 /*flags*/);
574            final int count = infos.size();
575            for (int i = 0; i < count; i++) {
576                groupList.add(infos.get(i).name);
577            }
578            groupList.add(null);
579        } else {
580            final String grp = getNextArg();
581            groupList.add(grp);
582        }
583
584        if (dangerousOnly) {
585            pw.println("Dangerous Permissions:");
586            pw.println("");
587            doListPermissions(groupList, groups, labels, summary,
588                    PermissionInfo.PROTECTION_DANGEROUS,
589                    PermissionInfo.PROTECTION_DANGEROUS);
590            if (userOnly) {
591                pw.println("Normal Permissions:");
592                pw.println("");
593                doListPermissions(groupList, groups, labels, summary,
594                        PermissionInfo.PROTECTION_NORMAL,
595                        PermissionInfo.PROTECTION_NORMAL);
596            }
597        } else if (userOnly) {
598            pw.println("Dangerous and Normal Permissions:");
599            pw.println("");
600            doListPermissions(groupList, groups, labels, summary,
601                    PermissionInfo.PROTECTION_NORMAL,
602                    PermissionInfo.PROTECTION_DANGEROUS);
603        } else {
604            pw.println("All Permissions:");
605            pw.println("");
606            doListPermissions(groupList, groups, labels, summary,
607                    -10000, 10000);
608        }
609        return 0;
610    }
611
612    private int runUninstall() throws RemoteException {
613        final PrintWriter pw = getOutPrintWriter();
614        int flags = 0;
615        int userId = UserHandle.USER_ALL;
616
617        String opt;
618        while ((opt = getNextOption()) != null) {
619            switch (opt) {
620                case "-k":
621                    flags |= PackageManager.DELETE_KEEP_DATA;
622                    break;
623                case "--user":
624                    userId = UserHandle.parseUserArg(getNextArgRequired());
625                    break;
626                default:
627                    pw.println("Error: Unknown option: " + opt);
628                    return 1;
629            }
630        }
631
632        String packageName = getNextArg();
633        if (packageName == null) {
634            pw.println("Error: package name not specified");
635            return 1;
636        }
637
638        userId = translateUserId(userId, "runUninstall");
639        if (userId == UserHandle.USER_ALL) {
640            userId = UserHandle.USER_SYSTEM;
641            flags |= PackageManager.DELETE_ALL_USERS;
642        } else {
643            final PackageInfo info = mInterface.getPackageInfo(packageName, 0, userId);
644            if (info == null) {
645                pw.println("Failure [not installed for " + userId + "]");
646                return 1;
647            }
648            final boolean isSystem =
649                    (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
650            // If we are being asked to delete a system app for just one
651            // user set flag so it disables rather than reverting to system
652            // version of the app.
653            if (isSystem) {
654                flags |= PackageManager.DELETE_SYSTEM_APP;
655            }
656        }
657
658        final LocalIntentReceiver receiver = new LocalIntentReceiver();
659        mInterface.getPackageInstaller().uninstall(packageName, null /*callerPackageName*/, flags,
660                receiver.getIntentSender(), userId);
661
662        final Intent result = receiver.getResult();
663        final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
664                PackageInstaller.STATUS_FAILURE);
665        if (status == PackageInstaller.STATUS_SUCCESS) {
666            pw.println("Success");
667            return 0;
668        } else {
669            pw.println("Failure ["
670                    + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
671            return 1;
672        }
673    }
674
675    private Intent parseIntentAndUser() throws URISyntaxException {
676        mTargetUser = UserHandle.USER_CURRENT;
677        Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
678            @Override
679            public boolean handleOption(String opt, ShellCommand cmd) {
680                if ("--user".equals(opt)) {
681                    mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
682                    return true;
683                }
684                return false;
685            }
686        });
687        mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
688                Binder.getCallingUid(), mTargetUser, false, false, null, null);
689        return intent;
690    }
691
692    private int runResolveActivity() {
693        Intent intent;
694        try {
695            intent = parseIntentAndUser();
696        } catch (URISyntaxException e) {
697            throw new RuntimeException(e.getMessage(), e);
698        }
699        try {
700            ResolveInfo ri = mInterface.resolveIntent(intent, null, 0, mTargetUser);
701            PrintWriter pw = getOutPrintWriter();
702            if (ri == null) {
703                pw.println("No activity found");
704            } else {
705                PrintWriterPrinter pr = new PrintWriterPrinter(pw);
706                ri.dump(pr, "");
707            }
708        } catch (RemoteException e) {
709            throw new RuntimeException("Failed calling service", e);
710        }
711        return 0;
712    }
713
714    private int runQueryIntentActivities() {
715        Intent intent;
716        try {
717            intent = parseIntentAndUser();
718        } catch (URISyntaxException e) {
719            throw new RuntimeException(e.getMessage(), e);
720        }
721        try {
722            List<ResolveInfo> result = mInterface.queryIntentActivities(intent, null, 0,
723                    mTargetUser);
724            PrintWriter pw = getOutPrintWriter();
725            if (result == null || result.size() <= 0) {
726                pw.println("No activities found");
727            } else {
728                pw.print(result.size()); pw.println(" activities found:");
729                PrintWriterPrinter pr = new PrintWriterPrinter(pw);
730                for (int i=0; i<result.size(); i++) {
731                    pw.print("  Activity #"); pw.print(i); pw.println(":");
732                    result.get(i).dump(pr, "    ");
733                }
734            }
735        } catch (RemoteException e) {
736            throw new RuntimeException("Failed calling service", e);
737        }
738        return 0;
739    }
740
741    private int runQueryIntentServices() {
742        Intent intent;
743        try {
744            intent = parseIntentAndUser();
745        } catch (URISyntaxException e) {
746            throw new RuntimeException(e.getMessage(), e);
747        }
748        try {
749            List<ResolveInfo> result = mInterface.queryIntentServices(intent, null, 0,
750                    mTargetUser);
751            PrintWriter pw = getOutPrintWriter();
752            if (result == null || result.size() <= 0) {
753                pw.println("No services found");
754            } else {
755                pw.print(result.size()); pw.println(" services found:");
756                PrintWriterPrinter pr = new PrintWriterPrinter(pw);
757                for (int i=0; i<result.size(); i++) {
758                    pw.print("  Service #"); pw.print(i); pw.println(":");
759                    result.get(i).dump(pr, "    ");
760                }
761            }
762        } catch (RemoteException e) {
763            throw new RuntimeException("Failed calling service", e);
764        }
765        return 0;
766    }
767
768    private int runQueryIntentReceivers() {
769        Intent intent;
770        try {
771            intent = parseIntentAndUser();
772        } catch (URISyntaxException e) {
773            throw new RuntimeException(e.getMessage(), e);
774        }
775        try {
776            List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, null, 0,
777                    mTargetUser);
778            PrintWriter pw = getOutPrintWriter();
779            if (result == null || result.size() <= 0) {
780                pw.println("No receivers found");
781            } else {
782                pw.print(result.size()); pw.println(" receivers found:");
783                PrintWriterPrinter pr = new PrintWriterPrinter(pw);
784                for (int i=0; i<result.size(); i++) {
785                    pw.print("  Receiver #"); pw.print(i); pw.println(":");
786                    result.get(i).dump(pr, "    ");
787                }
788            }
789        } catch (RemoteException e) {
790            throw new RuntimeException("Failed calling service", e);
791        }
792        return 0;
793    }
794
795    private static class InstallParams {
796        SessionParams sessionParams;
797        String installerPackageName;
798        int userId = UserHandle.USER_ALL;
799    }
800
801    private InstallParams makeInstallParams() {
802        final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
803        final InstallParams params = new InstallParams();
804        params.sessionParams = sessionParams;
805        String opt;
806        while ((opt = getNextOption()) != null) {
807            switch (opt) {
808                case "-l":
809                    sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
810                    break;
811                case "-r":
812                    sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
813                    break;
814                case "-i":
815                    params.installerPackageName = getNextArg();
816                    if (params.installerPackageName == null) {
817                        throw new IllegalArgumentException("Missing installer package");
818                    }
819                    break;
820                case "-t":
821                    sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
822                    break;
823                case "-s":
824                    sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL;
825                    break;
826                case "-f":
827                    sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
828                    break;
829                case "-d":
830                    sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
831                    break;
832                case "-g":
833                    sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
834                    break;
835                case "--originating-uri":
836                    sessionParams.originatingUri = Uri.parse(getNextArg());
837                    break;
838                case "--referrer":
839                    sessionParams.referrerUri = Uri.parse(getNextArg());
840                    break;
841                case "-p":
842                    sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
843                    sessionParams.appPackageName = getNextArg();
844                    if (sessionParams.appPackageName == null) {
845                        throw new IllegalArgumentException("Missing inherit package name");
846                    }
847                    break;
848                case "-S":
849                    sessionParams.setSize(Long.parseLong(getNextArg()));
850                    break;
851                case "--abi":
852                    sessionParams.abiOverride = checkAbiArgument(getNextArg());
853                    break;
854                case "--ephemeral":
855                    sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL;
856                    break;
857                case "--user":
858                    params.userId = UserHandle.parseUserArg(getNextArgRequired());
859                    break;
860                case "--install-location":
861                    sessionParams.installLocation = Integer.parseInt(getNextArg());
862                    break;
863                case "--force-uuid":
864                    sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
865                    sessionParams.volumeUuid = getNextArg();
866                    if ("internal".equals(sessionParams.volumeUuid)) {
867                        sessionParams.volumeUuid = null;
868                    }
869                    break;
870                default:
871                    throw new IllegalArgumentException("Unknown option " + opt);
872            }
873        }
874        return params;
875    }
876
877    private static String checkAbiArgument(String abi) {
878        if (TextUtils.isEmpty(abi)) {
879            throw new IllegalArgumentException("Missing ABI argument");
880        }
881
882        if ("-".equals(abi)) {
883            return abi;
884        }
885
886        final String[] supportedAbis = Build.SUPPORTED_ABIS;
887        for (String supportedAbi : supportedAbis) {
888            if (supportedAbi.equals(abi)) {
889                return abi;
890            }
891        }
892
893        throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
894    }
895
896    private int translateUserId(int userId, String logContext) {
897        return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
898                userId, true, true, logContext, "pm command");
899    }
900
901    private int doCreateSession(SessionParams params, String installerPackageName, int userId)
902            throws RemoteException {
903        userId = translateUserId(userId, "runInstallCreate");
904        if (userId == UserHandle.USER_ALL) {
905            userId = UserHandle.USER_SYSTEM;
906            params.installFlags |= PackageManager.INSTALL_ALL_USERS;
907        }
908
909        final int sessionId = mInterface.getPackageInstaller()
910                .createSession(params, installerPackageName, userId);
911        return sessionId;
912    }
913
914    private int doWriteSession(int sessionId, String inPath, long sizeBytes, String splitName,
915            boolean logSuccess) throws RemoteException {
916        final PrintWriter pw = getOutPrintWriter();
917        if ("-".equals(inPath)) {
918            inPath = null;
919        } else if (inPath != null) {
920            final File file = new File(inPath);
921            if (file.isFile()) {
922                sizeBytes = file.length();
923            }
924        }
925
926        final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId);
927
928        PackageInstaller.Session session = null;
929        InputStream in = null;
930        OutputStream out = null;
931        try {
932            session = new PackageInstaller.Session(
933                    mInterface.getPackageInstaller().openSession(sessionId));
934
935            if (inPath != null) {
936                in = new FileInputStream(inPath);
937            } else {
938                in = new SizedInputStream(getRawInputStream(), sizeBytes);
939            }
940            out = session.openWrite(splitName, 0, sizeBytes);
941
942            int total = 0;
943            byte[] buffer = new byte[65536];
944            int c;
945            while ((c = in.read(buffer)) != -1) {
946                total += c;
947                out.write(buffer, 0, c);
948
949                if (info.sizeBytes > 0) {
950                    final float fraction = ((float) c / (float) info.sizeBytes);
951                    session.addProgress(fraction);
952                }
953            }
954            session.fsync(out);
955
956            if (logSuccess) {
957                pw.println("Success: streamed " + total + " bytes");
958            }
959            return 0;
960        } catch (IOException e) {
961            pw.println("Error: failed to write; " + e.getMessage());
962            return 1;
963        } finally {
964            IoUtils.closeQuietly(out);
965            IoUtils.closeQuietly(in);
966            IoUtils.closeQuietly(session);
967        }
968    }
969
970    private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
971        final PrintWriter pw = getOutPrintWriter();
972        PackageInstaller.Session session = null;
973        try {
974            session = new PackageInstaller.Session(
975                    mInterface.getPackageInstaller().openSession(sessionId));
976
977            final LocalIntentReceiver receiver = new LocalIntentReceiver();
978            session.commit(receiver.getIntentSender());
979
980            final Intent result = receiver.getResult();
981            final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
982                    PackageInstaller.STATUS_FAILURE);
983            if (status == PackageInstaller.STATUS_SUCCESS) {
984                if (logSuccess) {
985                    System.out.println("Success");
986                }
987            } else {
988                pw.println("Failure ["
989                        + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
990            }
991            return status;
992        } finally {
993            IoUtils.closeQuietly(session);
994        }
995    }
996
997    private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
998        final PrintWriter pw = getOutPrintWriter();
999        PackageInstaller.Session session = null;
1000        try {
1001            session = new PackageInstaller.Session(
1002                    mInterface.getPackageInstaller().openSession(sessionId));
1003            session.abandon();
1004            if (logSuccess) {
1005                pw.println("Success");
1006            }
1007            return 0;
1008        } finally {
1009            IoUtils.closeQuietly(session);
1010        }
1011    }
1012
1013    private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
1014            boolean summary, int startProtectionLevel, int endProtectionLevel)
1015                    throws RemoteException {
1016        final PrintWriter pw = getOutPrintWriter();
1017        final int groupCount = groupList.size();
1018        for (int i = 0; i < groupCount; i++) {
1019            String groupName = groupList.get(i);
1020            String prefix = "";
1021            if (groups) {
1022                if (i > 0) {
1023                    pw.println("");
1024                }
1025                if (groupName != null) {
1026                    PermissionGroupInfo pgi =
1027                            mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
1028                    if (summary) {
1029                        Resources res = getResources(pgi);
1030                        if (res != null) {
1031                            pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
1032                        } else {
1033                            pw.print(pgi.name + ": ");
1034
1035                        }
1036                    } else {
1037                        pw.println((labels ? "+ " : "") + "group:" + pgi.name);
1038                        if (labels) {
1039                            pw.println("  package:" + pgi.packageName);
1040                            Resources res = getResources(pgi);
1041                            if (res != null) {
1042                                pw.println("  label:"
1043                                        + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
1044                                pw.println("  description:"
1045                                        + loadText(pgi, pgi.descriptionRes,
1046                                                pgi.nonLocalizedDescription));
1047                            }
1048                        }
1049                    }
1050                } else {
1051                    pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
1052                }
1053                prefix = "  ";
1054            }
1055            List<PermissionInfo> ps =
1056                    mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/);
1057            final int count = ps.size();
1058            boolean first = true;
1059            for (int p = 0 ; p < count ; p++) {
1060                PermissionInfo pi = ps.get(p);
1061                if (groups && groupName == null && pi.group != null) {
1062                    continue;
1063                }
1064                final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
1065                if (base < startProtectionLevel
1066                        || base > endProtectionLevel) {
1067                    continue;
1068                }
1069                if (summary) {
1070                    if (first) {
1071                        first = false;
1072                    } else {
1073                        pw.print(", ");
1074                    }
1075                    Resources res = getResources(pi);
1076                    if (res != null) {
1077                        pw.print(loadText(pi, pi.labelRes,
1078                                pi.nonLocalizedLabel));
1079                    } else {
1080                        pw.print(pi.name);
1081                    }
1082                } else {
1083                    pw.println(prefix + (labels ? "+ " : "")
1084                            + "permission:" + pi.name);
1085                    if (labels) {
1086                        pw.println(prefix + "  package:" + pi.packageName);
1087                        Resources res = getResources(pi);
1088                        if (res != null) {
1089                            pw.println(prefix + "  label:"
1090                                    + loadText(pi, pi.labelRes,
1091                                            pi.nonLocalizedLabel));
1092                            pw.println(prefix + "  description:"
1093                                    + loadText(pi, pi.descriptionRes,
1094                                            pi.nonLocalizedDescription));
1095                        }
1096                        pw.println(prefix + "  protectionLevel:"
1097                                + PermissionInfo.protectionToString(pi.protectionLevel));
1098                    }
1099                }
1100            }
1101
1102            if (summary) {
1103                pw.println("");
1104            }
1105        }
1106    }
1107
1108    private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
1109            throws RemoteException {
1110        if (nonLocalized != null) {
1111            return nonLocalized.toString();
1112        }
1113        if (res != 0) {
1114            Resources r = getResources(pii);
1115            if (r != null) {
1116                try {
1117                    return r.getString(res);
1118                } catch (Resources.NotFoundException e) {
1119                }
1120            }
1121        }
1122        return null;
1123    }
1124
1125    private Resources getResources(PackageItemInfo pii) throws RemoteException {
1126        Resources res = mResourceCache.get(pii.packageName);
1127        if (res != null) return res;
1128
1129        ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0);
1130        AssetManager am = new AssetManager();
1131        am.addAssetPath(ai.publicSourceDir);
1132        res = new Resources(am, null, null);
1133        mResourceCache.put(pii.packageName, res);
1134        return res;
1135    }
1136
1137    @Override
1138    public void onHelp() {
1139        final PrintWriter pw = getOutPrintWriter();
1140        pw.println("Package manager (package) commands:");
1141        pw.println("  help");
1142        pw.println("    Print this help text.");
1143        pw.println("");
1144        pw.println("  compile [-m MODE] [-f] TARGET-PACKAGE");
1145        pw.println("    Trigger compilation of TARGET-PACKAGE.");
1146        pw.println("    Options:");
1147        pw.println("      -m: select compilation mode");
1148        pw.println("          MODE can be one of \"default\", \"all\", \"profile\", and \"extract\"");
1149        pw.println("      -f: force compilation even if not needed");
1150        pw.println("  list features");
1151        pw.println("    Prints all features of the system.");
1152        pw.println("  list instrumentation [-f] [TARGET-PACKAGE]");
1153        pw.println("    Prints all test packages; optionally only those targeting TARGET-PACKAGE");
1154        pw.println("    Options:");
1155        pw.println("      -f: dump the name of the .apk file containing the test package");
1156        pw.println("  list libraries");
1157        pw.println("    Prints all system libraries.");
1158        pw.println("  list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]");
1159        pw.println("    Prints all packages; optionally only those whose name contains");
1160        pw.println("    the text in FILTER.");
1161        pw.println("    Options:");
1162        pw.println("      -f: see their associated file");
1163        pw.println("      -d: filter to only show disabled packages");
1164        pw.println("      -e: filter to only show enabled packages");
1165        pw.println("      -s: filter to only show system packages");
1166        pw.println("      -3: filter to only show third party packages");
1167        pw.println("      -i: see the installer for the packages");
1168        pw.println("      -u: also include uninstalled packages");
1169        pw.println("  list permission-groups");
1170        pw.println("    Prints all known permission groups.");
1171        pw.println("  list permissions [-g] [-f] [-d] [-u] [GROUP]");
1172        pw.println("    Prints all known permissions; optionally only those in GROUP.");
1173        pw.println("    Options:");
1174        pw.println("      -g: organize by group");
1175        pw.println("      -f: print all information");
1176        pw.println("      -s: short summary");
1177        pw.println("      -d: only list dangerous permissions");
1178        pw.println("      -u: list only the permissions users will see");
1179        pw.println("  resolve-activity [--user USER_ID] INTENT");
1180        pw.println("    Prints the activity that resolves to the given Intent.");
1181        pw.println("  query-activities [--user USER_ID] INTENT");
1182        pw.println("    Prints all activities that can handle the given Intent.");
1183        pw.println("  query-services [--user USER_ID] INTENT");
1184        pw.println("    Prints all services that can handle the given Intent.");
1185        pw.println("  query-receivers [--user USER_ID] INTENT");
1186        pw.println("    Prints all broadcast receivers that can handle the given Intent.");
1187        pw.println("  suspend [--user USER_ID] TARGET-PACKAGE");
1188        pw.println("    Suspends the specified package (as user).");
1189        pw.println("  unsuspend [--user USER_ID] TARGET-PACKAGE");
1190        pw.println("    Unsuspends the specified package (as user).");
1191        pw.println();
1192        Intent.printIntentArgsHelp(pw , "");
1193    }
1194
1195    private static class LocalIntentReceiver {
1196        private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
1197
1198        private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
1199            @Override
1200            public int send(int code, Intent intent, String resolvedType,
1201                    IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
1202                try {
1203                    mResult.offer(intent, 5, TimeUnit.SECONDS);
1204                } catch (InterruptedException e) {
1205                    throw new RuntimeException(e);
1206                }
1207                return 0;
1208            }
1209        };
1210
1211        public IntentSender getIntentSender() {
1212            return new IntentSender((IIntentSender) mLocalSender);
1213        }
1214
1215        public Intent getResult() {
1216            try {
1217                return mResult.take();
1218            } catch (InterruptedException e) {
1219                throw new RuntimeException(e);
1220            }
1221        }
1222    }
1223}
1224