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