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