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