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