PackageManagerShellCommand.java revision 3fc56c30000d9b88c2145d4297a97ec5061d60d1
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.accounts.IAccountManager;
20import android.app.ActivityManager;
21import android.content.ComponentName;
22import android.content.Context;
23import android.content.IIntentReceiver;
24import android.content.IIntentSender;
25import android.content.Intent;
26import android.content.IntentSender;
27import android.content.pm.ApplicationInfo;
28import android.content.pm.FeatureInfo;
29import android.content.pm.IPackageDataObserver;
30import android.content.pm.IPackageManager;
31import android.content.pm.InstrumentationInfo;
32import android.content.pm.PackageInfo;
33import android.content.pm.PackageInstaller;
34import android.content.pm.PackageItemInfo;
35import android.content.pm.PackageManager;
36import android.content.pm.PackageParser;
37import android.content.pm.PackageParser.ApkLite;
38import android.content.pm.PackageParser.PackageLite;
39import android.content.pm.PackageParser.PackageParserException;
40import android.content.pm.ParceledListSlice;
41import android.content.pm.PermissionGroupInfo;
42import android.content.pm.PermissionInfo;
43import android.content.pm.PackageInstaller.SessionInfo;
44import android.content.pm.PackageInstaller.SessionParams;
45import android.content.pm.PackageManager.NameNotFoundException;
46import android.content.pm.ResolveInfo;
47import android.content.pm.UserInfo;
48import android.content.pm.VersionedPackage;
49import android.content.pm.dex.DexMetadataHelper;
50import android.content.res.AssetManager;
51import android.content.res.Resources;
52import android.net.Uri;
53import android.os.Binder;
54import android.os.Build;
55import android.os.Bundle;
56import android.os.IBinder;
57import android.os.IUserManager;
58import android.os.ParcelFileDescriptor;
59import android.os.Process;
60import android.os.RemoteException;
61import android.os.ServiceManager;
62import android.os.ShellCommand;
63import android.os.SystemClock;
64import android.os.SystemProperties;
65import android.os.UserHandle;
66import android.os.UserManager;
67import android.os.storage.StorageManager;
68import android.text.TextUtils;
69import android.text.format.DateUtils;
70import android.util.ArraySet;
71import android.util.PrintWriterPrinter;
72
73import com.android.internal.content.PackageHelper;
74import com.android.internal.util.ArrayUtils;
75import com.android.internal.util.SizedInputStream;
76import com.android.server.SystemConfig;
77
78import dalvik.system.DexFile;
79
80import libcore.io.IoUtils;
81
82import java.io.IOException;
83import java.io.InputStream;
84import java.io.OutputStream;
85import java.io.PrintWriter;
86import java.net.URISyntaxException;
87import java.util.ArrayList;
88import java.util.Collections;
89import java.util.Comparator;
90import java.util.List;
91import java.util.Map;
92import java.util.WeakHashMap;
93import java.util.concurrent.SynchronousQueue;
94import java.util.concurrent.TimeUnit;
95
96import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
97import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
98import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
99import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
100import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
101
102class PackageManagerShellCommand extends ShellCommand {
103    /** Path for streaming APK content */
104    private static final String STDIN_PATH = "-";
105
106    final IPackageManager mInterface;
107    final private WeakHashMap<String, Resources> mResourceCache =
108            new WeakHashMap<String, Resources>();
109    int mTargetUser;
110    boolean mBrief;
111    boolean mComponents;
112
113    PackageManagerShellCommand(PackageManagerService service) {
114        mInterface = service;
115    }
116
117    @Override
118    public int onCommand(String cmd) {
119        if (cmd == null) {
120            return handleDefaultCommands(cmd);
121        }
122
123        final PrintWriter pw = getOutPrintWriter();
124        try {
125            switch(cmd) {
126                case "path":
127                    return runPath();
128                case "dump":
129                    return runDump();
130                case "list":
131                    return runList();
132                case "resolve-activity":
133                    return runResolveActivity();
134                case "query-activities":
135                    return runQueryIntentActivities();
136                case "query-services":
137                    return runQueryIntentServices();
138                case "query-receivers":
139                    return runQueryIntentReceivers();
140                case "install":
141                    return runInstall();
142                case "install-abandon":
143                case "install-destroy":
144                    return runInstallAbandon();
145                case "install-commit":
146                    return runInstallCommit();
147                case "install-create":
148                    return runInstallCreate();
149                case "install-remove":
150                    return runInstallRemove();
151                case "install-write":
152                    return runInstallWrite();
153                case "install-existing":
154                    return runInstallExisting();
155                case "set-install-location":
156                    return runSetInstallLocation();
157                case "get-install-location":
158                    return runGetInstallLocation();
159                case "move-package":
160                    return runMovePackage();
161                case "move-primary-storage":
162                    return runMovePrimaryStorage();
163                case "compile":
164                    return runCompile();
165                case "reconcile-secondary-dex-files":
166                    return runreconcileSecondaryDexFiles();
167                case "force-dex-opt":
168                    return runForceDexOpt();
169                case "bg-dexopt-job":
170                    return runDexoptJob();
171                case "dump-profiles":
172                    return runDumpProfiles();
173                case "uninstall":
174                    return runUninstall();
175                case "clear":
176                    return runClear();
177                case "enable":
178                    return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
179                case "disable":
180                    return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
181                case "disable-user":
182                    return runSetEnabledSetting(
183                            PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
184                case "disable-until-used":
185                    return runSetEnabledSetting(
186                            PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
187                case "default-state":
188                    return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
189                case "hide":
190                    return runSetHiddenSetting(true);
191                case "unhide":
192                    return runSetHiddenSetting(false);
193                case "suspend":
194                    return runSuspend(true);
195                case "unsuspend":
196                    return runSuspend(false);
197                case "grant":
198                    return runGrantRevokePermission(true);
199                case "revoke":
200                    return runGrantRevokePermission(false);
201                case "reset-permissions":
202                    return runResetPermissions();
203                case "set-permission-enforced":
204                    return runSetPermissionEnforced();
205                case "get-privapp-permissions":
206                    return runGetPrivappPermissions();
207                case "get-privapp-deny-permissions":
208                    return runGetPrivappDenyPermissions();
209                case "get-oem-permissions":
210                    return runGetOemPermissions();
211                case "set-app-link":
212                    return runSetAppLink();
213                case "get-app-link":
214                    return runGetAppLink();
215                case "trim-caches":
216                    return runTrimCaches();
217                case "create-user":
218                    return runCreateUser();
219                case "remove-user":
220                    return runRemoveUser();
221                case "set-user-restriction":
222                    return runSetUserRestriction();
223                case "get-max-users":
224                    return runGetMaxUsers();
225                case "set-home-activity":
226                    return runSetHomeActivity();
227                case "set-installer":
228                    return runSetInstaller();
229                case "get-instantapp-resolver":
230                    return runGetInstantAppResolver();
231                case "has-feature":
232                    return runHasFeature();
233                default: {
234                    String nextArg = getNextArg();
235                    if (nextArg == null) {
236                        if (cmd.equalsIgnoreCase("-l")) {
237                            return runListPackages(false);
238                        } else if (cmd.equalsIgnoreCase("-lf")) {
239                            return runListPackages(true);
240                        }
241                    } else if (getNextArg() == null) {
242                        if (cmd.equalsIgnoreCase("-p")) {
243                            return displayPackageFilePath(nextArg, UserHandle.USER_SYSTEM);
244                        }
245                    }
246                    return handleDefaultCommands(cmd);
247                }
248            }
249        } catch (RemoteException e) {
250            pw.println("Remote exception: " + e);
251        }
252        return -1;
253    }
254
255    private void setParamsSize(InstallParams params, String inPath) {
256        if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
257            final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");
258            if (fd == null) {
259                getErrPrintWriter().println("Error: Can't open file: " + inPath);
260                throw new IllegalArgumentException("Error: Can't open file: " + inPath);
261            }
262            try {
263                ApkLite baseApk = PackageParser.parseApkLite(fd.getFileDescriptor(), inPath, 0);
264                PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
265                        null, null);
266                params.sessionParams.setSize(PackageHelper.calculateInstalledSize(
267                        pkgLite, params.sessionParams.abiOverride, fd.getFileDescriptor()));
268            } catch (PackageParserException | IOException e) {
269                getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath);
270                throw new IllegalArgumentException(
271                        "Error: Failed to parse APK file: " + inPath, e);
272            } finally {
273                try {
274                    fd.close();
275                } catch (IOException e) {
276                }
277            }
278        }
279    }
280    /**
281     * Displays the package file for a package.
282     * @param pckg
283     */
284    private int displayPackageFilePath(String pckg, int userId) throws RemoteException {
285        PackageInfo info = mInterface.getPackageInfo(pckg, 0, userId);
286        if (info != null && info.applicationInfo != null) {
287            final PrintWriter pw = getOutPrintWriter();
288            pw.print("package:");
289            pw.println(info.applicationInfo.sourceDir);
290            if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
291                for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
292                    pw.print("package:");
293                    pw.println(splitSourceDir);
294                }
295            }
296            return 0;
297        }
298        return 1;
299    }
300
301    private int runPath() throws RemoteException {
302        int userId = UserHandle.USER_SYSTEM;
303        String option = getNextOption();
304        if (option != null && option.equals("--user")) {
305            userId = UserHandle.parseUserArg(getNextArgRequired());
306        }
307
308        String pkg = getNextArgRequired();
309        if (pkg == null) {
310            getErrPrintWriter().println("Error: no package specified");
311            return 1;
312        }
313        return displayPackageFilePath(pkg, userId);
314    }
315
316    private int runList() throws RemoteException {
317        final PrintWriter pw = getOutPrintWriter();
318        final String type = getNextArg();
319        if (type == null) {
320            pw.println("Error: didn't specify type of data to list");
321            return -1;
322        }
323        switch(type) {
324            case "features":
325                return runListFeatures();
326            case "instrumentation":
327                return runListInstrumentation();
328            case "libraries":
329                return runListLibraries();
330            case "package":
331            case "packages":
332                return runListPackages(false /*showSourceDir*/);
333            case "permission-groups":
334                return runListPermissionGroups();
335            case "permissions":
336                return runListPermissions();
337            case "users":
338                ServiceManager.getService("user").shellCommand(
339                        getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
340                        new String[] { "list" }, getShellCallback(), adoptResultReceiver());
341                return 0;
342        }
343        pw.println("Error: unknown list type '" + type + "'");
344        return -1;
345    }
346
347    private int runListFeatures() throws RemoteException {
348        final PrintWriter pw = getOutPrintWriter();
349        final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
350
351        // sort by name
352        Collections.sort(list, new Comparator<FeatureInfo>() {
353            public int compare(FeatureInfo o1, FeatureInfo o2) {
354                if (o1.name == o2.name) return 0;
355                if (o1.name == null) return -1;
356                if (o2.name == null) return 1;
357                return o1.name.compareTo(o2.name);
358            }
359        });
360
361        final int count = (list != null) ? list.size() : 0;
362        for (int p = 0; p < count; p++) {
363            FeatureInfo fi = list.get(p);
364            pw.print("feature:");
365            if (fi.name != null) {
366                pw.print(fi.name);
367                if (fi.version > 0) {
368                    pw.print("=");
369                    pw.print(fi.version);
370                }
371                pw.println();
372            } else {
373                pw.println("reqGlEsVersion=0x"
374                        + Integer.toHexString(fi.reqGlEsVersion));
375            }
376        }
377        return 0;
378    }
379
380    private int runListInstrumentation() throws RemoteException {
381        final PrintWriter pw = getOutPrintWriter();
382        boolean showSourceDir = false;
383        String targetPackage = null;
384
385        try {
386            String opt;
387            while ((opt = getNextArg()) != null) {
388                switch (opt) {
389                    case "-f":
390                        showSourceDir = true;
391                        break;
392                    default:
393                        if (opt.charAt(0) != '-') {
394                            targetPackage = opt;
395                        } else {
396                            pw.println("Error: Unknown option: " + opt);
397                            return -1;
398                        }
399                        break;
400                }
401            }
402        } catch (RuntimeException ex) {
403            pw.println("Error: " + ex.toString());
404            return -1;
405        }
406
407        final List<InstrumentationInfo> list =
408                mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
409
410        // sort by target package
411        Collections.sort(list, new Comparator<InstrumentationInfo>() {
412            public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
413                return o1.targetPackage.compareTo(o2.targetPackage);
414            }
415        });
416
417        final int count = (list != null) ? list.size() : 0;
418        for (int p = 0; p < count; p++) {
419            final InstrumentationInfo ii = list.get(p);
420            pw.print("instrumentation:");
421            if (showSourceDir) {
422                pw.print(ii.sourceDir);
423                pw.print("=");
424            }
425            final ComponentName cn = new ComponentName(ii.packageName, ii.name);
426            pw.print(cn.flattenToShortString());
427            pw.print(" (target=");
428            pw.print(ii.targetPackage);
429            pw.println(")");
430        }
431        return 0;
432    }
433
434    private int runListLibraries() throws RemoteException {
435        final PrintWriter pw = getOutPrintWriter();
436        final List<String> list = new ArrayList<String>();
437        final String[] rawList = mInterface.getSystemSharedLibraryNames();
438        for (int i = 0; i < rawList.length; i++) {
439            list.add(rawList[i]);
440        }
441
442        // sort by name
443        Collections.sort(list, new Comparator<String>() {
444            public int compare(String o1, String o2) {
445                if (o1 == o2) return 0;
446                if (o1 == null) return -1;
447                if (o2 == null) return 1;
448                return o1.compareTo(o2);
449            }
450        });
451
452        final int count = (list != null) ? list.size() : 0;
453        for (int p = 0; p < count; p++) {
454            String lib = list.get(p);
455            pw.print("library:");
456            pw.println(lib);
457        }
458        return 0;
459    }
460
461    private int runListPackages(boolean showSourceDir) throws RemoteException {
462        final PrintWriter pw = getOutPrintWriter();
463        int getFlags = 0;
464        boolean listDisabled = false, listEnabled = false;
465        boolean listSystem = false, listThirdParty = false;
466        boolean listInstaller = false;
467        boolean showUid = false;
468        boolean showVersionCode = false;
469        int uid = -1;
470        int userId = UserHandle.USER_SYSTEM;
471        try {
472            String opt;
473            while ((opt = getNextOption()) != null) {
474                switch (opt) {
475                    case "-d":
476                        listDisabled = true;
477                        break;
478                    case "-e":
479                        listEnabled = true;
480                        break;
481                    case "-f":
482                        showSourceDir = true;
483                        break;
484                    case "-i":
485                        listInstaller = true;
486                        break;
487                    case "-l":
488                        // old compat
489                        break;
490                    case "-s":
491                        listSystem = true;
492                        break;
493                    case "-U":
494                        showUid = true;
495                        break;
496                    case "-u":
497                        getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
498                        break;
499                    case "-3":
500                        listThirdParty = true;
501                        break;
502                    case "--show-versioncode":
503                        showVersionCode = true;
504                        break;
505                    case "--user":
506                        userId = UserHandle.parseUserArg(getNextArgRequired());
507                        break;
508                    case "--uid":
509                        showUid = true;
510                        uid = Integer.parseInt(getNextArgRequired());
511                        break;
512                    default:
513                        pw.println("Error: Unknown option: " + opt);
514                        return -1;
515                }
516            }
517        } catch (RuntimeException ex) {
518            pw.println("Error: " + ex.toString());
519            return -1;
520        }
521
522        final String filter = getNextArg();
523
524        @SuppressWarnings("unchecked")
525        final ParceledListSlice<PackageInfo> slice =
526                mInterface.getInstalledPackages(getFlags, userId);
527        final List<PackageInfo> packages = slice.getList();
528
529        final int count = packages.size();
530        for (int p = 0; p < count; p++) {
531            final PackageInfo info = packages.get(p);
532            if (filter != null && !info.packageName.contains(filter)) {
533                continue;
534            }
535            if (uid != -1 && info.applicationInfo.uid != uid) {
536                continue;
537            }
538            final boolean isSystem =
539                    (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
540            if ((!listDisabled || !info.applicationInfo.enabled) &&
541                    (!listEnabled || info.applicationInfo.enabled) &&
542                    (!listSystem || isSystem) &&
543                    (!listThirdParty || !isSystem)) {
544                pw.print("package:");
545                if (showSourceDir) {
546                    pw.print(info.applicationInfo.sourceDir);
547                    pw.print("=");
548                }
549                pw.print(info.packageName);
550                if (showVersionCode) {
551                    pw.print(" versionCode:");
552                    pw.print(info.applicationInfo.versionCode);
553                }
554                if (listInstaller) {
555                    pw.print("  installer=");
556                    pw.print(mInterface.getInstallerPackageName(info.packageName));
557                }
558                if (showUid) {
559                    pw.print(" uid:");
560                    pw.print(info.applicationInfo.uid);
561                }
562                pw.println();
563            }
564        }
565        return 0;
566    }
567
568    private int runListPermissionGroups() throws RemoteException {
569        final PrintWriter pw = getOutPrintWriter();
570        final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList();
571
572        final int count = pgs.size();
573        for (int p = 0; p < count ; p++) {
574            final PermissionGroupInfo pgi = pgs.get(p);
575            pw.print("permission group:");
576            pw.println(pgi.name);
577        }
578        return 0;
579    }
580
581    private int runListPermissions() throws RemoteException {
582        final PrintWriter pw = getOutPrintWriter();
583        boolean labels = false;
584        boolean groups = false;
585        boolean userOnly = false;
586        boolean summary = false;
587        boolean dangerousOnly = false;
588        String opt;
589        while ((opt = getNextOption()) != null) {
590            switch (opt) {
591                case "-d":
592                    dangerousOnly = true;
593                    break;
594                case "-f":
595                    labels = true;
596                    break;
597                case "-g":
598                    groups = true;
599                    break;
600                case "-s":
601                    groups = true;
602                    labels = true;
603                    summary = true;
604                    break;
605                case "-u":
606                    userOnly = true;
607                    break;
608                default:
609                    pw.println("Error: Unknown option: " + opt);
610                    return 1;
611            }
612        }
613
614        final ArrayList<String> groupList = new ArrayList<String>();
615        if (groups) {
616            final List<PermissionGroupInfo> infos =
617                    mInterface.getAllPermissionGroups(0 /*flags*/).getList();
618            final int count = infos.size();
619            for (int i = 0; i < count; i++) {
620                groupList.add(infos.get(i).name);
621            }
622            groupList.add(null);
623        } else {
624            final String grp = getNextArg();
625            groupList.add(grp);
626        }
627
628        if (dangerousOnly) {
629            pw.println("Dangerous Permissions:");
630            pw.println("");
631            doListPermissions(groupList, groups, labels, summary,
632                    PermissionInfo.PROTECTION_DANGEROUS,
633                    PermissionInfo.PROTECTION_DANGEROUS);
634            if (userOnly) {
635                pw.println("Normal Permissions:");
636                pw.println("");
637                doListPermissions(groupList, groups, labels, summary,
638                        PermissionInfo.PROTECTION_NORMAL,
639                        PermissionInfo.PROTECTION_NORMAL);
640            }
641        } else if (userOnly) {
642            pw.println("Dangerous and Normal Permissions:");
643            pw.println("");
644            doListPermissions(groupList, groups, labels, summary,
645                    PermissionInfo.PROTECTION_NORMAL,
646                    PermissionInfo.PROTECTION_DANGEROUS);
647        } else {
648            pw.println("All Permissions:");
649            pw.println("");
650            doListPermissions(groupList, groups, labels, summary,
651                    -10000, 10000);
652        }
653        return 0;
654    }
655
656    private Intent parseIntentAndUser() throws URISyntaxException {
657        mTargetUser = UserHandle.USER_CURRENT;
658        mBrief = false;
659        mComponents = false;
660        Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
661            @Override
662            public boolean handleOption(String opt, ShellCommand cmd) {
663                if ("--user".equals(opt)) {
664                    mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
665                    return true;
666                } else if ("--brief".equals(opt)) {
667                    mBrief = true;
668                    return true;
669                } else if ("--components".equals(opt)) {
670                    mComponents = true;
671                    return true;
672                }
673                return false;
674            }
675        });
676        mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
677                Binder.getCallingUid(), mTargetUser, false, false, null, null);
678        return intent;
679    }
680
681    private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri,
682            boolean brief, boolean components) {
683        if (brief || components) {
684            final ComponentName comp;
685            if (ri.activityInfo != null) {
686                comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
687            } else if (ri.serviceInfo != null) {
688                comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
689            } else if (ri.providerInfo != null) {
690                comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name);
691            } else {
692                comp = null;
693            }
694            if (comp != null) {
695                if (!components) {
696                    pr.println(prefix + "priority=" + ri.priority
697                            + " preferredOrder=" + ri.preferredOrder
698                            + " match=0x" + Integer.toHexString(ri.match)
699                            + " specificIndex=" + ri.specificIndex
700                            + " isDefault=" + ri.isDefault);
701                }
702                pr.println(prefix + comp.flattenToShortString());
703                return;
704            }
705        }
706        ri.dump(pr, prefix);
707    }
708
709    private int runResolveActivity() {
710        Intent intent;
711        try {
712            intent = parseIntentAndUser();
713        } catch (URISyntaxException e) {
714            throw new RuntimeException(e.getMessage(), e);
715        }
716        try {
717            ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), 0, mTargetUser);
718            PrintWriter pw = getOutPrintWriter();
719            if (ri == null) {
720                pw.println("No activity found");
721            } else {
722                PrintWriterPrinter pr = new PrintWriterPrinter(pw);
723                printResolveInfo(pr, "", ri, mBrief, mComponents);
724            }
725        } catch (RemoteException e) {
726            throw new RuntimeException("Failed calling service", e);
727        }
728        return 0;
729    }
730
731    private int runQueryIntentActivities() {
732        Intent intent;
733        try {
734            intent = parseIntentAndUser();
735        } catch (URISyntaxException e) {
736            throw new RuntimeException(e.getMessage(), e);
737        }
738        try {
739            List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(), 0,
740                    mTargetUser).getList();
741            PrintWriter pw = getOutPrintWriter();
742            if (result == null || result.size() <= 0) {
743                pw.println("No activities found");
744            } else {
745                if (!mComponents) {
746                    pw.print(result.size()); pw.println(" activities found:");
747                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
748                    for (int i = 0; i < result.size(); i++) {
749                        pw.print("  Activity #"); pw.print(i); pw.println(":");
750                        printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
751                    }
752                } else {
753                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
754                    for (int i = 0; i < result.size(); i++) {
755                        printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
756                    }
757                }
758            }
759        } catch (RemoteException e) {
760            throw new RuntimeException("Failed calling service", e);
761        }
762        return 0;
763    }
764
765    private int runQueryIntentServices() {
766        Intent intent;
767        try {
768            intent = parseIntentAndUser();
769        } catch (URISyntaxException e) {
770            throw new RuntimeException(e.getMessage(), e);
771        }
772        try {
773            List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(), 0,
774                    mTargetUser).getList();
775            PrintWriter pw = getOutPrintWriter();
776            if (result == null || result.size() <= 0) {
777                pw.println("No services found");
778            } else {
779                if (!mComponents) {
780                    pw.print(result.size()); pw.println(" services found:");
781                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
782                    for (int i = 0; i < result.size(); i++) {
783                        pw.print("  Service #"); pw.print(i); pw.println(":");
784                        printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
785                    }
786                } else {
787                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
788                    for (int i = 0; i < result.size(); i++) {
789                        printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
790                    }
791                }
792            }
793        } catch (RemoteException e) {
794            throw new RuntimeException("Failed calling service", e);
795        }
796        return 0;
797    }
798
799    private int runQueryIntentReceivers() {
800        Intent intent;
801        try {
802            intent = parseIntentAndUser();
803        } catch (URISyntaxException e) {
804            throw new RuntimeException(e.getMessage(), e);
805        }
806        try {
807            List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(), 0,
808                    mTargetUser).getList();
809            PrintWriter pw = getOutPrintWriter();
810            if (result == null || result.size() <= 0) {
811                pw.println("No receivers found");
812            } else {
813                if (!mComponents) {
814                    pw.print(result.size()); pw.println(" receivers found:");
815                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
816                    for (int i = 0; i < result.size(); i++) {
817                        pw.print("  Receiver #"); pw.print(i); pw.println(":");
818                        printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
819                    }
820                } else {
821                    PrintWriterPrinter pr = new PrintWriterPrinter(pw);
822                    for (int i = 0; i < result.size(); i++) {
823                        printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
824                    }
825                }
826            }
827        } catch (RemoteException e) {
828            throw new RuntimeException("Failed calling service", e);
829        }
830        return 0;
831    }
832
833    private int runInstall() throws RemoteException {
834        final PrintWriter pw = getOutPrintWriter();
835        final InstallParams params = makeInstallParams();
836        final String inPath = getNextArg();
837
838        setParamsSize(params, inPath);
839        final int sessionId = doCreateSession(params.sessionParams,
840                params.installerPackageName, params.userId);
841        boolean abandonSession = true;
842        try {
843            if (inPath == null && params.sessionParams.sizeBytes == -1) {
844                pw.println("Error: must either specify a package size or an APK file");
845                return 1;
846            }
847            if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
848                    false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
849                return 1;
850            }
851            if (doCommitSession(sessionId, false /*logSuccess*/)
852                    != PackageInstaller.STATUS_SUCCESS) {
853                return 1;
854            }
855            abandonSession = false;
856            pw.println("Success");
857            return 0;
858        } finally {
859            if (abandonSession) {
860                try {
861                    doAbandonSession(sessionId, false /*logSuccess*/);
862                } catch (Exception ignore) {
863                }
864            }
865        }
866    }
867
868    private int runInstallAbandon() throws RemoteException {
869        final int sessionId = Integer.parseInt(getNextArg());
870        return doAbandonSession(sessionId, true /*logSuccess*/);
871    }
872
873    private int runInstallCommit() throws RemoteException {
874        final int sessionId = Integer.parseInt(getNextArg());
875        return doCommitSession(sessionId, true /*logSuccess*/);
876    }
877
878    private int runInstallCreate() throws RemoteException {
879        final PrintWriter pw = getOutPrintWriter();
880        final InstallParams installParams = makeInstallParams();
881        final int sessionId = doCreateSession(installParams.sessionParams,
882                installParams.installerPackageName, installParams.userId);
883
884        // NOTE: adb depends on parsing this string
885        pw.println("Success: created install session [" + sessionId + "]");
886        return 0;
887    }
888
889    private int runInstallWrite() throws RemoteException {
890        long sizeBytes = -1;
891
892        String opt;
893        while ((opt = getNextOption()) != null) {
894            if (opt.equals("-S")) {
895                sizeBytes = Long.parseLong(getNextArg());
896            } else {
897                throw new IllegalArgumentException("Unknown option: " + opt);
898            }
899        }
900
901        final int sessionId = Integer.parseInt(getNextArg());
902        final String splitName = getNextArg();
903        final String path = getNextArg();
904        return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
905    }
906
907    private int runInstallRemove() throws RemoteException {
908        final PrintWriter pw = getOutPrintWriter();
909
910        final int sessionId = Integer.parseInt(getNextArg());
911
912        final String splitName = getNextArg();
913        if (splitName == null) {
914            pw.println("Error: split name not specified");
915            return 1;
916        }
917        return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
918    }
919
920    private int runInstallExisting() throws RemoteException {
921        final PrintWriter pw = getOutPrintWriter();
922        int userId = UserHandle.USER_SYSTEM;
923        int installFlags = 0;
924        String opt;
925        while ((opt = getNextOption()) != null) {
926            switch (opt) {
927                case "--user":
928                    userId = UserHandle.parseUserArg(getNextArgRequired());
929                    break;
930                case "--ephemeral":
931                case "--instant":
932                    installFlags |= PackageManager.INSTALL_INSTANT_APP;
933                    installFlags &= ~PackageManager.INSTALL_FULL_APP;
934                    break;
935                case "--full":
936                    installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
937                    installFlags |= PackageManager.INSTALL_FULL_APP;
938                    break;
939                default:
940                    pw.println("Error: Unknown option: " + opt);
941                    return 1;
942            }
943        }
944
945        final String packageName = getNextArg();
946        if (packageName == null) {
947            pw.println("Error: package name not specified");
948            return 1;
949        }
950
951        try {
952            final int res = mInterface.installExistingPackageAsUser(packageName, userId,
953                    installFlags, PackageManager.INSTALL_REASON_UNKNOWN);
954            if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
955                throw new NameNotFoundException("Package " + packageName + " doesn't exist");
956            }
957            pw.println("Package " + packageName + " installed for user: " + userId);
958            return 0;
959        } catch (RemoteException | NameNotFoundException e) {
960            pw.println(e.toString());
961            return 1;
962        }
963    }
964
965    private int runSetInstallLocation() throws RemoteException {
966        int loc;
967
968        String arg = getNextArg();
969        if (arg == null) {
970            getErrPrintWriter().println("Error: no install location specified.");
971            return 1;
972        }
973        try {
974            loc = Integer.parseInt(arg);
975        } catch (NumberFormatException e) {
976            getErrPrintWriter().println("Error: install location has to be a number.");
977            return 1;
978        }
979        if (!mInterface.setInstallLocation(loc)) {
980            getErrPrintWriter().println("Error: install location has to be a number.");
981            return 1;
982        }
983        return 0;
984    }
985
986    private int runGetInstallLocation() throws RemoteException {
987        int loc = mInterface.getInstallLocation();
988        String locStr = "invalid";
989        if (loc == PackageHelper.APP_INSTALL_AUTO) {
990            locStr = "auto";
991        } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
992            locStr = "internal";
993        } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
994            locStr = "external";
995        }
996        getOutPrintWriter().println(loc + "[" + locStr + "]");
997        return 0;
998    }
999
1000    public int runMovePackage() throws RemoteException {
1001        final String packageName = getNextArg();
1002        if (packageName == null) {
1003            getErrPrintWriter().println("Error: package name not specified");
1004            return 1;
1005        }
1006        String volumeUuid = getNextArg();
1007        if ("internal".equals(volumeUuid)) {
1008            volumeUuid = null;
1009        }
1010
1011        final int moveId = mInterface.movePackage(packageName, volumeUuid);
1012
1013        int status = mInterface.getMoveStatus(moveId);
1014        while (!PackageManager.isMoveStatusFinished(status)) {
1015            SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1016            status = mInterface.getMoveStatus(moveId);
1017        }
1018
1019        if (status == PackageManager.MOVE_SUCCEEDED) {
1020            getOutPrintWriter().println("Success");
1021            return 0;
1022        } else {
1023            getErrPrintWriter().println("Failure [" + status + "]");
1024            return 1;
1025        }
1026    }
1027
1028    public int runMovePrimaryStorage() throws RemoteException {
1029        String volumeUuid = getNextArg();
1030        if ("internal".equals(volumeUuid)) {
1031            volumeUuid = null;
1032        }
1033
1034        final int moveId = mInterface.movePrimaryStorage(volumeUuid);
1035
1036        int status = mInterface.getMoveStatus(moveId);
1037        while (!PackageManager.isMoveStatusFinished(status)) {
1038            SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1039            status = mInterface.getMoveStatus(moveId);
1040        }
1041
1042        if (status == PackageManager.MOVE_SUCCEEDED) {
1043            getOutPrintWriter().println("Success");
1044            return 0;
1045        } else {
1046            getErrPrintWriter().println("Failure [" + status + "]");
1047            return 1;
1048        }
1049    }
1050
1051    private int runCompile() throws RemoteException {
1052        final PrintWriter pw = getOutPrintWriter();
1053        boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
1054        boolean forceCompilation = false;
1055        boolean allPackages = false;
1056        boolean clearProfileData = false;
1057        String compilerFilter = null;
1058        String compilationReason = null;
1059        String checkProfilesRaw = null;
1060        boolean secondaryDex = false;
1061        String split = null;
1062
1063        String opt;
1064        while ((opt = getNextOption()) != null) {
1065            switch (opt) {
1066                case "-a":
1067                    allPackages = true;
1068                    break;
1069                case "-c":
1070                    clearProfileData = true;
1071                    break;
1072                case "-f":
1073                    forceCompilation = true;
1074                    break;
1075                case "-m":
1076                    compilerFilter = getNextArgRequired();
1077                    break;
1078                case "-r":
1079                    compilationReason = getNextArgRequired();
1080                    break;
1081                case "--check-prof":
1082                    checkProfilesRaw = getNextArgRequired();
1083                    break;
1084                case "--reset":
1085                    forceCompilation = true;
1086                    clearProfileData = true;
1087                    compilationReason = "install";
1088                    break;
1089                case "--secondary-dex":
1090                    secondaryDex = true;
1091                    break;
1092                case "--split":
1093                    split = getNextArgRequired();
1094                    break;
1095                default:
1096                    pw.println("Error: Unknown option: " + opt);
1097                    return 1;
1098            }
1099        }
1100
1101        if (checkProfilesRaw != null) {
1102            if ("true".equals(checkProfilesRaw)) {
1103                checkProfiles = true;
1104            } else if ("false".equals(checkProfilesRaw)) {
1105                checkProfiles = false;
1106            } else {
1107                pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
1108                return 1;
1109            }
1110        }
1111
1112        if (compilerFilter != null && compilationReason != null) {
1113            pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " +
1114                    "at the same time");
1115            return 1;
1116        }
1117        if (compilerFilter == null && compilationReason == null) {
1118            pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " +
1119                    "reason (\"-r\") at the same time");
1120            return 1;
1121        }
1122
1123        if (allPackages && split != null) {
1124            pw.println("-a cannot be specified together with --split");
1125            return 1;
1126        }
1127
1128        if (secondaryDex && split != null) {
1129            pw.println("--secondary-dex cannot be specified together with --split");
1130            return 1;
1131        }
1132
1133        String targetCompilerFilter;
1134        if (compilerFilter != null) {
1135            if (!DexFile.isValidCompilerFilter(compilerFilter)) {
1136                pw.println("Error: \"" + compilerFilter +
1137                        "\" is not a valid compilation filter.");
1138                return 1;
1139            }
1140            targetCompilerFilter = compilerFilter;
1141        } else {
1142            int reason = -1;
1143            for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
1144                if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
1145                        compilationReason)) {
1146                    reason = i;
1147                    break;
1148                }
1149            }
1150            if (reason == -1) {
1151                pw.println("Error: Unknown compilation reason: " + compilationReason);
1152                return 1;
1153            }
1154            targetCompilerFilter =
1155                    PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
1156        }
1157
1158
1159        List<String> packageNames = null;
1160        if (allPackages) {
1161            packageNames = mInterface.getAllPackages();
1162        } else {
1163            String packageName = getNextArg();
1164            if (packageName == null) {
1165                pw.println("Error: package name not specified");
1166                return 1;
1167            }
1168            packageNames = Collections.singletonList(packageName);
1169        }
1170
1171        List<String> failedPackages = new ArrayList<>();
1172        int index = 0;
1173        for (String packageName : packageNames) {
1174            if (clearProfileData) {
1175                mInterface.clearApplicationProfileData(packageName);
1176            }
1177
1178            if (allPackages) {
1179                pw.println(++index + "/" + packageNames.size() + ": " + packageName);
1180                pw.flush();
1181            }
1182
1183            boolean result = secondaryDex
1184                    ? mInterface.performDexOptSecondary(packageName,
1185                            targetCompilerFilter, forceCompilation)
1186                    : mInterface.performDexOptMode(packageName,
1187                            checkProfiles, targetCompilerFilter, forceCompilation,
1188                            true /* bootComplete */, split);
1189            if (!result) {
1190                failedPackages.add(packageName);
1191            }
1192        }
1193
1194        if (failedPackages.isEmpty()) {
1195            pw.println("Success");
1196            return 0;
1197        } else if (failedPackages.size() == 1) {
1198            pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
1199            return 1;
1200        } else {
1201            pw.print("Failure: the following packages could not be compiled: ");
1202            boolean is_first = true;
1203            for (String packageName : failedPackages) {
1204                if (is_first) {
1205                    is_first = false;
1206                } else {
1207                    pw.print(", ");
1208                }
1209                pw.print(packageName);
1210            }
1211            pw.println();
1212            return 1;
1213        }
1214    }
1215
1216    private int runreconcileSecondaryDexFiles() throws RemoteException {
1217        String packageName = getNextArg();
1218        mInterface.reconcileSecondaryDexFiles(packageName);
1219        return 0;
1220    }
1221
1222    public int runForceDexOpt() throws RemoteException {
1223        mInterface.forceDexOpt(getNextArgRequired());
1224        return 0;
1225    }
1226
1227    private int runDexoptJob() throws RemoteException {
1228        String arg;
1229        List<String> packageNames = new ArrayList<>();
1230        while ((arg = getNextArg()) != null) {
1231            packageNames.add(arg);
1232        }
1233        boolean result = mInterface.runBackgroundDexoptJob(packageNames.isEmpty() ? null :
1234                packageNames);
1235        return result ? 0 : -1;
1236    }
1237
1238    private int runDumpProfiles() throws RemoteException {
1239        String packageName = getNextArg();
1240        mInterface.dumpProfiles(packageName);
1241        return 0;
1242    }
1243
1244    private int runUninstall() throws RemoteException {
1245        final PrintWriter pw = getOutPrintWriter();
1246        int flags = 0;
1247        int userId = UserHandle.USER_ALL;
1248        long versionCode = PackageManager.VERSION_CODE_HIGHEST;
1249
1250        String opt;
1251        while ((opt = getNextOption()) != null) {
1252            switch (opt) {
1253                case "-k":
1254                    flags |= PackageManager.DELETE_KEEP_DATA;
1255                    break;
1256                case "--user":
1257                    userId = UserHandle.parseUserArg(getNextArgRequired());
1258                    break;
1259                case "--versionCode":
1260                    versionCode = Long.parseLong(getNextArgRequired());
1261                    break;
1262                default:
1263                    pw.println("Error: Unknown option: " + opt);
1264                    return 1;
1265            }
1266        }
1267
1268        final String packageName = getNextArg();
1269        if (packageName == null) {
1270            pw.println("Error: package name not specified");
1271            return 1;
1272        }
1273
1274        // if a split is specified, just remove it and not the whole package
1275        final String splitName = getNextArg();
1276        if (splitName != null) {
1277            return runRemoveSplit(packageName, splitName);
1278        }
1279
1280        userId = translateUserId(userId, "runUninstall");
1281        if (userId == UserHandle.USER_ALL) {
1282            userId = UserHandle.USER_SYSTEM;
1283            flags |= PackageManager.DELETE_ALL_USERS;
1284        } else {
1285            final PackageInfo info = mInterface.getPackageInfo(packageName,
1286                    PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId);
1287            if (info == null) {
1288                pw.println("Failure [not installed for " + userId + "]");
1289                return 1;
1290            }
1291            final boolean isSystem =
1292                    (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
1293            // If we are being asked to delete a system app for just one
1294            // user set flag so it disables rather than reverting to system
1295            // version of the app.
1296            if (isSystem) {
1297                flags |= PackageManager.DELETE_SYSTEM_APP;
1298            }
1299        }
1300
1301        final LocalIntentReceiver receiver = new LocalIntentReceiver();
1302        mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
1303                versionCode), null /*callerPackageName*/, flags,
1304                receiver.getIntentSender(), userId);
1305
1306        final Intent result = receiver.getResult();
1307        final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1308                PackageInstaller.STATUS_FAILURE);
1309        if (status == PackageInstaller.STATUS_SUCCESS) {
1310            pw.println("Success");
1311            return 0;
1312        } else {
1313            pw.println("Failure ["
1314                    + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
1315            return 1;
1316        }
1317    }
1318
1319    private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
1320        final PrintWriter pw = getOutPrintWriter();
1321        final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
1322        sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1323        sessionParams.appPackageName = packageName;
1324        final int sessionId =
1325                doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
1326        boolean abandonSession = true;
1327        try {
1328            if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
1329                    != PackageInstaller.STATUS_SUCCESS) {
1330                return 1;
1331            }
1332            if (doCommitSession(sessionId, false /*logSuccess*/)
1333                    != PackageInstaller.STATUS_SUCCESS) {
1334                return 1;
1335            }
1336            abandonSession = false;
1337            pw.println("Success");
1338            return 0;
1339        } finally {
1340            if (abandonSession) {
1341                try {
1342                    doAbandonSession(sessionId, false /*logSuccess*/);
1343                } catch (Exception ignore) {
1344                }
1345            }
1346        }
1347    }
1348
1349    static class ClearDataObserver extends IPackageDataObserver.Stub {
1350        boolean finished;
1351        boolean result;
1352
1353        @Override
1354        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1355            synchronized (this) {
1356                finished = true;
1357                result = succeeded;
1358                notifyAll();
1359            }
1360        }
1361    }
1362
1363    private int runClear() throws RemoteException {
1364        int userId = UserHandle.USER_SYSTEM;
1365        String option = getNextOption();
1366        if (option != null && option.equals("--user")) {
1367            userId = UserHandle.parseUserArg(getNextArgRequired());
1368        }
1369
1370        String pkg = getNextArg();
1371        if (pkg == null) {
1372            getErrPrintWriter().println("Error: no package specified");
1373            return 1;
1374        }
1375
1376        ClearDataObserver obs = new ClearDataObserver();
1377        ActivityManager.getService().clearApplicationUserData(pkg, false, obs, userId);
1378        synchronized (obs) {
1379            while (!obs.finished) {
1380                try {
1381                    obs.wait();
1382                } catch (InterruptedException e) {
1383                }
1384            }
1385        }
1386
1387        if (obs.result) {
1388            getOutPrintWriter().println("Success");
1389            return 0;
1390        } else {
1391            getErrPrintWriter().println("Failed");
1392            return 1;
1393        }
1394    }
1395
1396    private static String enabledSettingToString(int state) {
1397        switch (state) {
1398            case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
1399                return "default";
1400            case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
1401                return "enabled";
1402            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
1403                return "disabled";
1404            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
1405                return "disabled-user";
1406            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
1407                return "disabled-until-used";
1408        }
1409        return "unknown";
1410    }
1411
1412    private int runSetEnabledSetting(int state) throws RemoteException {
1413        int userId = UserHandle.USER_SYSTEM;
1414        String option = getNextOption();
1415        if (option != null && option.equals("--user")) {
1416            userId = UserHandle.parseUserArg(getNextArgRequired());
1417        }
1418
1419        String pkg = getNextArg();
1420        if (pkg == null) {
1421            getErrPrintWriter().println("Error: no package or component specified");
1422            return 1;
1423        }
1424        ComponentName cn = ComponentName.unflattenFromString(pkg);
1425        if (cn == null) {
1426            mInterface.setApplicationEnabledSetting(pkg, state, 0, userId,
1427                    "shell:" + android.os.Process.myUid());
1428            getOutPrintWriter().println("Package " + pkg + " new state: "
1429                    + enabledSettingToString(
1430                    mInterface.getApplicationEnabledSetting(pkg, userId)));
1431            return 0;
1432        } else {
1433            mInterface.setComponentEnabledSetting(cn, state, 0, userId);
1434            getOutPrintWriter().println("Component " + cn.toShortString() + " new state: "
1435                    + enabledSettingToString(
1436                    mInterface.getComponentEnabledSetting(cn, userId)));
1437            return 0;
1438        }
1439    }
1440
1441    private int runSetHiddenSetting(boolean state) throws RemoteException {
1442        int userId = UserHandle.USER_SYSTEM;
1443        String option = getNextOption();
1444        if (option != null && option.equals("--user")) {
1445            userId = UserHandle.parseUserArg(getNextArgRequired());
1446        }
1447
1448        String pkg = getNextArg();
1449        if (pkg == null) {
1450            getErrPrintWriter().println("Error: no package or component specified");
1451            return 1;
1452        }
1453        mInterface.setApplicationHiddenSettingAsUser(pkg, state, userId);
1454        getOutPrintWriter().println("Package " + pkg + " new hidden state: "
1455                + mInterface.getApplicationHiddenSettingAsUser(pkg, userId));
1456        return 0;
1457    }
1458
1459    private int runSuspend(boolean suspendedState) {
1460        final PrintWriter pw = getOutPrintWriter();
1461        int userId = UserHandle.USER_SYSTEM;
1462        String opt;
1463        while ((opt = getNextOption()) != null) {
1464            switch (opt) {
1465                case "--user":
1466                    userId = UserHandle.parseUserArg(getNextArgRequired());
1467                    break;
1468                default:
1469                    pw.println("Error: Unknown option: " + opt);
1470                    return 1;
1471            }
1472        }
1473
1474        String packageName = getNextArg();
1475        if (packageName == null) {
1476            pw.println("Error: package name not specified");
1477            return 1;
1478        }
1479
1480        try {
1481            mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
1482                    userId);
1483            pw.println("Package " + packageName + " new suspended state: "
1484                    + mInterface.isPackageSuspendedForUser(packageName, userId));
1485            return 0;
1486        } catch (RemoteException | IllegalArgumentException e) {
1487            pw.println(e.toString());
1488            return 1;
1489        }
1490    }
1491
1492    private int runGrantRevokePermission(boolean grant) throws RemoteException {
1493        int userId = UserHandle.USER_SYSTEM;
1494
1495        String opt = null;
1496        while ((opt = getNextOption()) != null) {
1497            if (opt.equals("--user")) {
1498                userId = UserHandle.parseUserArg(getNextArgRequired());
1499            }
1500        }
1501
1502        String pkg = getNextArg();
1503        if (pkg == null) {
1504            getErrPrintWriter().println("Error: no package specified");
1505            return 1;
1506        }
1507        String perm = getNextArg();
1508        if (perm == null) {
1509            getErrPrintWriter().println("Error: no permission specified");
1510            return 1;
1511        }
1512
1513        if (grant) {
1514            mInterface.grantRuntimePermission(pkg, perm, userId);
1515        } else {
1516            mInterface.revokeRuntimePermission(pkg, perm, userId);
1517        }
1518        return 0;
1519    }
1520
1521    private int runResetPermissions() throws RemoteException {
1522        mInterface.resetRuntimePermissions();
1523        return 0;
1524    }
1525
1526    private int runSetPermissionEnforced() throws RemoteException {
1527        final String permission = getNextArg();
1528        if (permission == null) {
1529            getErrPrintWriter().println("Error: no permission specified");
1530            return 1;
1531        }
1532        final String enforcedRaw = getNextArg();
1533        if (enforcedRaw == null) {
1534            getErrPrintWriter().println("Error: no enforcement specified");
1535            return 1;
1536        }
1537        mInterface.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw));
1538        return 0;
1539    }
1540
1541    private boolean isVendorApp(String pkg) {
1542        try {
1543            final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
1544            return info != null && info.applicationInfo.isVendor();
1545        } catch (RemoteException e) {
1546            return false;
1547        }
1548    }
1549
1550    private int runGetPrivappPermissions() {
1551        final String pkg = getNextArg();
1552        if (pkg == null) {
1553            getErrPrintWriter().println("Error: no package specified.");
1554            return 1;
1555        }
1556
1557        ArraySet<String> privAppPermissions = isVendorApp(pkg) ?
1558                SystemConfig.getInstance().getVendorPrivAppPermissions(pkg)
1559                    : SystemConfig.getInstance().getPrivAppPermissions(pkg);
1560
1561        getOutPrintWriter().println(privAppPermissions == null
1562                ? "{}" : privAppPermissions.toString());
1563        return 0;
1564    }
1565
1566    private int runGetPrivappDenyPermissions() {
1567        final String pkg = getNextArg();
1568        if (pkg == null) {
1569            getErrPrintWriter().println("Error: no package specified.");
1570            return 1;
1571        }
1572
1573        ArraySet<String> privAppPermissions = isVendorApp(pkg) ?
1574                SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg)
1575                    : SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
1576
1577        getOutPrintWriter().println(privAppPermissions == null
1578                ? "{}" : privAppPermissions.toString());
1579        return 0;
1580    }
1581
1582    private int runGetOemPermissions() {
1583        final String pkg = getNextArg();
1584        if (pkg == null) {
1585            getErrPrintWriter().println("Error: no package specified.");
1586            return 1;
1587        }
1588        final Map<String, Boolean> oemPermissions = SystemConfig.getInstance()
1589                .getOemPermissions(pkg);
1590        if (oemPermissions == null || oemPermissions.isEmpty()) {
1591            getOutPrintWriter().println("{}");
1592        } else {
1593            oemPermissions.forEach((permission, granted) ->
1594                    getOutPrintWriter().println(permission + " granted:" + granted)
1595            );
1596        }
1597        return 0;
1598    }
1599
1600    private String linkStateToString(int state) {
1601        switch (state) {
1602            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
1603            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
1604            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
1605            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
1606            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
1607        }
1608        return "Unknown link state: " + state;
1609    }
1610
1611    // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
1612    private int runSetAppLink() throws RemoteException {
1613        int userId = UserHandle.USER_SYSTEM;
1614
1615        String opt;
1616        while ((opt = getNextOption()) != null) {
1617            if (opt.equals("--user")) {
1618                userId = UserHandle.parseUserArg(getNextArgRequired());
1619            } else {
1620                getErrPrintWriter().println("Error: unknown option: " + opt);
1621                return 1;
1622            }
1623        }
1624
1625        // Package name to act on; required
1626        final String pkg = getNextArg();
1627        if (pkg == null) {
1628            getErrPrintWriter().println("Error: no package specified.");
1629            return 1;
1630        }
1631
1632        // State to apply; {always|ask|never|undefined}, required
1633        final String modeString = getNextArg();
1634        if (modeString == null) {
1635            getErrPrintWriter().println("Error: no app link state specified.");
1636            return 1;
1637        }
1638
1639        final int newMode;
1640        switch (modeString.toLowerCase()) {
1641            case "undefined":
1642                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
1643                break;
1644
1645            case "always":
1646                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
1647                break;
1648
1649            case "ask":
1650                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
1651                break;
1652
1653            case "always-ask":
1654                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
1655                break;
1656
1657            case "never":
1658                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
1659                break;
1660
1661            default:
1662                getErrPrintWriter().println("Error: unknown app link state '" + modeString + "'");
1663                return 1;
1664        }
1665
1666        final PackageInfo info = mInterface.getPackageInfo(pkg, 0, userId);
1667        if (info == null) {
1668            getErrPrintWriter().println("Error: package " + pkg + " not found.");
1669            return 1;
1670        }
1671
1672        if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
1673            getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
1674            return 1;
1675        }
1676
1677        if (!mInterface.updateIntentVerificationStatus(pkg, newMode, userId)) {
1678            getErrPrintWriter().println("Error: unable to update app link status for " + pkg);
1679            return 1;
1680        }
1681
1682        return 0;
1683    }
1684
1685    // pm get-app-link [--user USER_ID] PACKAGE
1686    private int runGetAppLink() throws RemoteException {
1687        int userId = UserHandle.USER_SYSTEM;
1688
1689        String opt;
1690        while ((opt = getNextOption()) != null) {
1691            if (opt.equals("--user")) {
1692                userId = UserHandle.parseUserArg(getNextArgRequired());
1693            } else {
1694                getErrPrintWriter().println("Error: unknown option: " + opt);
1695                return 1;
1696            }
1697        }
1698
1699        // Package name to act on; required
1700        final String pkg = getNextArg();
1701        if (pkg == null) {
1702            getErrPrintWriter().println("Error: no package specified.");
1703            return 1;
1704        }
1705
1706        final PackageInfo info = mInterface.getPackageInfo(pkg, 0, userId);
1707        if (info == null) {
1708            getErrPrintWriter().println("Error: package " + pkg + " not found.");
1709            return 1;
1710        }
1711
1712        if ((info.applicationInfo.privateFlags
1713                & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
1714            getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
1715            return 1;
1716        }
1717
1718        getOutPrintWriter().println(linkStateToString(
1719                mInterface.getIntentVerificationStatus(pkg, userId)));
1720
1721        return 0;
1722    }
1723
1724    private int runTrimCaches() throws RemoteException {
1725        String size = getNextArg();
1726        if (size == null) {
1727            getErrPrintWriter().println("Error: no size specified");
1728            return 1;
1729        }
1730        long multiplier = 1;
1731        int len = size.length();
1732        char c = size.charAt(len - 1);
1733        if (c < '0' || c > '9') {
1734            if (c == 'K' || c == 'k') {
1735                multiplier = 1024L;
1736            } else if (c == 'M' || c == 'm') {
1737                multiplier = 1024L*1024L;
1738            } else if (c == 'G' || c == 'g') {
1739                multiplier = 1024L*1024L*1024L;
1740            } else {
1741                getErrPrintWriter().println("Invalid suffix: " + c);
1742                return 1;
1743            }
1744            size = size.substring(0, len-1);
1745        }
1746        long sizeVal;
1747        try {
1748            sizeVal = Long.parseLong(size) * multiplier;
1749        } catch (NumberFormatException e) {
1750            getErrPrintWriter().println("Error: expected number at: " + size);
1751            return 1;
1752        }
1753        String volumeUuid = getNextArg();
1754        if ("internal".equals(volumeUuid)) {
1755            volumeUuid = null;
1756        }
1757        ClearDataObserver obs = new ClearDataObserver();
1758        mInterface.freeStorageAndNotify(volumeUuid, sizeVal,
1759                StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs);
1760        synchronized (obs) {
1761            while (!obs.finished) {
1762                try {
1763                    obs.wait();
1764                } catch (InterruptedException e) {
1765                }
1766            }
1767        }
1768        return 0;
1769    }
1770
1771    private static boolean isNumber(String s) {
1772        try {
1773            Integer.parseInt(s);
1774        } catch (NumberFormatException nfe) {
1775            return false;
1776        }
1777        return true;
1778    }
1779
1780    public int runCreateUser() throws RemoteException {
1781        String name;
1782        int userId = -1;
1783        int flags = 0;
1784        String opt;
1785        while ((opt = getNextOption()) != null) {
1786            if ("--profileOf".equals(opt)) {
1787                userId = UserHandle.parseUserArg(getNextArgRequired());
1788            } else if ("--managed".equals(opt)) {
1789                flags |= UserInfo.FLAG_MANAGED_PROFILE;
1790            } else if ("--restricted".equals(opt)) {
1791                flags |= UserInfo.FLAG_RESTRICTED;
1792            } else if ("--ephemeral".equals(opt)) {
1793                flags |= UserInfo.FLAG_EPHEMERAL;
1794            } else if ("--guest".equals(opt)) {
1795                flags |= UserInfo.FLAG_GUEST;
1796            } else if ("--demo".equals(opt)) {
1797                flags |= UserInfo.FLAG_DEMO;
1798            } else {
1799                getErrPrintWriter().println("Error: unknown option " + opt);
1800                return 1;
1801            }
1802        }
1803        String arg = getNextArg();
1804        if (arg == null) {
1805            getErrPrintWriter().println("Error: no user name specified.");
1806            return 1;
1807        }
1808        name = arg;
1809        UserInfo info;
1810        IUserManager um = IUserManager.Stub.asInterface(
1811                ServiceManager.getService(Context.USER_SERVICE));
1812        IAccountManager accm = IAccountManager.Stub.asInterface(
1813                ServiceManager.getService(Context.ACCOUNT_SERVICE));
1814        if ((flags & UserInfo.FLAG_RESTRICTED) != 0) {
1815            // In non-split user mode, userId can only be SYSTEM
1816            int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
1817            info = um.createRestrictedProfile(name, parentUserId);
1818            accm.addSharedAccountsFromParentUser(parentUserId, userId,
1819                    (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
1820        } else if (userId < 0) {
1821            info = um.createUser(name, flags);
1822        } else {
1823            info = um.createProfileForUser(name, flags, userId, null);
1824        }
1825
1826        if (info != null) {
1827            getOutPrintWriter().println("Success: created user id " + info.id);
1828            return 0;
1829        } else {
1830            getErrPrintWriter().println("Error: couldn't create User.");
1831            return 1;
1832        }
1833    }
1834
1835    public int runRemoveUser() throws RemoteException {
1836        int userId;
1837        String arg = getNextArg();
1838        if (arg == null) {
1839            getErrPrintWriter().println("Error: no user id specified.");
1840            return 1;
1841        }
1842        userId = UserHandle.parseUserArg(arg);
1843        IUserManager um = IUserManager.Stub.asInterface(
1844                ServiceManager.getService(Context.USER_SERVICE));
1845        if (um.removeUser(userId)) {
1846            getOutPrintWriter().println("Success: removed user");
1847            return 0;
1848        } else {
1849            getErrPrintWriter().println("Error: couldn't remove user id " + userId);
1850            return 1;
1851        }
1852    }
1853
1854    public int runSetUserRestriction() throws RemoteException {
1855        int userId = UserHandle.USER_SYSTEM;
1856        String opt = getNextOption();
1857        if (opt != null && "--user".equals(opt)) {
1858            userId = UserHandle.parseUserArg(getNextArgRequired());
1859        }
1860
1861        String restriction = getNextArg();
1862        String arg = getNextArg();
1863        boolean value;
1864        if ("1".equals(arg)) {
1865            value = true;
1866        } else if ("0".equals(arg)) {
1867            value = false;
1868        } else {
1869            getErrPrintWriter().println("Error: valid value not specified");
1870            return 1;
1871        }
1872        IUserManager um = IUserManager.Stub.asInterface(
1873                ServiceManager.getService(Context.USER_SERVICE));
1874        um.setUserRestriction(restriction, value, userId);
1875        return 0;
1876    }
1877
1878    public int runGetMaxUsers() {
1879        getOutPrintWriter().println("Maximum supported users: "
1880                + UserManager.getMaxSupportedUsers());
1881        return 0;
1882    }
1883
1884    private static class InstallParams {
1885        SessionParams sessionParams;
1886        String installerPackageName;
1887        int userId = UserHandle.USER_ALL;
1888    }
1889
1890    private InstallParams makeInstallParams() {
1891        final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
1892        final InstallParams params = new InstallParams();
1893        params.sessionParams = sessionParams;
1894        String opt;
1895        boolean replaceExisting = true;
1896        while ((opt = getNextOption()) != null) {
1897            switch (opt) {
1898                case "-l":
1899                    sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
1900                    break;
1901                case "-r": // ignore
1902                    break;
1903                case "-R":
1904                    replaceExisting = false;
1905                    break;
1906                case "-i":
1907                    params.installerPackageName = getNextArg();
1908                    if (params.installerPackageName == null) {
1909                        throw new IllegalArgumentException("Missing installer package");
1910                    }
1911                    break;
1912                case "-t":
1913                    sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
1914                    break;
1915                case "-s":
1916                    sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL;
1917                    break;
1918                case "-f":
1919                    sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
1920                    break;
1921                case "-d":
1922                    sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
1923                    break;
1924                case "-g":
1925                    sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1926                    break;
1927                case "--dont-kill":
1928                    sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
1929                    break;
1930                case "--originating-uri":
1931                    sessionParams.originatingUri = Uri.parse(getNextArg());
1932                    break;
1933                case "--referrer":
1934                    sessionParams.referrerUri = Uri.parse(getNextArg());
1935                    break;
1936                case "-p":
1937                    sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
1938                    sessionParams.appPackageName = getNextArg();
1939                    if (sessionParams.appPackageName == null) {
1940                        throw new IllegalArgumentException("Missing inherit package name");
1941                    }
1942                    break;
1943                case "--pkg":
1944                    sessionParams.appPackageName = getNextArg();
1945                    if (sessionParams.appPackageName == null) {
1946                        throw new IllegalArgumentException("Missing package name");
1947                    }
1948                    break;
1949                case "-S":
1950                    final long sizeBytes = Long.parseLong(getNextArg());
1951                    if (sizeBytes <= 0) {
1952                        throw new IllegalArgumentException("Size must be positive");
1953                    }
1954                    sessionParams.setSize(sizeBytes);
1955                    break;
1956                case "--abi":
1957                    sessionParams.abiOverride = checkAbiArgument(getNextArg());
1958                    break;
1959                case "--ephemeral":
1960                case "--instant":
1961                case "--instantapp":
1962                    sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
1963                    break;
1964                case "--full":
1965                    sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
1966                    break;
1967                case "--preload":
1968                    sessionParams.setInstallAsVirtualPreload();
1969                    break;
1970                case "--user":
1971                    params.userId = UserHandle.parseUserArg(getNextArgRequired());
1972                    break;
1973                case "--install-location":
1974                    sessionParams.installLocation = Integer.parseInt(getNextArg());
1975                    break;
1976                case "--force-uuid":
1977                    sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
1978                    sessionParams.volumeUuid = getNextArg();
1979                    if ("internal".equals(sessionParams.volumeUuid)) {
1980                        sessionParams.volumeUuid = null;
1981                    }
1982                    break;
1983                case "--force-sdk":
1984                    sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK;
1985                    break;
1986                default:
1987                    throw new IllegalArgumentException("Unknown option " + opt);
1988            }
1989            if (replaceExisting) {
1990                sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1991            }
1992        }
1993        return params;
1994    }
1995
1996    private int runSetHomeActivity() {
1997        final PrintWriter pw = getOutPrintWriter();
1998        int userId = UserHandle.USER_SYSTEM;
1999        String opt;
2000        while ((opt = getNextOption()) != null) {
2001            switch (opt) {
2002                case "--user":
2003                    userId = UserHandle.parseUserArg(getNextArgRequired());
2004                    break;
2005                default:
2006                    pw.println("Error: Unknown option: " + opt);
2007                    return 1;
2008            }
2009        }
2010
2011        String component = getNextArg();
2012        ComponentName componentName =
2013                component != null ? ComponentName.unflattenFromString(component) : null;
2014
2015        if (componentName == null) {
2016            pw.println("Error: component name not specified or invalid");
2017            return 1;
2018        }
2019
2020        try {
2021            mInterface.setHomeActivity(componentName, userId);
2022            pw.println("Success");
2023            return 0;
2024        } catch (Exception e) {
2025            pw.println(e.toString());
2026            return 1;
2027        }
2028    }
2029
2030    private int runSetInstaller() throws RemoteException {
2031        final String targetPackage = getNextArg();
2032        final String installerPackageName = getNextArg();
2033
2034        if (targetPackage == null || installerPackageName == null) {
2035            getErrPrintWriter().println("Must provide both target and installer package names");
2036            return 1;
2037        }
2038
2039        mInterface.setInstallerPackageName(targetPackage, installerPackageName);
2040        getOutPrintWriter().println("Success");
2041        return 0;
2042    }
2043
2044    private int runGetInstantAppResolver() {
2045        final PrintWriter pw = getOutPrintWriter();
2046        try {
2047            final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent();
2048            if (instantAppsResolver == null) {
2049                return 1;
2050            }
2051            pw.println(instantAppsResolver.flattenToString());
2052            return 0;
2053        } catch (Exception e) {
2054            pw.println(e.toString());
2055            return 1;
2056        }
2057    }
2058
2059    private int runHasFeature() {
2060        final PrintWriter err = getErrPrintWriter();
2061        final String featureName = getNextArg();
2062        if (featureName == null) {
2063            err.println("Error: expected FEATURE name");
2064            return 1;
2065        }
2066        final String versionString = getNextArg();
2067        try {
2068            final int version = (versionString == null) ? 0 : Integer.parseInt(versionString);
2069            final boolean hasFeature = mInterface.hasSystemFeature(featureName, version);
2070            getOutPrintWriter().println(hasFeature);
2071            return hasFeature ? 0 : 1;
2072        } catch (NumberFormatException e) {
2073            err.println("Error: illegal version number " + versionString);
2074            return 1;
2075        } catch (RemoteException e) {
2076            err.println(e.toString());
2077            return 1;
2078        }
2079    }
2080
2081    private int runDump() {
2082        String pkg = getNextArg();
2083        if (pkg == null) {
2084            getErrPrintWriter().println("Error: no package specified");
2085            return 1;
2086        }
2087        ActivityManager.dumpPackageStateStatic(getOutFileDescriptor(), pkg);
2088        return 0;
2089    }
2090
2091    private static String checkAbiArgument(String abi) {
2092        if (TextUtils.isEmpty(abi)) {
2093            throw new IllegalArgumentException("Missing ABI argument");
2094        }
2095
2096        if ("-".equals(abi)) {
2097            return abi;
2098        }
2099
2100        final String[] supportedAbis = Build.SUPPORTED_ABIS;
2101        for (String supportedAbi : supportedAbis) {
2102            if (supportedAbi.equals(abi)) {
2103                return abi;
2104            }
2105        }
2106
2107        throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
2108    }
2109
2110    private int translateUserId(int userId, String logContext) {
2111        return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2112                userId, true, true, logContext, "pm command");
2113    }
2114
2115    private int doCreateSession(SessionParams params, String installerPackageName, int userId)
2116            throws RemoteException {
2117        userId = translateUserId(userId, "runInstallCreate");
2118        if (userId == UserHandle.USER_ALL) {
2119            userId = UserHandle.USER_SYSTEM;
2120            params.installFlags |= PackageManager.INSTALL_ALL_USERS;
2121        }
2122
2123        final int sessionId = mInterface.getPackageInstaller()
2124                .createSession(params, installerPackageName, userId);
2125        return sessionId;
2126    }
2127
2128    private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
2129            boolean logSuccess) throws RemoteException {
2130        final PrintWriter pw = getOutPrintWriter();
2131        final ParcelFileDescriptor fd;
2132        if (STDIN_PATH.equals(inPath)) {
2133            fd = null;
2134        } else if (inPath != null) {
2135            fd = openFileForSystem(inPath, "r");
2136            if (fd == null) {
2137                return -1;
2138            }
2139            sizeBytes = fd.getStatSize();
2140            if (sizeBytes < 0) {
2141                getErrPrintWriter().println("Unable to get size of: " + inPath);
2142                return -1;
2143            }
2144        } else {
2145            fd = null;
2146        }
2147        if (sizeBytes <= 0) {
2148            getErrPrintWriter().println("Error: must specify a APK size");
2149            return 1;
2150        }
2151
2152        final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId);
2153
2154        PackageInstaller.Session session = null;
2155        InputStream in = null;
2156        OutputStream out = null;
2157        try {
2158            session = new PackageInstaller.Session(
2159                    mInterface.getPackageInstaller().openSession(sessionId));
2160
2161            if (fd != null) {
2162                in = new ParcelFileDescriptor.AutoCloseInputStream(fd);
2163            } else {
2164                in = new SizedInputStream(getRawInputStream(), sizeBytes);
2165            }
2166            out = session.openWrite(splitName, 0, sizeBytes);
2167
2168            int total = 0;
2169            byte[] buffer = new byte[1024 * 1024];
2170            int c;
2171            while ((c = in.read(buffer)) != -1) {
2172                total += c;
2173                out.write(buffer, 0, c);
2174
2175                if (info.sizeBytes > 0) {
2176                    final float fraction = ((float) c / (float) info.sizeBytes);
2177                    session.addProgress(fraction);
2178                }
2179            }
2180            session.fsync(out);
2181
2182            if (logSuccess) {
2183                pw.println("Success: streamed " + total + " bytes");
2184            }
2185            return 0;
2186        } catch (IOException e) {
2187            getErrPrintWriter().println("Error: failed to write; " + e.getMessage());
2188            return 1;
2189        } finally {
2190            IoUtils.closeQuietly(out);
2191            IoUtils.closeQuietly(in);
2192            IoUtils.closeQuietly(session);
2193        }
2194    }
2195
2196    private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
2197            throws RemoteException {
2198        final PrintWriter pw = getOutPrintWriter();
2199        PackageInstaller.Session session = null;
2200        try {
2201            session = new PackageInstaller.Session(
2202                    mInterface.getPackageInstaller().openSession(sessionId));
2203            session.removeSplit(splitName);
2204
2205            if (logSuccess) {
2206                pw.println("Success");
2207            }
2208            return 0;
2209        } catch (IOException e) {
2210            pw.println("Error: failed to remove split; " + e.getMessage());
2211            return 1;
2212        } finally {
2213            IoUtils.closeQuietly(session);
2214        }
2215    }
2216
2217    private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
2218        final PrintWriter pw = getOutPrintWriter();
2219        PackageInstaller.Session session = null;
2220        try {
2221            session = new PackageInstaller.Session(
2222                    mInterface.getPackageInstaller().openSession(sessionId));
2223
2224            // Sanity check that all .dm files match an apk.
2225            // (The installer does not support standalone .dm files and will not process them.)
2226            try {
2227                DexMetadataHelper.validateDexPaths(session.getNames());
2228            } catch (IllegalStateException | IOException e) {
2229                pw.println("Warning [Could not validate the dex paths: " + e.getMessage() + "]");
2230            }
2231
2232            final LocalIntentReceiver receiver = new LocalIntentReceiver();
2233            session.commit(receiver.getIntentSender());
2234
2235            final Intent result = receiver.getResult();
2236            final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
2237                    PackageInstaller.STATUS_FAILURE);
2238            if (status == PackageInstaller.STATUS_SUCCESS) {
2239                if (logSuccess) {
2240                    pw.println("Success");
2241                }
2242            } else {
2243                pw.println("Failure ["
2244                        + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
2245            }
2246            return status;
2247        } finally {
2248            IoUtils.closeQuietly(session);
2249        }
2250    }
2251
2252    private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
2253        final PrintWriter pw = getOutPrintWriter();
2254        PackageInstaller.Session session = null;
2255        try {
2256            session = new PackageInstaller.Session(
2257                    mInterface.getPackageInstaller().openSession(sessionId));
2258            session.abandon();
2259            if (logSuccess) {
2260                pw.println("Success");
2261            }
2262            return 0;
2263        } finally {
2264            IoUtils.closeQuietly(session);
2265        }
2266    }
2267
2268    private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
2269            boolean summary, int startProtectionLevel, int endProtectionLevel)
2270                    throws RemoteException {
2271        final PrintWriter pw = getOutPrintWriter();
2272        final int groupCount = groupList.size();
2273        for (int i = 0; i < groupCount; i++) {
2274            String groupName = groupList.get(i);
2275            String prefix = "";
2276            if (groups) {
2277                if (i > 0) {
2278                    pw.println("");
2279                }
2280                if (groupName != null) {
2281                    PermissionGroupInfo pgi =
2282                            mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
2283                    if (summary) {
2284                        Resources res = getResources(pgi);
2285                        if (res != null) {
2286                            pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
2287                        } else {
2288                            pw.print(pgi.name + ": ");
2289
2290                        }
2291                    } else {
2292                        pw.println((labels ? "+ " : "") + "group:" + pgi.name);
2293                        if (labels) {
2294                            pw.println("  package:" + pgi.packageName);
2295                            Resources res = getResources(pgi);
2296                            if (res != null) {
2297                                pw.println("  label:"
2298                                        + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
2299                                pw.println("  description:"
2300                                        + loadText(pgi, pgi.descriptionRes,
2301                                                pgi.nonLocalizedDescription));
2302                            }
2303                        }
2304                    }
2305                } else {
2306                    pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
2307                }
2308                prefix = "  ";
2309            }
2310            List<PermissionInfo> ps =
2311                    mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
2312            final int count = ps.size();
2313            boolean first = true;
2314            for (int p = 0 ; p < count ; p++) {
2315                PermissionInfo pi = ps.get(p);
2316                if (groups && groupName == null && pi.group != null) {
2317                    continue;
2318                }
2319                final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
2320                if (base < startProtectionLevel
2321                        || base > endProtectionLevel) {
2322                    continue;
2323                }
2324                if (summary) {
2325                    if (first) {
2326                        first = false;
2327                    } else {
2328                        pw.print(", ");
2329                    }
2330                    Resources res = getResources(pi);
2331                    if (res != null) {
2332                        pw.print(loadText(pi, pi.labelRes,
2333                                pi.nonLocalizedLabel));
2334                    } else {
2335                        pw.print(pi.name);
2336                    }
2337                } else {
2338                    pw.println(prefix + (labels ? "+ " : "")
2339                            + "permission:" + pi.name);
2340                    if (labels) {
2341                        pw.println(prefix + "  package:" + pi.packageName);
2342                        Resources res = getResources(pi);
2343                        if (res != null) {
2344                            pw.println(prefix + "  label:"
2345                                    + loadText(pi, pi.labelRes,
2346                                            pi.nonLocalizedLabel));
2347                            pw.println(prefix + "  description:"
2348                                    + loadText(pi, pi.descriptionRes,
2349                                            pi.nonLocalizedDescription));
2350                        }
2351                        pw.println(prefix + "  protectionLevel:"
2352                                + PermissionInfo.protectionToString(pi.protectionLevel));
2353                    }
2354                }
2355            }
2356
2357            if (summary) {
2358                pw.println("");
2359            }
2360        }
2361    }
2362
2363    private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
2364            throws RemoteException {
2365        if (nonLocalized != null) {
2366            return nonLocalized.toString();
2367        }
2368        if (res != 0) {
2369            Resources r = getResources(pii);
2370            if (r != null) {
2371                try {
2372                    return r.getString(res);
2373                } catch (Resources.NotFoundException e) {
2374                }
2375            }
2376        }
2377        return null;
2378    }
2379
2380    private Resources getResources(PackageItemInfo pii) throws RemoteException {
2381        Resources res = mResourceCache.get(pii.packageName);
2382        if (res != null) return res;
2383
2384        ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0);
2385        AssetManager am = new AssetManager();
2386        am.addAssetPath(ai.publicSourceDir);
2387        res = new Resources(am, null, null);
2388        mResourceCache.put(pii.packageName, res);
2389        return res;
2390    }
2391
2392    @Override
2393    public void onHelp() {
2394        final PrintWriter pw = getOutPrintWriter();
2395        pw.println("Package manager (package) commands:");
2396        pw.println("  help");
2397        pw.println("    Print this help text.");
2398        pw.println("");
2399        pw.println("  path [--user USER_ID] PACKAGE");
2400        pw.println("    Print the path to the .apk of the given PACKAGE.");
2401        pw.println("");
2402        pw.println("  dump PACKAGE");
2403        pw.println("    Print various system state associated with the given PACKAGE.");
2404        pw.println("");
2405        pw.println("  list features");
2406        pw.println("    Prints all features of the system.");
2407        pw.println("");
2408        pw.println("  has-feature FEATURE_NAME [version]");
2409        pw.println("    Prints true and returns exit status 0 when system has a FEATURE_NAME,");
2410        pw.println("    otherwise prints false and returns exit status 1");
2411        pw.println("");
2412        pw.println("  list instrumentation [-f] [TARGET-PACKAGE]");
2413        pw.println("    Prints all test packages; optionally only those targeting TARGET-PACKAGE");
2414        pw.println("    Options:");
2415        pw.println("      -f: dump the name of the .apk file containing the test package");
2416        pw.println("");
2417        pw.println("  list libraries");
2418        pw.println("    Prints all system libraries.");
2419        pw.println("");
2420        pw.println("  list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
2421        pw.println("      [--uid UID] [--user USER_ID] [FILTER]");
2422        pw.println("    Prints all packages; optionally only those whose name contains");
2423        pw.println("    the text in FILTER.  Options are:");
2424        pw.println("      -f: see their associated file");
2425        pw.println("      -d: filter to only show disabled packages");
2426        pw.println("      -e: filter to only show enabled packages");
2427        pw.println("      -s: filter to only show system packages");
2428        pw.println("      -3: filter to only show third party packages");
2429        pw.println("      -i: see the installer for the packages");
2430        pw.println("      -l: ignored (used for compatibility with older releases)");
2431        pw.println("      -U: also show the package UID");
2432        pw.println("      -u: also include uninstalled packages");
2433        pw.println("      --uid UID: filter to only show packages with the given UID");
2434        pw.println("      --user USER_ID: only list packages belonging to the given user");
2435        pw.println("");
2436        pw.println("  list permission-groups");
2437        pw.println("    Prints all known permission groups.");
2438        pw.println("");
2439        pw.println("  list permissions [-g] [-f] [-d] [-u] [GROUP]");
2440        pw.println("    Prints all known permissions; optionally only those in GROUP.  Options are:");
2441        pw.println("      -g: organize by group");
2442        pw.println("      -f: print all information");
2443        pw.println("      -s: short summary");
2444        pw.println("      -d: only list dangerous permissions");
2445        pw.println("      -u: list only the permissions users will see");
2446        pw.println("");
2447        pw.println("  resolve-activity [--brief] [--components] [--user USER_ID] INTENT");
2448        pw.println("    Prints the activity that resolves to the given INTENT.");
2449        pw.println("");
2450        pw.println("  query-activities [--brief] [--components] [--user USER_ID] INTENT");
2451        pw.println("    Prints all activities that can handle the given INTENT.");
2452        pw.println("");
2453        pw.println("  query-services [--brief] [--components] [--user USER_ID] INTENT");
2454        pw.println("    Prints all services that can handle the given INTENT.");
2455        pw.println("");
2456        pw.println("  query-receivers [--brief] [--components] [--user USER_ID] INTENT");
2457        pw.println("    Prints all broadcast receivers that can handle the given INTENT.");
2458        pw.println("");
2459        pw.println("  install [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
2460        pw.println("       [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
2461        pw.println("       [--originating-uri URI] [---referrer URI]");
2462        pw.println("       [--abi ABI_NAME] [--force-sdk]");
2463        pw.println("       [--preload] [--instantapp] [--full] [--dont-kill]");
2464        pw.println("       [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES] [PATH|-]");
2465        pw.println("    Install an application.  Must provide the apk data to install, either as a");
2466        pw.println("    file path or '-' to read from stdin.  Options are:");
2467        pw.println("      -l: forward lock application");
2468        pw.println("      -R: disallow replacement of existing application");
2469        pw.println("      -t: allow test packages");
2470        pw.println("      -i: specify package name of installer owning the app");
2471        pw.println("      -s: install application on sdcard");
2472        pw.println("      -f: install application on internal flash");
2473        pw.println("      -d: allow version code downgrade (debuggable packages only)");
2474        pw.println("      -p: partial application install (new split on top of existing pkg)");
2475        pw.println("      -g: grant all runtime permissions");
2476        pw.println("      -S: size in bytes of package, required for stdin");
2477        pw.println("      --user: install under the given user.");
2478        pw.println("      --dont-kill: installing a new feature split, don't kill running app");
2479        pw.println("      --originating-uri: set URI where app was downloaded from");
2480        pw.println("      --referrer: set URI that instigated the install of the app");
2481        pw.println("      --pkg: specify expected package name of app being installed");
2482        pw.println("      --abi: override the default ABI of the platform");
2483        pw.println("      --instantapp: cause the app to be installed as an ephemeral install app");
2484        pw.println("      --full: cause the app to be installed as a non-ephemeral full app");
2485        pw.println("      --install-location: force the install location:");
2486        pw.println("          0=auto, 1=internal only, 2=prefer external");
2487        pw.println("      --force-uuid: force install on to disk volume with given UUID");
2488        pw.println("      --force-sdk: allow install even when existing app targets platform");
2489        pw.println("          codename but new one targets a final API level");
2490        pw.println("");
2491        pw.println("  install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
2492        pw.println("       [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
2493        pw.println("       [--originating-uri URI] [---referrer URI]");
2494        pw.println("       [--abi ABI_NAME] [--force-sdk]");
2495        pw.println("       [--preload] [--instantapp] [--full] [--dont-kill]");
2496        pw.println("       [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
2497        pw.println("    Like \"install\", but starts an install session.  Use \"install-write\"");
2498        pw.println("    to push data into the session, and \"install-commit\" to finish.");
2499        pw.println("");
2500        pw.println("  install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]");
2501        pw.println("    Write an apk into the given install session.  If the path is '-', data");
2502        pw.println("    will be read from stdin.  Options are:");
2503        pw.println("      -S: size in bytes of package, required for stdin");
2504        pw.println("");
2505        pw.println("  install-commit SESSION_ID");
2506        pw.println("    Commit the given active install session, installing the app.");
2507        pw.println("");
2508        pw.println("  install-abandon SESSION_ID");
2509        pw.println("    Delete the given active install session.");
2510        pw.println("");
2511        pw.println("  set-install-location LOCATION");
2512        pw.println("    Changes the default install location.  NOTE this is only intended for debugging;");
2513        pw.println("    using this can cause applications to break and other undersireable behavior.");
2514        pw.println("    LOCATION is one of:");
2515        pw.println("    0 [auto]: Let system decide the best location");
2516        pw.println("    1 [internal]: Install on internal device storage");
2517        pw.println("    2 [external]: Install on external media");
2518        pw.println("");
2519        pw.println("  get-install-location");
2520        pw.println("    Returns the current install location: 0, 1 or 2 as per set-install-location.");
2521        pw.println("");
2522        pw.println("  move-package PACKAGE [internal|UUID]");
2523        pw.println("");
2524        pw.println("  move-primary-storage [internal|UUID]");
2525        pw.println("");
2526        pw.println("  pm uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE] PACKAGE [SPLIT]");
2527        pw.println("    Remove the given package name from the system.  May remove an entire app");
2528        pw.println("    if no SPLIT name is specified, otherwise will remove only the split of the");
2529        pw.println("    given app.  Options are:");
2530        pw.println("      -k: keep the data and cache directories around after package removal.");
2531        pw.println("      --user: remove the app from the given user.");
2532        pw.println("      --versionCode: only uninstall if the app has the given version code.");
2533        pw.println("");
2534        pw.println("  clear [--user USER_ID] PACKAGE");
2535        pw.println("    Deletes all data associated with a package.");
2536        pw.println("");
2537        pw.println("  enable [--user USER_ID] PACKAGE_OR_COMPONENT");
2538        pw.println("  disable [--user USER_ID] PACKAGE_OR_COMPONENT");
2539        pw.println("  disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
2540        pw.println("  disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
2541        pw.println("  default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
2542        pw.println("    These commands change the enabled state of a given package or");
2543        pw.println("    component (written as \"package/class\").");
2544        pw.println("");
2545        pw.println("  hide [--user USER_ID] PACKAGE_OR_COMPONENT");
2546        pw.println("  unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
2547        pw.println("");
2548        pw.println("  suspend [--user USER_ID] TARGET-PACKAGE");
2549        pw.println("    Suspends the specified package (as user).");
2550        pw.println("");
2551        pw.println("  unsuspend [--user USER_ID] TARGET-PACKAGE");
2552        pw.println("    Unsuspends the specified package (as user).");
2553        pw.println("");
2554        pw.println("  grant [--user USER_ID] PACKAGE PERMISSION");
2555        pw.println("  revoke [--user USER_ID] PACKAGE PERMISSION");
2556        pw.println("    These commands either grant or revoke permissions to apps.  The permissions");
2557        pw.println("    must be declared as used in the app's manifest, be runtime permissions");
2558        pw.println("    (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
2559        pw.println("");
2560        pw.println("  reset-permissions");
2561        pw.println("    Revert all runtime permissions to their default state.");
2562        pw.println("");
2563        pw.println("  set-permission-enforced PERMISSION [true|false]");
2564        pw.println("");
2565        pw.println("  get-privapp-permissions TARGET-PACKAGE");
2566        pw.println("    Prints all privileged permissions for a package.");
2567        pw.println("");
2568        pw.println("  get-privapp-deny-permissions TARGET-PACKAGE");
2569        pw.println("    Prints all privileged permissions that are denied for a package.");
2570        pw.println("");
2571        pw.println("  get-oem-permissions TARGET-PACKAGE");
2572        pw.println("    Prints all OEM permissions for a package.");
2573        pw.println("");
2574        pw.println("  set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
2575        pw.println("  get-app-link [--user USER_ID] PACKAGE");
2576        pw.println("");
2577        pw.println("  trim-caches DESIRED_FREE_SPACE [internal|UUID]");
2578        pw.println("    Trim cache files to reach the given free space.");
2579        pw.println("");
2580        pw.println("  create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
2581        pw.println("      [--guest] USER_NAME");
2582        pw.println("    Create a new user with the given USER_NAME, printing the new user identifier");
2583        pw.println("    of the user.");
2584        pw.println("");
2585        pw.println("  remove-user USER_ID");
2586        pw.println("    Remove the user with the given USER_IDENTIFIER, deleting all data");
2587        pw.println("    associated with that user");
2588        pw.println("");
2589        pw.println("  set-user-restriction [--user USER_ID] RESTRICTION VALUE");
2590        pw.println("");
2591        pw.println("  get-max-users");
2592        pw.println("");
2593        pw.println("  compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
2594        pw.println("          [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
2595        pw.println("    Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".  Options are:");
2596        pw.println("      -a: compile all packages");
2597        pw.println("      -c: clear profile data before compiling");
2598        pw.println("      -f: force compilation even if not needed");
2599        pw.println("      -m: select compilation mode");
2600        pw.println("          MODE is one of the dex2oat compiler filters:");
2601        pw.println("            assume-verified");
2602        pw.println("            extract");
2603        pw.println("            verify");
2604        pw.println("            quicken");
2605        pw.println("            space-profile");
2606        pw.println("            space");
2607        pw.println("            speed-profile");
2608        pw.println("            speed");
2609        pw.println("            everything");
2610        pw.println("      -r: select compilation reason");
2611        pw.println("          REASON is one of:");
2612        for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
2613            pw.println("            " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
2614        }
2615        pw.println("      --reset: restore package to its post-install state");
2616        pw.println("      --check-prof (true | false): look at profiles when doing dexopt?");
2617        pw.println("      --secondary-dex: compile app secondary dex files");
2618        pw.println("      --split SPLIT: compile only the given split name");
2619        pw.println("");
2620        pw.println("  force-dex-opt PACKAGE");
2621        pw.println("    Force immediate execution of dex opt for the given PACKAGE.");
2622        pw.println("");
2623        pw.println("  bg-dexopt-job");
2624        pw.println("    Execute the background optimizations immediately.");
2625        pw.println("    Note that the command only runs the background optimizer logic. It may");
2626        pw.println("    overlap with the actual job but the job scheduler will not be able to");
2627        pw.println("    cancel it. It will also run even if the device is not in the idle");
2628        pw.println("    maintenance mode.");
2629        pw.println("");
2630        pw.println("  reconcile-secondary-dex-files TARGET-PACKAGE");
2631        pw.println("    Reconciles the package secondary dex files with the generated oat files.");
2632        pw.println("");
2633        pw.println("  dump-profiles TARGET-PACKAGE");
2634        pw.println("    Dumps method/class profile files to");
2635        pw.println("    /data/misc/profman/TARGET-PACKAGE.txt");
2636        pw.println("");
2637        pw.println("  set-home-activity [--user USER_ID] TARGET-COMPONENT");
2638        pw.println("    Set the default home activity (aka launcher).");
2639        pw.println("");
2640        pw.println("  set-installer PACKAGE INSTALLER");
2641        pw.println("    Set installer package name");
2642        pw.println("");
2643        pw.println("  get-instantapp-resolver");
2644        pw.println("    Return the name of the component that is the current instant app installer.");
2645        pw.println();
2646        Intent.printIntentArgsHelp(pw , "");
2647    }
2648
2649    private static class LocalIntentReceiver {
2650        private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
2651
2652        private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
2653            @Override
2654            public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
2655                    IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
2656                try {
2657                    mResult.offer(intent, 5, TimeUnit.SECONDS);
2658                } catch (InterruptedException e) {
2659                    throw new RuntimeException(e);
2660                }
2661            }
2662        };
2663
2664        public IntentSender getIntentSender() {
2665            return new IntentSender((IIntentSender) mLocalSender);
2666        }
2667
2668        public Intent getResult() {
2669            try {
2670                return mResult.take();
2671            } catch (InterruptedException e) {
2672                throw new RuntimeException(e);
2673            }
2674        }
2675    }
2676}
2677