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