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