• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.PackageInstaller.LOCATION_DATA_APP;
20 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
21 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
22 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
23 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
24 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
25 
26 import android.accounts.IAccountManager;
27 import android.annotation.NonNull;
28 import android.annotation.UserIdInt;
29 import android.app.ActivityManager;
30 import android.app.ActivityManagerInternal;
31 import android.app.role.RoleManager;
32 import android.content.ComponentName;
33 import android.content.Context;
34 import android.content.IIntentReceiver;
35 import android.content.IIntentSender;
36 import android.content.Intent;
37 import android.content.IntentSender;
38 import android.content.pm.ApplicationInfo;
39 import android.content.pm.FeatureInfo;
40 import android.content.pm.IPackageDataObserver;
41 import android.content.pm.IPackageInstaller;
42 import android.content.pm.IPackageManager;
43 import android.content.pm.InstrumentationInfo;
44 import android.content.pm.ModuleInfo;
45 import android.content.pm.PackageInfo;
46 import android.content.pm.PackageInstaller;
47 import android.content.pm.PackageInstaller.SessionInfo;
48 import android.content.pm.PackageInstaller.SessionParams;
49 import android.content.pm.PackageItemInfo;
50 import android.content.pm.PackageManager;
51 import android.content.pm.PackageManager.NameNotFoundException;
52 import android.content.pm.PackageManagerInternal;
53 import android.content.pm.ParceledListSlice;
54 import android.content.pm.PermissionGroupInfo;
55 import android.content.pm.PermissionInfo;
56 import android.content.pm.ResolveInfo;
57 import android.content.pm.SharedLibraryInfo;
58 import android.content.pm.SuspendDialogInfo;
59 import android.content.pm.UserInfo;
60 import android.content.pm.VersionedPackage;
61 import android.content.pm.dex.ArtManager;
62 import android.content.pm.dex.DexMetadataHelper;
63 import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
64 import android.content.pm.parsing.ApkLite;
65 import android.content.pm.parsing.ApkLiteParseUtils;
66 import android.content.pm.parsing.PackageLite;
67 import android.content.pm.parsing.result.ParseResult;
68 import android.content.pm.parsing.result.ParseTypeImpl;
69 import android.content.res.AssetManager;
70 import android.content.res.Resources;
71 import android.content.rollback.PackageRollbackInfo;
72 import android.content.rollback.RollbackInfo;
73 import android.content.rollback.RollbackManager;
74 import android.net.Uri;
75 import android.os.Binder;
76 import android.os.Build;
77 import android.os.Bundle;
78 import android.os.IBinder;
79 import android.os.IUserManager;
80 import android.os.ParcelFileDescriptor;
81 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
82 import android.os.PersistableBundle;
83 import android.os.Process;
84 import android.os.RemoteException;
85 import android.os.ServiceManager;
86 import android.os.ServiceSpecificException;
87 import android.os.ShellCommand;
88 import android.os.SystemClock;
89 import android.os.SystemProperties;
90 import android.os.Trace;
91 import android.os.UserHandle;
92 import android.os.UserManager;
93 import android.os.incremental.V4Signature;
94 import android.os.storage.StorageManager;
95 import android.permission.PermissionManager;
96 import android.system.ErrnoException;
97 import android.system.Os;
98 import android.text.TextUtils;
99 import android.text.format.DateUtils;
100 import android.util.ArrayMap;
101 import android.util.ArraySet;
102 import android.util.IntArray;
103 import android.util.PrintWriterPrinter;
104 import android.util.Slog;
105 import android.util.SparseArray;
106 
107 import com.android.internal.content.InstallLocationUtils;
108 import com.android.internal.util.ArrayUtils;
109 import com.android.internal.util.IndentingPrintWriter;
110 import com.android.internal.util.Preconditions;
111 import com.android.server.FgThread;
112 import com.android.server.LocalServices;
113 import com.android.server.SystemConfig;
114 import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata;
115 import com.android.server.pm.permission.LegacyPermissionManagerInternal;
116 import com.android.server.pm.verify.domain.DomainVerificationShell;
117 
118 import dalvik.system.DexFile;
119 
120 import libcore.io.IoUtils;
121 import libcore.io.Streams;
122 
123 import java.io.File;
124 import java.io.FileOutputStream;
125 import java.io.IOException;
126 import java.io.InputStream;
127 import java.io.OutputStream;
128 import java.io.PrintWriter;
129 import java.net.URISyntaxException;
130 import java.security.SecureRandom;
131 import java.util.ArrayList;
132 import java.util.Arrays;
133 import java.util.Base64;
134 import java.util.Collection;
135 import java.util.Collections;
136 import java.util.Comparator;
137 import java.util.HashMap;
138 import java.util.List;
139 import java.util.Map;
140 import java.util.Objects;
141 import java.util.Set;
142 import java.util.WeakHashMap;
143 import java.util.concurrent.CompletableFuture;
144 import java.util.concurrent.CountDownLatch;
145 import java.util.concurrent.LinkedBlockingQueue;
146 import java.util.concurrent.TimeUnit;
147 
148 class PackageManagerShellCommand extends ShellCommand {
149     /** Path for streaming APK content */
150     private static final String STDIN_PATH = "-";
151     /** Path where ART profiles snapshots are dumped for the shell user */
152     private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
153     private static final int DEFAULT_STAGED_READY_TIMEOUT_MS = 60 * 1000;
154     private static final String TAG = "PackageManagerShellCommand";
155     private static final Set<String> UNSUPPORTED_INSTALL_CMD_OPTS = Set.of(
156             "--multi-package"
157     );
158     private static final Set<String> UNSUPPORTED_SESSION_CREATE_OPTS = Collections.emptySet();
159     private static final Map<String, Integer> SUPPORTED_PERMISSION_FLAGS = new ArrayMap<>();
160     private static final List<String> SUPPORTED_PERMISSION_FLAGS_LIST;
161     static {
162         SUPPORTED_PERMISSION_FLAGS_LIST = List.of("review-required", "revoked-compat",
163                 "revoke-when-requested", "user-fixed", "user-set");
164         SUPPORTED_PERMISSION_FLAGS.put("user-set", FLAG_PERMISSION_USER_SET);
165         SUPPORTED_PERMISSION_FLAGS.put("user-fixed", FLAG_PERMISSION_USER_FIXED);
166         SUPPORTED_PERMISSION_FLAGS.put("revoked-compat", FLAG_PERMISSION_REVOKED_COMPAT);
167         SUPPORTED_PERMISSION_FLAGS.put("review-required", FLAG_PERMISSION_REVIEW_REQUIRED);
168         SUPPORTED_PERMISSION_FLAGS.put("revoke-when-requested",
169                 FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
170     }
171 
172     final IPackageManager mInterface;
173     final LegacyPermissionManagerInternal mLegacyPermissionManager;
174     final PermissionManager mPermissionManager;
175     final Context mContext;
176     final DomainVerificationShell mDomainVerificationShell;
177     final private WeakHashMap<String, Resources> mResourceCache =
178             new WeakHashMap<String, Resources>();
179     int mTargetUser;
180     boolean mBrief;
181     boolean mComponents;
182     int mQueryFlags;
183 
184     private static final SecureRandom RANDOM = new SecureRandom();
185 
PackageManagerShellCommand(@onNull IPackageManager packageManager, @NonNull Context context, @NonNull DomainVerificationShell domainVerificationShell)186     PackageManagerShellCommand(@NonNull IPackageManager packageManager,
187             @NonNull Context context, @NonNull DomainVerificationShell domainVerificationShell) {
188         mInterface = packageManager;
189         mLegacyPermissionManager = LocalServices.getService(LegacyPermissionManagerInternal.class);
190         mPermissionManager = context.getSystemService(PermissionManager.class);
191         mContext = context;
192         mDomainVerificationShell = domainVerificationShell;
193     }
194 
195     @Override
onCommand(String cmd)196     public int onCommand(String cmd) {
197         if (cmd == null) {
198             return handleDefaultCommands(cmd);
199         }
200 
201         final PrintWriter pw = getOutPrintWriter();
202         try {
203             switch (cmd) {
204                 case "path":
205                     return runPath();
206                 case "dump":
207                     return runDump();
208                 case "list":
209                     return runList();
210                 case "gc":
211                     return runGc();
212                 case "resolve-activity":
213                     return runResolveActivity();
214                 case "query-activities":
215                     return runQueryIntentActivities();
216                 case "query-services":
217                     return runQueryIntentServices();
218                 case "query-receivers":
219                     return runQueryIntentReceivers();
220                 case "install":
221                     return runInstall();
222                 case "install-streaming":
223                     return runStreamingInstall();
224                 case "install-incremental":
225                     return runIncrementalInstall();
226                 case "install-abandon":
227                 case "install-destroy":
228                     return runInstallAbandon();
229                 case "install-commit":
230                     return runInstallCommit();
231                 case "install-create":
232                     return runInstallCreate();
233                 case "install-remove":
234                     return runInstallRemove();
235                 case "install-write":
236                     return runInstallWrite();
237                 case "install-existing":
238                     return runInstallExisting();
239                 case "set-install-location":
240                     return runSetInstallLocation();
241                 case "get-install-location":
242                     return runGetInstallLocation();
243                 case "install-add-session":
244                     return runInstallAddSession();
245                 case "move-package":
246                     return runMovePackage();
247                 case "move-primary-storage":
248                     return runMovePrimaryStorage();
249                 case "compile":
250                     return runCompile();
251                 case "reconcile-secondary-dex-files":
252                     return runreconcileSecondaryDexFiles();
253                 case "force-dex-opt":
254                     return runForceDexOpt();
255                 case "bg-dexopt-job":
256                     return runDexoptJob();
257                 case "cancel-bg-dexopt-job":
258                     return cancelBgDexOptJob();
259                 case "delete-dexopt":
260                     return runDeleteDexOpt();
261                 case "dump-profiles":
262                     return runDumpProfiles();
263                 case "snapshot-profile":
264                     return runSnapshotProfile();
265                 case "uninstall":
266                     return runUninstall();
267                 case "clear":
268                     return runClear();
269                 case "enable":
270                     return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
271                 case "disable":
272                     return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
273                 case "disable-user":
274                     return runSetEnabledSetting(
275                             PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
276                 case "disable-until-used":
277                     return runSetEnabledSetting(
278                             PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
279                 case "default-state":
280                     return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
281                 case "hide":
282                     return runSetHiddenSetting(true);
283                 case "unhide":
284                     return runSetHiddenSetting(false);
285                 case "suspend":
286                     return runSuspend(true);
287                 case "unsuspend":
288                     return runSuspend(false);
289                 case "set-distracting-restriction":
290                     return runSetDistractingRestriction();
291                 case "grant":
292                     return runGrantRevokePermission(true);
293                 case "revoke":
294                     return runGrantRevokePermission(false);
295                 case "reset-permissions":
296                     return runResetPermissions();
297                 case "set-permission-flags":
298                     return setOrClearPermissionFlags(true);
299                 case "clear-permission-flags":
300                     return setOrClearPermissionFlags(false);
301                 case "set-permission-enforced":
302                     return runSetPermissionEnforced();
303                 case "get-privapp-permissions":
304                     return runGetPrivappPermissions();
305                 case "get-privapp-deny-permissions":
306                     return runGetPrivappDenyPermissions();
307                 case "get-oem-permissions":
308                     return runGetOemPermissions();
309                 case "trim-caches":
310                     return runTrimCaches();
311                 case "create-user":
312                     return runCreateUser();
313                 case "remove-user":
314                     return runRemoveUser();
315                 case "set-user-restriction":
316                     return runSetUserRestriction();
317                 case "get-max-users":
318                     return runGetMaxUsers();
319                 case "get-max-running-users":
320                     return runGetMaxRunningUsers();
321                 case "set-home-activity":
322                     return runSetHomeActivity();
323                 case "set-installer":
324                     return runSetInstaller();
325                 case "get-instantapp-resolver":
326                     return runGetInstantAppResolver();
327                 case "has-feature":
328                     return runHasFeature();
329                 case "set-harmful-app-warning":
330                     return runSetHarmfulAppWarning();
331                 case "get-harmful-app-warning":
332                     return runGetHarmfulAppWarning();
333                 case "get-stagedsessions":
334                     return runListStagedSessions();
335                 case "uninstall-system-updates":
336                     String packageName = getNextArg();
337                     return uninstallSystemUpdates(packageName);
338                 case "rollback-app":
339                     return runRollbackApp();
340                 case "get-moduleinfo":
341                     return runGetModuleInfo();
342                 case "log-visibility":
343                     return runLogVisibility();
344                 case "bypass-staged-installer-check":
345                     return runBypassStagedInstallerCheck();
346                 case "bypass-allowed-apex-update-check":
347                     return runBypassAllowedApexUpdateCheck();
348                 case "set-silent-updates-policy":
349                     return runSetSilentUpdatesPolicy();
350                 default: {
351                     Boolean domainVerificationResult =
352                             mDomainVerificationShell.runCommand(this, cmd);
353                     if (domainVerificationResult != null) {
354                         return domainVerificationResult ? 0 : 1;
355                     }
356 
357                     String nextArg = getNextArg();
358                     if (nextArg == null) {
359                         if (cmd.equalsIgnoreCase("-l")) {
360                             return runListPackages(false);
361                         } else if (cmd.equalsIgnoreCase("-lf")) {
362                             return runListPackages(true);
363                         }
364                     } else if (getNextArg() == null) {
365                         if (cmd.equalsIgnoreCase("-p")) {
366                             return displayPackageFilePath(nextArg, UserHandle.USER_SYSTEM);
367                         }
368                     }
369                     return handleDefaultCommands(cmd);
370                 }
371             }
372         } catch (RemoteException e) {
373             pw.println("Remote exception: " + e);
374         }
375         return -1;
376     }
377 
378     /**
379      * Shows module info
380      *
381      * Usage: get-moduleinfo [--all | --installed] [module-name]
382      * Example: get-moduleinfo, get-moduleinfo --all, get-moduleinfo xyz
383      */
runGetModuleInfo()384     private int runGetModuleInfo() {
385         final PrintWriter pw = getOutPrintWriter();
386         int flags = 0;
387 
388         String opt;
389         while ((opt = getNextOption()) != null) {
390             switch (opt) {
391                 case "--all":
392                     flags |= PackageManager.MATCH_ALL;
393                     break;
394                 case "--installed":
395                     break;
396                 default:
397                     pw.println("Error: Unknown option: " + opt);
398                     return -1;
399             }
400         }
401 
402         String moduleName = getNextArg();
403         try {
404             if (moduleName != null) {
405                 ModuleInfo m = mInterface.getModuleInfo(moduleName, flags);
406                 pw.println(m.toString() + " packageName: " + m.getPackageName());
407 
408             } else {
409                 List<ModuleInfo> modules = mInterface.getInstalledModules(flags);
410                 for (ModuleInfo m: modules) {
411                     pw.println(m.toString() + " packageName: " + m.getPackageName());
412                 }
413             }
414         } catch (RemoteException e) {
415             pw.println("Failure [" + e.getClass().getName() + " - " + e.getMessage() + "]");
416             return -1;
417         }
418         return 1;
419     }
420 
runLogVisibility()421     private int runLogVisibility() {
422         final PrintWriter pw = getOutPrintWriter();
423         boolean enable = true;
424 
425         String opt;
426         while ((opt = getNextOption()) != null) {
427             switch (opt) {
428                 case "--disable":
429                     enable = false;
430                     break;
431                 case "--enable":
432                     enable = true;
433                     break;
434                 default:
435                     pw.println("Error: Unknown option: " + opt);
436                     return -1;
437             }
438         }
439 
440         String packageName = getNextArg();
441         if (packageName != null) {
442             LocalServices.getService(PackageManagerInternal.class)
443                     .setVisibilityLogging(packageName, enable);
444         } else {
445             getErrPrintWriter().println("Error: no package specified");
446             return -1;
447         }
448         return 1;
449     }
450 
runBypassStagedInstallerCheck()451     private int runBypassStagedInstallerCheck() {
452         final PrintWriter pw = getOutPrintWriter();
453         try {
454             mInterface.getPackageInstaller()
455                     .bypassNextStagedInstallerCheck(Boolean.parseBoolean(getNextArg()));
456             return 0;
457         } catch (RemoteException e) {
458             pw.println("Failure ["
459                     + e.getClass().getName() + " - "
460                     + e.getMessage() + "]");
461             return -1;
462         }
463     }
464 
runBypassAllowedApexUpdateCheck()465     private int runBypassAllowedApexUpdateCheck() {
466         final PrintWriter pw = getOutPrintWriter();
467         try {
468             mInterface.getPackageInstaller()
469                     .bypassNextAllowedApexUpdateCheck(Boolean.parseBoolean(getNextArg()));
470             return 0;
471         } catch (RemoteException e) {
472             pw.println("Failure ["
473                     + e.getClass().getName() + " - "
474                     + e.getMessage() + "]");
475             return -1;
476         }
477     }
478 
uninstallSystemUpdates(String packageName)479     private int uninstallSystemUpdates(String packageName) {
480         final PrintWriter pw = getOutPrintWriter();
481         boolean failedUninstalls = false;
482         try {
483             final IPackageInstaller installer = mInterface.getPackageInstaller();
484             final List<ApplicationInfo> list;
485             if (packageName == null) {
486                 final ParceledListSlice<ApplicationInfo> packages =
487                         mInterface.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY
488                                         | PackageManager.MATCH_UNINSTALLED_PACKAGES,
489                                 UserHandle.USER_SYSTEM);
490                 list = packages.getList();
491             } else {
492                 list = new ArrayList<>(1);
493                 list.add(mInterface.getApplicationInfo(packageName, PackageManager.MATCH_SYSTEM_ONLY
494                                 | PackageManager.MATCH_UNINSTALLED_PACKAGES,
495                         UserHandle.USER_SYSTEM));
496             }
497             for (ApplicationInfo info : list) {
498                 if (info.isUpdatedSystemApp()) {
499                     pw.println("Uninstalling updates to " + info.packageName + "...");
500                     final LocalIntentReceiver receiver = new LocalIntentReceiver();
501                     installer.uninstall(new VersionedPackage(info.packageName,
502                                     info.versionCode), null /*callerPackageName*/, 0 /* flags */,
503                             receiver.getIntentSender(), 0);
504 
505                     final Intent result = receiver.getResult();
506                     final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
507                             PackageInstaller.STATUS_FAILURE);
508                     if (status != PackageInstaller.STATUS_SUCCESS) {
509                         failedUninstalls = true;
510                         pw.println("Couldn't uninstall package: " + info.packageName);
511                     }
512                 }
513             }
514         } catch (RemoteException e) {
515             pw.println("Failure ["
516                     + e.getClass().getName() + " - "
517                     + e.getMessage() + "]");
518             return 0;
519         }
520         if (failedUninstalls) {
521             return 0;
522         }
523         pw.println("Success");
524         return 1;
525     }
526 
runRollbackApp()527     private int runRollbackApp() throws RemoteException {
528         final PrintWriter pw = getOutPrintWriter();
529 
530         String opt;
531         long stagedReadyTimeoutMs = DEFAULT_STAGED_READY_TIMEOUT_MS;
532         while ((opt = getNextOption()) != null) {
533             switch (opt) {
534                 case "--staged-ready-timeout":
535                     stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired());
536                     break;
537                 default:
538                     throw new IllegalArgumentException("Unknown option: " + opt);
539             }
540         }
541         final String packageName = getNextArgRequired();
542         if (packageName == null) {
543             pw.println("Error: package name not specified");
544             return 1;
545         }
546 
547         final Context shellPackageContext;
548         try {
549             shellPackageContext = mContext.createPackageContextAsUser(
550                     "com.android.shell", 0, Binder.getCallingUserHandle());
551         } catch (NameNotFoundException e) {
552             // should not happen
553             throw new RuntimeException(e);
554         }
555 
556         final LocalIntentReceiver receiver = new LocalIntentReceiver();
557         RollbackManager rm = shellPackageContext.getSystemService(RollbackManager.class);
558         RollbackInfo rollback = null;
559         for (RollbackInfo r : rm.getAvailableRollbacks()) {
560             for (PackageRollbackInfo info : r.getPackages()) {
561                 if (packageName.equals(info.getPackageName())) {
562                     rollback = r;
563                     break;
564                 }
565             }
566         }
567 
568         if (rollback == null) {
569             pw.println("No available rollbacks for: " + packageName);
570             return 1;
571         }
572 
573         rm.commitRollback(rollback.getRollbackId(),
574                 Collections.emptyList(), receiver.getIntentSender());
575 
576         final Intent result = receiver.getResult();
577         final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
578                 RollbackManager.STATUS_FAILURE);
579 
580         if (status != RollbackManager.STATUS_SUCCESS) {
581             pw.println("Failure ["
582                     + result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE) + "]");
583             return 1;
584         }
585 
586         if (rollback.isStaged() && stagedReadyTimeoutMs > 0) {
587             final int committedSessionId = rollback.getCommittedSessionId();
588             return doWaitForStagedSessionReady(committedSessionId, stagedReadyTimeoutMs, pw);
589         }
590 
591         pw.println("Success");
592         return 0;
593 
594     }
595 
setParamsSize(InstallParams params, List<String> inPaths)596     private void setParamsSize(InstallParams params, List<String> inPaths) {
597         if (params.sessionParams.sizeBytes != -1 || STDIN_PATH.equals(inPaths.get(0))) {
598             return;
599         }
600 
601         long sessionSize = 0;
602 
603         ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
604         for (String inPath : inPaths) {
605             final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");
606             if (fd == null) {
607                 getErrPrintWriter().println("Error: Can't open file: " + inPath);
608                 throw new IllegalArgumentException("Error: Can't open file: " + inPath);
609             }
610             try {
611                 ParseResult<ApkLite> apkLiteResult = ApkLiteParseUtils.parseApkLite(
612                         input.reset(), fd.getFileDescriptor(), inPath, 0);
613                 if (apkLiteResult.isError()) {
614                     throw new IllegalArgumentException(
615                             "Error: Failed to parse APK file: " + inPath + ": "
616                                     + apkLiteResult.getErrorMessage(),
617                             apkLiteResult.getException());
618                 }
619                 final ApkLite apkLite = apkLiteResult.getResult();
620                 final PackageLite pkgLite = new PackageLite(null, apkLite.getPath(), apkLite,
621                         null /* splitNames */, null /* isFeatureSplits */,
622                         null /* usesSplitNames */, null /* configForSplit */,
623                         null /* splitApkPaths */, null /* splitRevisionCodes */,
624                         apkLite.getTargetSdkVersion(), null /* requiredSplitTypes */,
625                         null /* splitTypes */);
626                 sessionSize += InstallLocationUtils.calculateInstalledSize(pkgLite,
627                         params.sessionParams.abiOverride, fd.getFileDescriptor());
628             } catch (IOException e) {
629                 getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath);
630                 throw new IllegalArgumentException(
631                         "Error: Failed to parse APK file: " + inPath, e);
632             } finally {
633                 try {
634                     fd.close();
635                 } catch (IOException e) {
636                 }
637             }
638         }
639 
640         params.sessionParams.setSize(sessionSize);
641     }
642     /**
643      * Displays the package file for a package.
644      * @param pckg
645      */
displayPackageFilePath(String pckg, int userId)646     private int displayPackageFilePath(String pckg, int userId) throws RemoteException {
647         PackageInfo info = mInterface.getPackageInfo(pckg, PackageManager.MATCH_APEX, userId);
648         if (info != null && info.applicationInfo != null) {
649             final PrintWriter pw = getOutPrintWriter();
650             pw.print("package:");
651             pw.println(info.applicationInfo.sourceDir);
652             if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
653                 for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
654                     pw.print("package:");
655                     pw.println(splitSourceDir);
656                 }
657             }
658             return 0;
659         }
660         return 1;
661     }
662 
runPath()663     private int runPath() throws RemoteException {
664         int userId = UserHandle.USER_SYSTEM;
665         String option = getNextOption();
666         if (option != null && option.equals("--user")) {
667             userId = UserHandle.parseUserArg(getNextArgRequired());
668         }
669 
670         String pkg = getNextArgRequired();
671         if (pkg == null) {
672             getErrPrintWriter().println("Error: no package specified");
673             return 1;
674         }
675         final int translatedUserId =
676                 translateUserId(userId, UserHandle.USER_NULL, "runPath");
677         return displayPackageFilePath(pkg, translatedUserId);
678     }
679 
runList()680     private int runList() throws RemoteException {
681         final PrintWriter pw = getOutPrintWriter();
682         final String type = getNextArg();
683         if (type == null) {
684             pw.println("Error: didn't specify type of data to list");
685             return -1;
686         }
687         switch(type) {
688             case "features":
689                 return runListFeatures();
690             case "instrumentation":
691                 return runListInstrumentation();
692             case "libraries":
693                 return runListLibraries();
694             case "package":
695             case "packages":
696                 return runListPackages(false /*showSourceDir*/);
697             case "permission-groups":
698                 return runListPermissionGroups();
699             case "permissions":
700                 return runListPermissions();
701             case "staged-sessions":
702                 return runListStagedSessions();
703             case "sdks":
704                 return runListSdks();
705             case "users":
706                 ServiceManager.getService("user").shellCommand(
707                         getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
708                         new String[] { "list" }, getShellCallback(), adoptResultReceiver());
709                 return 0;
710         }
711         pw.println("Error: unknown list type '" + type + "'");
712         return -1;
713     }
714 
runGc()715     private int runGc() throws RemoteException {
716         Runtime.getRuntime().gc();
717         final PrintWriter pw = getOutPrintWriter();
718         pw.println("Ok");
719         return 0;
720     }
721 
runListFeatures()722     private int runListFeatures() throws RemoteException {
723         final PrintWriter pw = getOutPrintWriter();
724         final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
725 
726         // sort by name
727         Collections.sort(list, new Comparator<FeatureInfo>() {
728             public int compare(FeatureInfo o1, FeatureInfo o2) {
729                 if (o1.name == o2.name) return 0;
730                 if (o1.name == null) return -1;
731                 if (o2.name == null) return 1;
732                 return o1.name.compareTo(o2.name);
733             }
734         });
735 
736         final int count = (list != null) ? list.size() : 0;
737         for (int p = 0; p < count; p++) {
738             FeatureInfo fi = list.get(p);
739             pw.print("feature:");
740             if (fi.name != null) {
741                 pw.print(fi.name);
742                 if (fi.version > 0) {
743                     pw.print("=");
744                     pw.print(fi.version);
745                 }
746                 pw.println();
747             } else {
748                 pw.println("reqGlEsVersion=0x"
749                         + Integer.toHexString(fi.reqGlEsVersion));
750             }
751         }
752         return 0;
753     }
754 
runListInstrumentation()755     private int runListInstrumentation() throws RemoteException {
756         final PrintWriter pw = getOutPrintWriter();
757         boolean showSourceDir = false;
758         String targetPackage = null;
759 
760         try {
761             String opt;
762             while ((opt = getNextArg()) != null) {
763                 switch (opt) {
764                     case "-f":
765                         showSourceDir = true;
766                         break;
767                     default:
768                         if (opt.charAt(0) != '-') {
769                             targetPackage = opt;
770                         } else {
771                             pw.println("Error: Unknown option: " + opt);
772                             return -1;
773                         }
774                         break;
775                 }
776             }
777         } catch (RuntimeException ex) {
778             pw.println("Error: " + ex.toString());
779             return -1;
780         }
781 
782         final List<InstrumentationInfo> list =
783                 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
784 
785         // sort by target package
786         Collections.sort(list, new Comparator<InstrumentationInfo>() {
787             public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
788                 return o1.targetPackage.compareTo(o2.targetPackage);
789             }
790         });
791 
792         final int count = (list != null) ? list.size() : 0;
793         for (int p = 0; p < count; p++) {
794             final InstrumentationInfo ii = list.get(p);
795             pw.print("instrumentation:");
796             if (showSourceDir) {
797                 pw.print(ii.sourceDir);
798                 pw.print("=");
799             }
800             final ComponentName cn = new ComponentName(ii.packageName, ii.name);
801             pw.print(cn.flattenToShortString());
802             pw.print(" (target=");
803             pw.print(ii.targetPackage);
804             pw.println(")");
805         }
806         return 0;
807     }
808 
runListLibraries()809     private int runListLibraries() throws RemoteException {
810         final PrintWriter pw = getOutPrintWriter();
811         final List<String> list = new ArrayList<String>();
812         final String[] rawList = mInterface.getSystemSharedLibraryNames();
813         for (int i = 0; i < rawList.length; i++) {
814             list.add(rawList[i]);
815         }
816 
817         // sort by name
818         Collections.sort(list, new Comparator<String>() {
819             public int compare(String o1, String o2) {
820                 if (o1 == o2) return 0;
821                 if (o1 == null) return -1;
822                 if (o2 == null) return 1;
823                 return o1.compareTo(o2);
824             }
825         });
826 
827         final int count = (list != null) ? list.size() : 0;
828         for (int p = 0; p < count; p++) {
829             String lib = list.get(p);
830             pw.print("library:");
831             pw.println(lib);
832         }
833         return 0;
834     }
835 
runListPackages(boolean showSourceDir)836     private int runListPackages(boolean showSourceDir) throws RemoteException {
837         return runListPackages(showSourceDir, false);
838     }
839 
runListSdks()840     private int runListSdks() throws RemoteException {
841         return runListPackages(false, true);
842     }
843 
runListPackages(boolean showSourceDir, boolean showSdks)844     private int runListPackages(boolean showSourceDir, boolean showSdks) throws RemoteException {
845         final String prefix = showSdks ? "sdk:" : "package:";
846         final PrintWriter pw = getOutPrintWriter();
847         int getFlags = 0;
848         boolean listDisabled = false, listEnabled = false;
849         boolean listSystem = false, listThirdParty = false;
850         boolean listInstaller = false;
851         boolean showUid = false;
852         boolean showVersionCode = false;
853         boolean listApexOnly = false;
854         int uid = -1;
855         int defaultUserId = UserHandle.USER_ALL;
856         try {
857             String opt;
858             while ((opt = getNextOption()) != null) {
859                 switch (opt) {
860                     case "-d":
861                         listDisabled = true;
862                         break;
863                     case "-e":
864                         listEnabled = true;
865                         break;
866                     case "-a":
867                         getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
868                         getFlags |= PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS;
869                         break;
870                     case "-f":
871                         showSourceDir = true;
872                         break;
873                     case "-i":
874                         listInstaller = true;
875                         break;
876                     case "-l":
877                         // old compat
878                         break;
879                     case "-s":
880                         listSystem = true;
881                         break;
882                     case "-U":
883                         showUid = true;
884                         break;
885                     case "-u":
886                         getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
887                         break;
888                     case "-3":
889                         listThirdParty = true;
890                         break;
891                     case "--show-versioncode":
892                         showVersionCode = true;
893                         break;
894                     case "--apex-only":
895                         getFlags |= PackageManager.MATCH_APEX;
896                         listApexOnly = true;
897                         break;
898                     case "--user":
899                         defaultUserId = UserHandle.parseUserArg(getNextArgRequired());
900                         break;
901                     case "--uid":
902                         showUid = true;
903                         uid = Integer.parseInt(getNextArgRequired());
904                         break;
905                     default:
906                         pw.println("Error: Unknown option: " + opt);
907                         return -1;
908                 }
909             }
910         } catch (RuntimeException ex) {
911             pw.println("Error: " + ex.toString());
912             return -1;
913         }
914 
915         final String filter = getNextArg();
916 
917         int[] userIds = {defaultUserId};
918         if (defaultUserId == UserHandle.USER_ALL) {
919             final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
920             userIds = umi.getUserIds();
921         }
922         if (showSdks) {
923             getFlags |= PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES;
924         }
925 
926         // Build a map of packages to a list of corresponding uids. Keys are strings containing
927         // the sdk or package name along with optional additional information based on opt.
928         final Map<String, List<String>> out = new HashMap<>();
929         for (int userId : userIds) {
930             final int translatedUserId =
931                     translateUserId(userId, UserHandle.USER_SYSTEM, "runListPackages");
932             @SuppressWarnings("unchecked") final ParceledListSlice<PackageInfo> slice =
933                     mInterface.getInstalledPackages(getFlags, translatedUserId);
934             final List<PackageInfo> packages = slice.getList();
935 
936             final int count = packages.size();
937             for (int p = 0; p < count; p++) {
938                 final PackageInfo info = packages.get(p);
939                 final StringBuilder stringBuilder = new StringBuilder();
940                 if (filter != null && !info.packageName.contains(filter)) {
941                     continue;
942                 }
943                 final boolean isApex = info.isApex;
944                 if (uid != -1 && !isApex && info.applicationInfo.uid != uid) {
945                     continue;
946                 }
947 
948                 final boolean isSystem = !isApex
949                         && (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
950                 final boolean isEnabled = !isApex && info.applicationInfo.enabled;
951                 if ((listDisabled && isEnabled)
952                         || (listEnabled && !isEnabled)
953                         || (listSystem && !isSystem)
954                         || (listThirdParty && isSystem)
955                         || (listApexOnly && !isApex)) {
956                     continue;
957                 }
958 
959                 String name = null;
960                 if (showSdks) {
961                     final ParceledListSlice<SharedLibraryInfo> libsSlice =
962                             mInterface.getDeclaredSharedLibraries(
963                                 info.packageName, getFlags, userId
964                             );
965                     if (libsSlice == null) {
966                         continue;
967                     }
968                     final List<SharedLibraryInfo> libs = libsSlice.getList();
969                     for (int l = 0, lsize = libs.size(); l < lsize; ++l) {
970                         SharedLibraryInfo lib = libs.get(l);
971                         if (lib.getType() == SharedLibraryInfo.TYPE_SDK_PACKAGE) {
972                             name = lib.getName() + ":" + lib.getLongVersion();
973                             break;
974                         }
975                     }
976                     if (name == null) {
977                         continue;
978                     }
979                 } else {
980                     name = info.packageName;
981                 }
982 
983                 stringBuilder.append(prefix);
984                 if (showSourceDir) {
985                     stringBuilder.append(info.applicationInfo.sourceDir);
986                     stringBuilder.append("=");
987                 }
988                 stringBuilder.append(name);
989                 if (showVersionCode) {
990                     stringBuilder.append(" versionCode:");
991                     if (info.applicationInfo != null) {
992                         stringBuilder.append(info.applicationInfo.longVersionCode);
993                     } else {
994                         stringBuilder.append(info.getLongVersionCode());
995                     }
996                 }
997                 if (listInstaller) {
998                     stringBuilder.append("  installer=");
999                     stringBuilder.append(mInterface.getInstallerPackageName(info.packageName));
1000                 }
1001                 List<String> uids = out.computeIfAbsent(
1002                         stringBuilder.toString(), k -> new ArrayList<>()
1003                 );
1004                 if (showUid && !isApex) {
1005                     uids.add(String.valueOf(info.applicationInfo.uid));
1006                 }
1007             }
1008         }
1009         for (Map.Entry<String, List<String>> entry : out.entrySet()) {
1010             pw.print(entry.getKey());
1011             List<String> uids = entry.getValue();
1012             if (!uids.isEmpty()) {
1013                 pw.print(" uid:");
1014                 pw.print(String.join(",", uids));
1015             }
1016             pw.println();
1017         }
1018         return 0;
1019     }
1020 
runListPermissionGroups()1021     private int runListPermissionGroups() throws RemoteException {
1022         final PrintWriter pw = getOutPrintWriter();
1023         final List<PermissionGroupInfo> pgs = mPermissionManager.getAllPermissionGroups(0);
1024 
1025         final int count = pgs.size();
1026         for (int p = 0; p < count ; p++) {
1027             final PermissionGroupInfo pgi = pgs.get(p);
1028             pw.print("permission group:");
1029             pw.println(pgi.name);
1030         }
1031         return 0;
1032     }
1033 
runListPermissions()1034     private int runListPermissions() throws RemoteException {
1035         final PrintWriter pw = getOutPrintWriter();
1036         boolean labels = false;
1037         boolean groups = false;
1038         boolean userOnly = false;
1039         boolean summary = false;
1040         boolean dangerousOnly = false;
1041         String opt;
1042         while ((opt = getNextOption()) != null) {
1043             switch (opt) {
1044                 case "-d":
1045                     dangerousOnly = true;
1046                     break;
1047                 case "-f":
1048                     labels = true;
1049                     break;
1050                 case "-g":
1051                     groups = true;
1052                     break;
1053                 case "-s":
1054                     groups = true;
1055                     labels = true;
1056                     summary = true;
1057                     break;
1058                 case "-u":
1059                     userOnly = true;
1060                     break;
1061                 default:
1062                     pw.println("Error: Unknown option: " + opt);
1063                     return 1;
1064             }
1065         }
1066 
1067         final ArrayList<String> groupList = new ArrayList<String>();
1068         if (groups) {
1069             final List<PermissionGroupInfo> infos =
1070                     mPermissionManager.getAllPermissionGroups(0 /*flags*/);
1071             final int count = infos.size();
1072             for (int i = 0; i < count; i++) {
1073                 groupList.add(infos.get(i).name);
1074             }
1075             groupList.add(null);
1076         } else {
1077             final String grp = getNextArg();
1078             groupList.add(grp);
1079         }
1080 
1081         if (dangerousOnly) {
1082             pw.println("Dangerous Permissions:");
1083             pw.println("");
1084             doListPermissions(groupList, groups, labels, summary,
1085                     PermissionInfo.PROTECTION_DANGEROUS,
1086                     PermissionInfo.PROTECTION_DANGEROUS);
1087             if (userOnly) {
1088                 pw.println("Normal Permissions:");
1089                 pw.println("");
1090                 doListPermissions(groupList, groups, labels, summary,
1091                         PermissionInfo.PROTECTION_NORMAL,
1092                         PermissionInfo.PROTECTION_NORMAL);
1093             }
1094         } else if (userOnly) {
1095             pw.println("Dangerous and Normal Permissions:");
1096             pw.println("");
1097             doListPermissions(groupList, groups, labels, summary,
1098                     PermissionInfo.PROTECTION_NORMAL,
1099                     PermissionInfo.PROTECTION_DANGEROUS);
1100         } else {
1101             pw.println("All Permissions:");
1102             pw.println("");
1103             doListPermissions(groupList, groups, labels, summary,
1104                     -10000, 10000);
1105         }
1106         return 0;
1107     }
1108 
1109     private static class SessionDump {
1110         boolean onlyParent; // Show parent sessions only
1111         boolean onlyReady; // Show only staged sessions that are in ready state
1112         boolean onlySessionId; // Show sessionId only
1113     }
1114 
1115     // Returns true if the provided flag is a session flag and given SessionDump was updated
setSessionFlag(String flag, SessionDump sessionDump)1116     private boolean setSessionFlag(String flag, SessionDump sessionDump) {
1117         switch (flag) {
1118             case "--only-parent":
1119                 sessionDump.onlyParent = true;
1120                 break;
1121             case "--only-ready":
1122                 sessionDump.onlyReady = true;
1123                 break;
1124             case "--only-sessionid":
1125                 sessionDump.onlySessionId = true;
1126                 break;
1127             default:
1128                 return false;
1129         }
1130         return true;
1131     }
1132 
runListStagedSessions()1133     private int runListStagedSessions() {
1134         try (IndentingPrintWriter pw = new IndentingPrintWriter(
1135                 getOutPrintWriter(), /* singleIndent */ "  ", /* wrapLength */ 120)) {
1136             final SessionDump sessionDump = new SessionDump();
1137             String opt;
1138             while ((opt = getNextOption()) != null) {
1139                 if (!setSessionFlag(opt, sessionDump)) {
1140                     pw.println("Error: Unknown option: " + opt);
1141                     return -1;
1142                 }
1143             }
1144 
1145             try {
1146                 final List<SessionInfo> stagedSessions =
1147                         mInterface.getPackageInstaller().getStagedSessions().getList();
1148                 printSessionList(pw, stagedSessions, sessionDump);
1149             } catch (RemoteException e) {
1150                 pw.println("Failure ["
1151                         + e.getClass().getName() + " - "
1152                         + e.getMessage() + "]");
1153                 return -1;
1154             }
1155             return 1;
1156         }
1157     }
1158 
printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions, SessionDump sessionDump)1159     private void printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions,
1160             SessionDump sessionDump) {
1161         final SparseArray<SessionInfo> sessionById = new SparseArray<>(stagedSessions.size());
1162         for (SessionInfo session : stagedSessions) {
1163             sessionById.put(session.getSessionId(), session);
1164         }
1165         for (SessionInfo session: stagedSessions) {
1166             if (sessionDump.onlyReady && !session.isStagedSessionReady()) {
1167                 continue;
1168             }
1169             if (session.getParentSessionId() != SessionInfo.INVALID_ID) {
1170                 continue;
1171             }
1172             printSession(pw, session, sessionDump);
1173             if (session.isMultiPackage() && !sessionDump.onlyParent) {
1174                 pw.increaseIndent();
1175                 final int[] childIds = session.getChildSessionIds();
1176                 for (int i = 0; i < childIds.length; i++) {
1177                     final SessionInfo childSession = sessionById.get(childIds[i]);
1178                     if (childSession == null) {
1179                         if (sessionDump.onlySessionId) {
1180                             pw.println(childIds[i]);
1181                         } else {
1182                             pw.println("sessionId = " + childIds[i] + "; not found");
1183                         }
1184                     } else {
1185                         printSession(pw, childSession, sessionDump);
1186                     }
1187                 }
1188                 pw.decreaseIndent();
1189             }
1190         }
1191     }
1192 
printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump)1193     private static void printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump) {
1194         if (sessionDump.onlySessionId) {
1195             pw.println(session.getSessionId());
1196             return;
1197         }
1198         pw.println("sessionId = " + session.getSessionId()
1199                 + "; appPackageName = " + session.getAppPackageName()
1200                 + "; isStaged = " + session.isStaged()
1201                 + "; isReady = " + session.isStagedSessionReady()
1202                 + "; isApplied = " + session.isStagedSessionApplied()
1203                 + "; isFailed = " + session.isStagedSessionFailed()
1204                 + "; errorMsg = " + session.getStagedSessionErrorMessage()
1205                 + ";");
1206     }
1207 
parseIntentAndUser()1208     private Intent parseIntentAndUser() throws URISyntaxException {
1209         mTargetUser = UserHandle.USER_CURRENT;
1210         mBrief = false;
1211         mComponents = false;
1212         Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
1213             @Override
1214             public boolean handleOption(String opt, ShellCommand cmd) {
1215                 if ("--user".equals(opt)) {
1216                     mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
1217                     return true;
1218                 } else if ("--brief".equals(opt)) {
1219                     mBrief = true;
1220                     return true;
1221                 } else if ("--components".equals(opt)) {
1222                     mComponents = true;
1223                     return true;
1224                 } else if ("--query-flags".equals(opt)) {
1225                     mQueryFlags = Integer.decode(cmd.getNextArgRequired());
1226                     return true;
1227                 }
1228                 return false;
1229             }
1230         });
1231         mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1232                 Binder.getCallingUid(), mTargetUser, false, false, null, null);
1233         return intent;
1234     }
1235 
printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri, boolean brief, boolean components)1236     private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri,
1237             boolean brief, boolean components) {
1238         if (brief || components) {
1239             final ComponentName comp;
1240             if (ri.activityInfo != null) {
1241                 comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
1242             } else if (ri.serviceInfo != null) {
1243                 comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
1244             } else if (ri.providerInfo != null) {
1245                 comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name);
1246             } else {
1247                 comp = null;
1248             }
1249             if (comp != null) {
1250                 if (!components) {
1251                     pr.println(prefix + "priority=" + ri.priority
1252                             + " preferredOrder=" + ri.preferredOrder
1253                             + " match=0x" + Integer.toHexString(ri.match)
1254                             + " specificIndex=" + ri.specificIndex
1255                             + " isDefault=" + ri.isDefault);
1256                 }
1257                 pr.println(prefix + comp.flattenToShortString());
1258                 return;
1259             }
1260         }
1261         ri.dump(pr, prefix);
1262     }
1263 
runResolveActivity()1264     private int runResolveActivity() {
1265         Intent intent;
1266         try {
1267             intent = parseIntentAndUser();
1268         } catch (URISyntaxException e) {
1269             throw new RuntimeException(e.getMessage(), e);
1270         }
1271         try {
1272             ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), mQueryFlags,
1273                     mTargetUser);
1274             PrintWriter pw = getOutPrintWriter();
1275             if (ri == null) {
1276                 pw.println("No activity found");
1277             } else {
1278                 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1279                 printResolveInfo(pr, "", ri, mBrief, mComponents);
1280             }
1281         } catch (RemoteException e) {
1282             throw new RuntimeException("Failed calling service", e);
1283         }
1284         return 0;
1285     }
1286 
runQueryIntentActivities()1287     private int runQueryIntentActivities() {
1288         Intent intent;
1289         try {
1290             intent = parseIntentAndUser();
1291         } catch (URISyntaxException e) {
1292             throw new RuntimeException(e.getMessage(), e);
1293         }
1294         try {
1295             List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(),
1296                     mQueryFlags, mTargetUser).getList();
1297             PrintWriter pw = getOutPrintWriter();
1298             if (result == null || result.size() <= 0) {
1299                 pw.println("No activities found");
1300             } else {
1301                 if (!mComponents) {
1302                     pw.print(result.size()); pw.println(" activities found:");
1303                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1304                     for (int i = 0; i < result.size(); i++) {
1305                         pw.print("  Activity #"); pw.print(i); pw.println(":");
1306                         printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
1307                     }
1308                 } else {
1309                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1310                     for (int i = 0; i < result.size(); i++) {
1311                         printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1312                     }
1313                 }
1314             }
1315         } catch (RemoteException e) {
1316             throw new RuntimeException("Failed calling service", e);
1317         }
1318         return 0;
1319     }
1320 
runQueryIntentServices()1321     private int runQueryIntentServices() {
1322         Intent intent;
1323         try {
1324             intent = parseIntentAndUser();
1325         } catch (URISyntaxException e) {
1326             throw new RuntimeException(e.getMessage(), e);
1327         }
1328         try {
1329             List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(),
1330                     mQueryFlags, mTargetUser).getList();
1331             PrintWriter pw = getOutPrintWriter();
1332             if (result == null || result.size() <= 0) {
1333                 pw.println("No services found");
1334             } else {
1335                 if (!mComponents) {
1336                     pw.print(result.size()); pw.println(" services found:");
1337                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1338                     for (int i = 0; i < result.size(); i++) {
1339                         pw.print("  Service #"); pw.print(i); pw.println(":");
1340                         printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
1341                     }
1342                 } else {
1343                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1344                     for (int i = 0; i < result.size(); i++) {
1345                         printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1346                     }
1347                 }
1348             }
1349         } catch (RemoteException e) {
1350             throw new RuntimeException("Failed calling service", e);
1351         }
1352         return 0;
1353     }
1354 
runQueryIntentReceivers()1355     private int runQueryIntentReceivers() {
1356         Intent intent;
1357         try {
1358             intent = parseIntentAndUser();
1359         } catch (URISyntaxException e) {
1360             throw new RuntimeException(e.getMessage(), e);
1361         }
1362         try {
1363             List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(),
1364                     mQueryFlags, mTargetUser).getList();
1365             PrintWriter pw = getOutPrintWriter();
1366             if (result == null || result.size() <= 0) {
1367                 pw.println("No receivers found");
1368             } else {
1369                 if (!mComponents) {
1370                     pw.print(result.size()); pw.println(" receivers found:");
1371                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1372                     for (int i = 0; i < result.size(); i++) {
1373                         pw.print("  Receiver #"); pw.print(i); pw.println(":");
1374                         printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
1375                     }
1376                 } else {
1377                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1378                     for (int i = 0; i < result.size(); i++) {
1379                         printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1380                     }
1381                 }
1382             }
1383         } catch (RemoteException e) {
1384             throw new RuntimeException("Failed calling service", e);
1385         }
1386         return 0;
1387     }
1388 
runStreamingInstall()1389     private int runStreamingInstall() throws RemoteException {
1390         final InstallParams params = makeInstallParams(UNSUPPORTED_INSTALL_CMD_OPTS);
1391         if (params.sessionParams.dataLoaderParams == null) {
1392             params.sessionParams.setDataLoaderParams(
1393                     PackageManagerShellCommandDataLoader.getStreamingDataLoaderParams(this));
1394         }
1395         return doRunInstall(params);
1396     }
1397 
runIncrementalInstall()1398     private int runIncrementalInstall() throws RemoteException {
1399         final InstallParams params = makeInstallParams(UNSUPPORTED_INSTALL_CMD_OPTS);
1400         if (params.sessionParams.dataLoaderParams == null) {
1401             params.sessionParams.setDataLoaderParams(
1402                     PackageManagerShellCommandDataLoader.getIncrementalDataLoaderParams(this));
1403         }
1404         return doRunInstall(params);
1405     }
1406 
runInstall()1407     private int runInstall() throws RemoteException {
1408         return doRunInstall(makeInstallParams(UNSUPPORTED_INSTALL_CMD_OPTS));
1409     }
1410 
doRunInstall(final InstallParams params)1411     private int doRunInstall(final InstallParams params) throws RemoteException {
1412         final PrintWriter pw = getOutPrintWriter();
1413 
1414         final boolean isStreaming = params.sessionParams.dataLoaderParams != null;
1415         final boolean isApex =
1416                 (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0;
1417 
1418         ArrayList<String> args = getRemainingArgs();
1419 
1420         final boolean fromStdIn = args.isEmpty() || STDIN_PATH.equals(args.get(0));
1421         final boolean hasSplits = args.size() > 1;
1422 
1423         if (fromStdIn && params.sessionParams.sizeBytes == -1) {
1424             pw.println("Error: must either specify a package size or an APK file");
1425             return 1;
1426         }
1427 
1428         if (isApex && hasSplits) {
1429             pw.println("Error: can't specify SPLIT(s) for APEX");
1430             return 1;
1431         }
1432 
1433         if (!isStreaming) {
1434             if (fromStdIn && hasSplits) {
1435                 pw.println("Error: can't specify SPLIT(s) along with STDIN");
1436                 return 1;
1437             }
1438 
1439             if (args.isEmpty()) {
1440                 args.add(STDIN_PATH);
1441             } else {
1442                 setParamsSize(params, args);
1443             }
1444         }
1445 
1446         final int sessionId = doCreateSession(params.sessionParams,
1447                 params.installerPackageName, params.userId);
1448         boolean abandonSession = true;
1449         try {
1450             if (isStreaming) {
1451                 if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex)
1452                         != PackageInstaller.STATUS_SUCCESS) {
1453                     return 1;
1454                 }
1455             } else {
1456                 if (doWriteSplits(sessionId, args, params.sessionParams.sizeBytes, isApex)
1457                         != PackageInstaller.STATUS_SUCCESS) {
1458                     return 1;
1459                 }
1460             }
1461             if (doCommitSession(sessionId, false /*logSuccess*/)
1462                     != PackageInstaller.STATUS_SUCCESS) {
1463                 return 1;
1464             }
1465             abandonSession = false;
1466 
1467             if (params.sessionParams.isStaged && params.stagedReadyTimeoutMs > 0) {
1468                 return doWaitForStagedSessionReady(sessionId, params.stagedReadyTimeoutMs, pw);
1469             }
1470 
1471             pw.println("Success");
1472             return 0;
1473         } finally {
1474             if (abandonSession) {
1475                 try {
1476                     doAbandonSession(sessionId, false /*logSuccess*/);
1477                 } catch (Exception ignore) {
1478                 }
1479             }
1480         }
1481     }
1482 
doWaitForStagedSessionReady(int sessionId, long timeoutMs, PrintWriter pw)1483     private int doWaitForStagedSessionReady(int sessionId, long timeoutMs, PrintWriter pw)
1484               throws RemoteException {
1485         Preconditions.checkArgument(timeoutMs > 0);
1486         PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
1487                 .getSessionInfo(sessionId);
1488         if (si == null) {
1489             pw.println("Failure [Unknown session " + sessionId + "]");
1490             return 1;
1491         }
1492         if (!si.isStaged()) {
1493             pw.println("Failure [Session " + sessionId + " is not a staged session]");
1494             return 1;
1495         }
1496         long currentTime = System.currentTimeMillis();
1497         long endTime = currentTime + timeoutMs;
1498         // Using a loop instead of BroadcastReceiver since we can receive session update
1499         // broadcast only if packageInstallerName is "android". We can't always force
1500         // "android" as packageIntallerName, e.g, rollback auto implies
1501         // "-i com.android.shell".
1502         while (currentTime < endTime) {
1503             if (si != null && (si.isStagedSessionReady() || si.isStagedSessionFailed())) {
1504                 break;
1505             }
1506             SystemClock.sleep(Math.min(endTime - currentTime, 100));
1507             currentTime = System.currentTimeMillis();
1508             si = mInterface.getPackageInstaller().getSessionInfo(sessionId);
1509         }
1510         if (si == null) {
1511             pw.println("Failure [failed to retrieve SessionInfo]");
1512             return 1;
1513         }
1514         if (!si.isStagedSessionReady() && !si.isStagedSessionFailed()) {
1515             pw.println("Failure [timed out after " + timeoutMs + " ms]");
1516             return 1;
1517         }
1518         if (!si.isStagedSessionReady()) {
1519             pw.println("Error [" + si.getStagedSessionErrorCode() + "] ["
1520                     + si.getStagedSessionErrorMessage() + "]");
1521             return 1;
1522         }
1523         pw.println("Success. Reboot device to apply staged session");
1524         return 0;
1525     }
1526 
runInstallAbandon()1527     private int runInstallAbandon() throws RemoteException {
1528         final int sessionId = Integer.parseInt(getNextArg());
1529         return doAbandonSession(sessionId, true /*logSuccess*/);
1530     }
1531 
runInstallCommit()1532     private int runInstallCommit() throws RemoteException {
1533         final PrintWriter pw = getOutPrintWriter();
1534         String opt;
1535         long stagedReadyTimeoutMs = DEFAULT_STAGED_READY_TIMEOUT_MS;
1536         while ((opt = getNextOption()) != null) {
1537             switch (opt) {
1538                 case "--staged-ready-timeout":
1539                     stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired());
1540                     break;
1541                 default:
1542                     throw new IllegalArgumentException("Unknown option: " + opt);
1543             }
1544         }
1545         final int sessionId = Integer.parseInt(getNextArg());
1546         if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
1547             return 1;
1548         }
1549         final PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
1550                 .getSessionInfo(sessionId);
1551         if (si != null && si.isStaged() && stagedReadyTimeoutMs > 0) {
1552             return doWaitForStagedSessionReady(sessionId, stagedReadyTimeoutMs, pw);
1553         }
1554         pw.println("Success");
1555         return 0;
1556     }
1557 
runInstallCreate()1558     private int runInstallCreate() throws RemoteException {
1559         final PrintWriter pw = getOutPrintWriter();
1560         final InstallParams installParams = makeInstallParams(UNSUPPORTED_SESSION_CREATE_OPTS);
1561         final int sessionId = doCreateSession(installParams.sessionParams,
1562                 installParams.installerPackageName, installParams.userId);
1563 
1564         // NOTE: adb depends on parsing this string
1565         pw.println("Success: created install session [" + sessionId + "]");
1566         return 0;
1567     }
1568 
runInstallWrite()1569     private int runInstallWrite() throws RemoteException {
1570         long sizeBytes = -1;
1571 
1572         String opt;
1573         while ((opt = getNextOption()) != null) {
1574             if (opt.equals("-S")) {
1575                 sizeBytes = Long.parseLong(getNextArg());
1576             } else {
1577                 throw new IllegalArgumentException("Unknown option: " + opt);
1578             }
1579         }
1580 
1581         final int sessionId = Integer.parseInt(getNextArg());
1582         final String splitName = getNextArg();
1583         final String path = getNextArg();
1584         return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
1585     }
1586 
runInstallAddSession()1587     private int runInstallAddSession() throws RemoteException {
1588         final PrintWriter pw = getOutPrintWriter();
1589         final int parentSessionId = Integer.parseInt(getNextArg());
1590 
1591         IntArray otherSessionIds = new IntArray();
1592         String opt;
1593         while ((opt = getNextArg()) != null) {
1594             otherSessionIds.add(Integer.parseInt(opt));
1595         }
1596         if (otherSessionIds.size() == 0) {
1597             pw.println("Error: At least two sessions are required.");
1598             return 1;
1599         }
1600         return doInstallAddSession(parentSessionId, otherSessionIds.toArray(),
1601                 true /*logSuccess*/);
1602     }
1603 
runInstallRemove()1604     private int runInstallRemove() throws RemoteException {
1605         final PrintWriter pw = getOutPrintWriter();
1606 
1607         final int sessionId = Integer.parseInt(getNextArg());
1608 
1609         ArrayList<String> splitNames = getRemainingArgs();
1610         if (splitNames.isEmpty()) {
1611             pw.println("Error: split name not specified");
1612             return 1;
1613         }
1614         return doRemoveSplits(sessionId, splitNames, true /*logSuccess*/);
1615     }
1616 
runInstallExisting()1617     private int runInstallExisting() throws RemoteException {
1618         final PrintWriter pw = getOutPrintWriter();
1619         int userId = UserHandle.USER_CURRENT;
1620         int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1621         String opt;
1622         boolean waitTillComplete = false;
1623         while ((opt = getNextOption()) != null) {
1624             switch (opt) {
1625                 case "--user":
1626                     userId = UserHandle.parseUserArg(getNextArgRequired());
1627                     break;
1628                 case "--ephemeral":
1629                 case "--instant":
1630                     installFlags |= PackageManager.INSTALL_INSTANT_APP;
1631                     installFlags &= ~PackageManager.INSTALL_FULL_APP;
1632                     break;
1633                 case "--full":
1634                     installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1635                     installFlags |= PackageManager.INSTALL_FULL_APP;
1636                     break;
1637                 case "--wait":
1638                     waitTillComplete = true;
1639                     break;
1640                 case "--restrict-permissions":
1641                     installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1642                     break;
1643                 default:
1644                     pw.println("Error: Unknown option: " + opt);
1645                     return 1;
1646             }
1647         }
1648 
1649         final String packageName = getNextArg();
1650         if (packageName == null) {
1651             pw.println("Error: package name not specified");
1652             return 1;
1653         }
1654         final int translatedUserId =
1655                 translateUserId(userId, UserHandle.USER_NULL, "runInstallExisting");
1656 
1657         int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
1658         try {
1659             if (waitTillComplete) {
1660                 final LocalIntentReceiver receiver = new LocalIntentReceiver();
1661                 final IPackageInstaller installer = mInterface.getPackageInstaller();
1662                 pw.println("Installing package " + packageName + " for user: " + translatedUserId);
1663                 installer.installExistingPackage(packageName, installFlags, installReason,
1664                         receiver.getIntentSender(), translatedUserId, null);
1665                 final Intent result = receiver.getResult();
1666                 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1667                         PackageInstaller.STATUS_FAILURE);
1668                 pw.println("Received intent for package install");
1669                 return status == PackageInstaller.STATUS_SUCCESS ? 0 : 1;
1670             }
1671 
1672             final int res = mInterface.installExistingPackageAsUser(packageName, translatedUserId,
1673                     installFlags, installReason, null);
1674             if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
1675                 throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1676             }
1677             pw.println("Package " + packageName + " installed for user: " + translatedUserId);
1678             return 0;
1679         } catch (RemoteException | NameNotFoundException e) {
1680             pw.println(e.toString());
1681             return 1;
1682         }
1683     }
1684 
runSetInstallLocation()1685     private int runSetInstallLocation() throws RemoteException {
1686         int loc;
1687 
1688         String arg = getNextArg();
1689         if (arg == null) {
1690             getErrPrintWriter().println("Error: no install location specified.");
1691             return 1;
1692         }
1693         try {
1694             loc = Integer.parseInt(arg);
1695         } catch (NumberFormatException e) {
1696             getErrPrintWriter().println("Error: install location has to be a number.");
1697             return 1;
1698         }
1699         if (!mInterface.setInstallLocation(loc)) {
1700             getErrPrintWriter().println("Error: install location has to be a number.");
1701             return 1;
1702         }
1703         return 0;
1704     }
1705 
runGetInstallLocation()1706     private int runGetInstallLocation() throws RemoteException {
1707         int loc = mInterface.getInstallLocation();
1708         String locStr = "invalid";
1709         if (loc == InstallLocationUtils.APP_INSTALL_AUTO) {
1710             locStr = "auto";
1711         } else if (loc == InstallLocationUtils.APP_INSTALL_INTERNAL) {
1712             locStr = "internal";
1713         } else if (loc == InstallLocationUtils.APP_INSTALL_EXTERNAL) {
1714             locStr = "external";
1715         }
1716         getOutPrintWriter().println(loc + "[" + locStr + "]");
1717         return 0;
1718     }
1719 
runMovePackage()1720     public int runMovePackage() throws RemoteException {
1721         final String packageName = getNextArg();
1722         if (packageName == null) {
1723             getErrPrintWriter().println("Error: package name not specified");
1724             return 1;
1725         }
1726         String volumeUuid = getNextArg();
1727         if ("internal".equals(volumeUuid)) {
1728             volumeUuid = null;
1729         }
1730 
1731         final int moveId = mInterface.movePackage(packageName, volumeUuid);
1732 
1733         int status = mInterface.getMoveStatus(moveId);
1734         while (!PackageManager.isMoveStatusFinished(status)) {
1735             SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1736             status = mInterface.getMoveStatus(moveId);
1737         }
1738 
1739         if (status == PackageManager.MOVE_SUCCEEDED) {
1740             getOutPrintWriter().println("Success");
1741             return 0;
1742         } else {
1743             getErrPrintWriter().println("Failure [" + status + "]");
1744             return 1;
1745         }
1746     }
1747 
runMovePrimaryStorage()1748     public int runMovePrimaryStorage() throws RemoteException {
1749         String volumeUuid = getNextArg();
1750         if ("internal".equals(volumeUuid)) {
1751             volumeUuid = null;
1752         }
1753 
1754         final int moveId = mInterface.movePrimaryStorage(volumeUuid);
1755 
1756         int status = mInterface.getMoveStatus(moveId);
1757         while (!PackageManager.isMoveStatusFinished(status)) {
1758             SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1759             status = mInterface.getMoveStatus(moveId);
1760         }
1761 
1762         if (status == PackageManager.MOVE_SUCCEEDED) {
1763             getOutPrintWriter().println("Success");
1764             return 0;
1765         } else {
1766             getErrPrintWriter().println("Failure [" + status + "]");
1767             return 1;
1768         }
1769     }
1770 
runCompile()1771     private int runCompile() throws RemoteException {
1772         final PrintWriter pw = getOutPrintWriter();
1773         boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
1774         boolean forceCompilation = false;
1775         boolean allPackages = false;
1776         boolean clearProfileData = false;
1777         String compilerFilter = null;
1778         String compilationReason = null;
1779         String checkProfilesRaw = null;
1780         boolean secondaryDex = false;
1781         String split = null;
1782         boolean compileLayouts = false;
1783 
1784         String opt;
1785         while ((opt = getNextOption()) != null) {
1786             switch (opt) {
1787                 case "-a":
1788                     allPackages = true;
1789                     break;
1790                 case "-c":
1791                     clearProfileData = true;
1792                     break;
1793                 case "-f":
1794                     forceCompilation = true;
1795                     break;
1796                 case "-m":
1797                     compilerFilter = getNextArgRequired();
1798                     break;
1799                 case "-r":
1800                     compilationReason = getNextArgRequired();
1801                     break;
1802                 case "--compile-layouts":
1803                     compileLayouts = true;
1804                     break;
1805                 case "--check-prof":
1806                     checkProfilesRaw = getNextArgRequired();
1807                     break;
1808                 case "--reset":
1809                     forceCompilation = true;
1810                     clearProfileData = true;
1811                     compilationReason = "install";
1812                     break;
1813                 case "--secondary-dex":
1814                     secondaryDex = true;
1815                     break;
1816                 case "--split":
1817                     split = getNextArgRequired();
1818                     break;
1819                 default:
1820                     pw.println("Error: Unknown option: " + opt);
1821                     return 1;
1822             }
1823         }
1824 
1825         if (checkProfilesRaw != null) {
1826             if ("true".equals(checkProfilesRaw)) {
1827                 checkProfiles = true;
1828             } else if ("false".equals(checkProfilesRaw)) {
1829                 checkProfiles = false;
1830             } else {
1831                 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
1832                 return 1;
1833             }
1834         }
1835 
1836         final boolean compilerFilterGiven = compilerFilter != null;
1837         final boolean compilationReasonGiven = compilationReason != null;
1838         // Make sure exactly one of -m, -r, or --compile-layouts is given.
1839         if ((!compilerFilterGiven && !compilationReasonGiven && !compileLayouts)
1840             || (!compilerFilterGiven && compilationReasonGiven && compileLayouts)
1841             || (compilerFilterGiven && !compilationReasonGiven && compileLayouts)
1842             || (compilerFilterGiven && compilationReasonGiven && !compileLayouts)
1843             || (compilerFilterGiven && compilationReasonGiven && compileLayouts)) {
1844             pw.println("Must specify exactly one of compilation filter (\"-m\"), compilation " +
1845                     "reason (\"-r\"), or compile layouts (\"--compile-layouts\")");
1846             return 1;
1847         }
1848 
1849         if (allPackages && split != null) {
1850             pw.println("-a cannot be specified together with --split");
1851             return 1;
1852         }
1853 
1854         if (secondaryDex && split != null) {
1855             pw.println("--secondary-dex cannot be specified together with --split");
1856             return 1;
1857         }
1858 
1859         String targetCompilerFilter = null;
1860         if (compilerFilterGiven) {
1861             if (!DexFile.isValidCompilerFilter(compilerFilter)) {
1862                 pw.println("Error: \"" + compilerFilter +
1863                         "\" is not a valid compilation filter.");
1864                 return 1;
1865             }
1866             targetCompilerFilter = compilerFilter;
1867         }
1868         if (compilationReasonGiven) {
1869             int reason = -1;
1870             for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
1871                 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
1872                         compilationReason)) {
1873                     reason = i;
1874                     break;
1875                 }
1876             }
1877             if (reason == -1) {
1878                 pw.println("Error: Unknown compilation reason: " + compilationReason);
1879                 return 1;
1880             }
1881             targetCompilerFilter =
1882                     PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
1883         }
1884 
1885 
1886         List<String> packageNames = null;
1887         if (allPackages) {
1888             packageNames = mInterface.getAllPackages();
1889         } else {
1890             String packageName = getNextArg();
1891             if (packageName == null) {
1892                 pw.println("Error: package name not specified");
1893                 return 1;
1894             }
1895             packageNames = Collections.singletonList(packageName);
1896         }
1897 
1898         List<String> failedPackages = new ArrayList<>();
1899         int index = 0;
1900         for (String packageName : packageNames) {
1901             if (clearProfileData) {
1902                 mInterface.clearApplicationProfileData(packageName);
1903             }
1904 
1905             if (allPackages) {
1906                 pw.println(++index + "/" + packageNames.size() + ": " + packageName);
1907                 pw.flush();
1908             }
1909 
1910             boolean result = true;
1911             if (compileLayouts) {
1912                 PackageManagerInternal internal = LocalServices.getService(
1913                         PackageManagerInternal.class);
1914                 result = internal.compileLayouts(packageName);
1915             } else {
1916                 result = secondaryDex
1917                     ? mInterface.performDexOptSecondary(packageName,
1918                             targetCompilerFilter, forceCompilation)
1919                     : mInterface.performDexOptMode(packageName,
1920                             checkProfiles, targetCompilerFilter, forceCompilation,
1921                             true /* bootComplete */, split);
1922             }
1923             if (!result) {
1924                 failedPackages.add(packageName);
1925             }
1926         }
1927 
1928         if (failedPackages.isEmpty()) {
1929             pw.println("Success");
1930             return 0;
1931         } else if (failedPackages.size() == 1) {
1932             pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
1933             return 1;
1934         } else {
1935             pw.print("Failure: the following packages could not be compiled: ");
1936             boolean is_first = true;
1937             for (String packageName : failedPackages) {
1938                 if (is_first) {
1939                     is_first = false;
1940                 } else {
1941                     pw.print(", ");
1942                 }
1943                 pw.print(packageName);
1944             }
1945             pw.println();
1946             return 1;
1947         }
1948     }
1949 
runreconcileSecondaryDexFiles()1950     private int runreconcileSecondaryDexFiles() throws RemoteException {
1951         String packageName = getNextArg();
1952         mInterface.reconcileSecondaryDexFiles(packageName);
1953         return 0;
1954     }
1955 
runForceDexOpt()1956     public int runForceDexOpt() throws RemoteException {
1957         mInterface.forceDexOpt(getNextArgRequired());
1958         return 0;
1959     }
1960 
runDexoptJob()1961     private int runDexoptJob() throws RemoteException {
1962         String arg;
1963         List<String> packageNames = new ArrayList<>();
1964         while ((arg = getNextArg()) != null) {
1965             packageNames.add(arg);
1966         }
1967         boolean result = BackgroundDexOptService.getService().runBackgroundDexoptJob(
1968                 packageNames.isEmpty() ? null : packageNames);
1969         getOutPrintWriter().println(result ? "Success" : "Failure");
1970         return result ? 0 : -1;
1971     }
1972 
cancelBgDexOptJob()1973     private int cancelBgDexOptJob() throws RemoteException {
1974         BackgroundDexOptService.getService().cancelBackgroundDexoptJob();
1975         getOutPrintWriter().println("Success");
1976         return 0;
1977     }
1978 
runDeleteDexOpt()1979     private int runDeleteDexOpt() throws RemoteException {
1980         PrintWriter pw = getOutPrintWriter();
1981         String packageName = getNextArg();
1982         if (TextUtils.isEmpty(packageName)) {
1983             pw.println("Error: no package name");
1984             return 1;
1985         }
1986         long freedBytes = LocalServices.getService(
1987                 PackageManagerInternal.class).deleteOatArtifactsOfPackage(packageName);
1988         if (freedBytes < 0) {
1989             pw.println("Error: delete failed");
1990             return 1;
1991         }
1992         pw.println("Success: freed " + freedBytes + " bytes");
1993         Slog.i(TAG, "delete-dexopt " + packageName + " ,freed " + freedBytes + " bytes");
1994         return 0;
1995     }
1996 
runDumpProfiles()1997     private int runDumpProfiles() throws RemoteException {
1998         final PrintWriter pw = getOutPrintWriter();
1999         boolean dumpClassesAndMethods = false;
2000 
2001         String opt;
2002         while ((opt = getNextOption()) != null) {
2003             switch (opt) {
2004                 case "--dump-classes-and-methods":
2005                     dumpClassesAndMethods = true;
2006                     break;
2007                 default:
2008                     pw.println("Error: Unknown option: " + opt);
2009                     return 1;
2010             }
2011         }
2012 
2013         String packageName = getNextArg();
2014         mInterface.dumpProfiles(packageName, dumpClassesAndMethods);
2015         return 0;
2016     }
2017 
runSnapshotProfile()2018     private int runSnapshotProfile() throws RemoteException {
2019         PrintWriter pw = getOutPrintWriter();
2020 
2021         // Parse the arguments
2022         final String packageName = getNextArg();
2023         final boolean isBootImage = "android".equals(packageName);
2024 
2025         String codePath = null;
2026         String opt;
2027         while ((opt = getNextArg()) != null) {
2028             switch (opt) {
2029                 case "--code-path":
2030                     if (isBootImage) {
2031                         pw.write("--code-path cannot be used for the boot image.");
2032                         return -1;
2033                     }
2034                     codePath = getNextArg();
2035                     break;
2036                 default:
2037                     pw.write("Unknown arg: " + opt);
2038                     return -1;
2039             }
2040         }
2041 
2042         // If no code path was explicitly requested, select the base code path.
2043         String baseCodePath = null;
2044         if (!isBootImage) {
2045             PackageInfo packageInfo = mInterface.getPackageInfo(packageName, /* flags */ 0,
2046                     /* userId */0);
2047             if (packageInfo == null) {
2048                 pw.write("Package not found " + packageName);
2049                 return -1;
2050             }
2051             baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
2052             if (codePath == null) {
2053                 codePath = baseCodePath;
2054             }
2055         }
2056 
2057         // Create the profile snapshot.
2058         final SnapshotRuntimeProfileCallback callback = new SnapshotRuntimeProfileCallback();
2059         // The calling package is needed to debug permission access.
2060         final String callingPackage = (Binder.getCallingUid() == Process.ROOT_UID)
2061                 ? "root" : "com.android.shell";
2062         final int profileType = isBootImage
2063                 ? ArtManager.PROFILE_BOOT_IMAGE : ArtManager.PROFILE_APPS;
2064         if (!mInterface.getArtManager().isRuntimeProfilingEnabled(profileType, callingPackage)) {
2065             pw.println("Error: Runtime profiling is not enabled");
2066             return -1;
2067         }
2068         mInterface.getArtManager().snapshotRuntimeProfile(profileType, packageName,
2069                 codePath, callback, callingPackage);
2070         if (!callback.waitTillDone()) {
2071             pw.println("Error: callback not called");
2072             return callback.mErrCode;
2073         }
2074 
2075         // Copy the snapshot profile to the output profile file.
2076         try (InputStream inStream = new AutoCloseInputStream(callback.mProfileReadFd)) {
2077             final String outputFileSuffix = isBootImage || Objects.equals(baseCodePath, codePath)
2078                     ? "" : ("-" + new File(codePath).getName());
2079             final String outputProfilePath =
2080                     ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + packageName + outputFileSuffix + ".prof";
2081             try (OutputStream outStream = new FileOutputStream(outputProfilePath)) {
2082                 Streams.copy(inStream, outStream);
2083             }
2084             // Give read permissions to the other group.
2085             Os.chmod(outputProfilePath, /*mode*/ 0644 );
2086         } catch (IOException | ErrnoException e) {
2087             pw.println("Error when reading the profile fd: " + e.getMessage());
2088             e.printStackTrace(pw);
2089             return -1;
2090         }
2091         return 0;
2092     }
2093 
getRemainingArgs()2094     private ArrayList<String> getRemainingArgs() {
2095         ArrayList<String> args = new ArrayList<>();
2096         String arg;
2097         while ((arg = getNextArg()) != null) {
2098             args.add(arg);
2099         }
2100         return args;
2101     }
2102 
2103     private static class SnapshotRuntimeProfileCallback
2104             extends ISnapshotRuntimeProfileCallback.Stub {
2105         private boolean mSuccess = false;
2106         private int mErrCode = -1;
2107         private ParcelFileDescriptor mProfileReadFd = null;
2108         private CountDownLatch mDoneSignal = new CountDownLatch(1);
2109 
2110         @Override
onSuccess(ParcelFileDescriptor profileReadFd)2111         public void onSuccess(ParcelFileDescriptor profileReadFd) {
2112             mSuccess = true;
2113             try {
2114                 // We need to dup the descriptor. We are in the same process as system server
2115                 // and we will be receiving the same object (which will be closed on the
2116                 // server side).
2117                 mProfileReadFd = profileReadFd.dup();
2118             } catch (IOException e) {
2119                 e.printStackTrace();
2120             }
2121             mDoneSignal.countDown();
2122         }
2123 
2124         @Override
onError(int errCode)2125         public void onError(int errCode) {
2126             mSuccess = false;
2127             mErrCode = errCode;
2128             mDoneSignal.countDown();
2129         }
2130 
waitTillDone()2131         boolean waitTillDone() {
2132             boolean done = false;
2133             try {
2134                 // The time-out is an arbitrary large value. Since this is a local call the result
2135                 // will come very fast.
2136                 done = mDoneSignal.await(10000000, TimeUnit.MILLISECONDS);
2137             } catch (InterruptedException ignored) {
2138             }
2139             return done && mSuccess;
2140         }
2141     }
2142 
runUninstall()2143     private int runUninstall() throws RemoteException {
2144         final PrintWriter pw = getOutPrintWriter();
2145         int flags = 0;
2146         int userId = UserHandle.USER_ALL;
2147         long versionCode = PackageManager.VERSION_CODE_HIGHEST;
2148 
2149         String opt;
2150         while ((opt = getNextOption()) != null) {
2151             switch (opt) {
2152                 case "-k":
2153                     flags |= PackageManager.DELETE_KEEP_DATA;
2154                     break;
2155                 case "--user":
2156                     userId = UserHandle.parseUserArg(getNextArgRequired());
2157                     break;
2158                 case "--versionCode":
2159                     versionCode = Long.parseLong(getNextArgRequired());
2160                     break;
2161                 default:
2162                     pw.println("Error: Unknown option: " + opt);
2163                     return 1;
2164             }
2165         }
2166 
2167         final String packageName = getNextArg();
2168         if (packageName == null) {
2169             pw.println("Error: package name not specified");
2170             return 1;
2171         }
2172 
2173         // if a split is specified, just remove it and not the whole package
2174         ArrayList<String> splitNames = getRemainingArgs();
2175         if (!splitNames.isEmpty()) {
2176             return runRemoveSplits(packageName, splitNames);
2177         }
2178 
2179         if (userId == UserHandle.USER_ALL) {
2180             flags |= PackageManager.DELETE_ALL_USERS;
2181         }
2182         final int translatedUserId =
2183                 translateUserId(userId, UserHandle.USER_SYSTEM, "runUninstall");
2184         final LocalIntentReceiver receiver = new LocalIntentReceiver();
2185         final PackageManagerInternal internal =
2186                 LocalServices.getService(PackageManagerInternal.class);
2187 
2188         if (internal.isApexPackage(packageName)) {
2189             internal.uninstallApex(
2190                     packageName, versionCode, translatedUserId, receiver.getIntentSender(), flags);
2191         } else {
2192             if ((flags & PackageManager.DELETE_ALL_USERS) == 0) {
2193                 final PackageInfo info = mInterface.getPackageInfo(packageName,
2194                         PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES, translatedUserId);
2195                 if (info == null) {
2196                     pw.println("Failure [not installed for " + translatedUserId + "]");
2197                     return 1;
2198                 }
2199                 final boolean isSystem =
2200                         (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
2201                 // If we are being asked to delete a system app for just one
2202                 // user set flag so it disables rather than reverting to system
2203                 // version of the app.
2204                 if (isSystem) {
2205                     flags |= PackageManager.DELETE_SYSTEM_APP;
2206                 }
2207             }
2208             mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
2209                             versionCode), null /*callerPackageName*/, flags,
2210                     receiver.getIntentSender(), translatedUserId);
2211         }
2212 
2213         final Intent result = receiver.getResult();
2214         final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
2215                 PackageInstaller.STATUS_FAILURE);
2216         if (status == PackageInstaller.STATUS_SUCCESS) {
2217             pw.println("Success");
2218             return 0;
2219         } else {
2220             pw.println("Failure ["
2221                     + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
2222             return 1;
2223         }
2224     }
2225 
runRemoveSplits(String packageName, Collection<String> splitNames)2226     private int runRemoveSplits(String packageName, Collection<String> splitNames)
2227             throws RemoteException {
2228         final PrintWriter pw = getOutPrintWriter();
2229         final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
2230         sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
2231         sessionParams.appPackageName = packageName;
2232         final int sessionId =
2233                 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
2234         boolean abandonSession = true;
2235         try {
2236             if (doRemoveSplits(sessionId, splitNames, false /*logSuccess*/)
2237                     != PackageInstaller.STATUS_SUCCESS) {
2238                 return 1;
2239             }
2240             if (doCommitSession(sessionId, false /*logSuccess*/)
2241                     != PackageInstaller.STATUS_SUCCESS) {
2242                 return 1;
2243             }
2244             abandonSession = false;
2245             pw.println("Success");
2246             return 0;
2247         } finally {
2248             if (abandonSession) {
2249                 try {
2250                     doAbandonSession(sessionId, false /*logSuccess*/);
2251                 } catch (Exception ignore) {
2252                 }
2253             }
2254         }
2255     }
2256 
2257     static class ClearDataObserver extends IPackageDataObserver.Stub {
2258         boolean finished;
2259         boolean result;
2260 
2261         @Override
onRemoveCompleted(String packageName, boolean succeeded)2262         public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
2263             synchronized (this) {
2264                 finished = true;
2265                 result = succeeded;
2266                 notifyAll();
2267             }
2268         }
2269     }
2270 
runClear()2271     private int runClear() throws RemoteException {
2272         final PrintWriter pw = getOutPrintWriter();
2273         int userId = UserHandle.USER_SYSTEM;
2274         boolean cacheOnly = false;
2275 
2276         String opt;
2277         while ((opt = getNextOption()) != null) {
2278             switch (opt) {
2279                 case "--user":
2280                     userId = UserHandle.parseUserArg(getNextArgRequired());
2281                     break;
2282                 case "--cache-only":
2283                     cacheOnly = true;
2284                     break;
2285                 default:
2286                     pw.println("Error: Unknown option: " + opt);
2287                     return 1;
2288             }
2289         }
2290 
2291         String pkg = getNextArg();
2292         if (pkg == null) {
2293             getErrPrintWriter().println("Error: no package specified");
2294             return 1;
2295         }
2296 
2297         final int translatedUserId =
2298                 translateUserId(userId, UserHandle.USER_NULL, "runClear");
2299         final ClearDataObserver obs = new ClearDataObserver();
2300         if (!cacheOnly) {
2301             ActivityManager.getService()
2302                     .clearApplicationUserData(pkg, false, obs, translatedUserId);
2303         } else {
2304             mInterface.deleteApplicationCacheFilesAsUser(pkg, translatedUserId, obs);
2305         }
2306         synchronized (obs) {
2307             while (!obs.finished) {
2308                 try {
2309                     obs.wait();
2310                 } catch (InterruptedException e) {
2311                 }
2312             }
2313         }
2314 
2315         if (obs.result) {
2316             getOutPrintWriter().println("Success");
2317             return 0;
2318         } else {
2319             getErrPrintWriter().println("Failed");
2320             return 1;
2321         }
2322     }
2323 
enabledSettingToString(int state)2324     private static String enabledSettingToString(int state) {
2325         switch (state) {
2326             case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
2327                 return "default";
2328             case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
2329                 return "enabled";
2330             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
2331                 return "disabled";
2332             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
2333                 return "disabled-user";
2334             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
2335                 return "disabled-until-used";
2336         }
2337         return "unknown";
2338     }
2339 
runSetEnabledSetting(int state)2340     private int runSetEnabledSetting(int state) throws RemoteException {
2341         int userId = UserHandle.USER_SYSTEM;
2342         String option = getNextOption();
2343         if (option != null && option.equals("--user")) {
2344             userId = UserHandle.parseUserArg(getNextArgRequired());
2345         }
2346 
2347         final String pkg = getNextArg();
2348         if (pkg == null) {
2349             getErrPrintWriter().println("Error: no package or component specified");
2350             return 1;
2351         }
2352         final int translatedUserId =
2353                 translateUserId(userId, UserHandle.USER_NULL, "runSetEnabledSetting");
2354         final ComponentName cn = ComponentName.unflattenFromString(pkg);
2355         if (cn == null) {
2356             mInterface.setApplicationEnabledSetting(pkg, state, 0, translatedUserId,
2357                     "shell:" + android.os.Process.myUid());
2358             getOutPrintWriter().println("Package " + pkg + " new state: "
2359                     + enabledSettingToString(
2360                     mInterface.getApplicationEnabledSetting(pkg, translatedUserId)));
2361             return 0;
2362         } else {
2363             mInterface.setComponentEnabledSetting(cn, state, 0, translatedUserId);
2364             getOutPrintWriter().println("Component " + cn.toShortString() + " new state: "
2365                     + enabledSettingToString(
2366                     mInterface.getComponentEnabledSetting(cn, translatedUserId)));
2367             return 0;
2368         }
2369     }
2370 
runSetHiddenSetting(boolean state)2371     private int runSetHiddenSetting(boolean state) throws RemoteException {
2372         int userId = UserHandle.USER_SYSTEM;
2373         String option = getNextOption();
2374         if (option != null && option.equals("--user")) {
2375             userId = UserHandle.parseUserArg(getNextArgRequired());
2376         }
2377 
2378         String pkg = getNextArg();
2379         if (pkg == null) {
2380             getErrPrintWriter().println("Error: no package or component specified");
2381             return 1;
2382         }
2383         final int translatedUserId =
2384                 translateUserId(userId, UserHandle.USER_NULL, "runSetHiddenSetting");
2385         mInterface.setApplicationHiddenSettingAsUser(pkg, state, translatedUserId);
2386         getOutPrintWriter().println("Package " + pkg + " new hidden state: "
2387                 + mInterface.getApplicationHiddenSettingAsUser(pkg, translatedUserId));
2388         return 0;
2389     }
2390 
runSetDistractingRestriction()2391     private int runSetDistractingRestriction() {
2392         final PrintWriter pw = getOutPrintWriter();
2393         int userId = UserHandle.USER_SYSTEM;
2394         String opt;
2395         int flags = 0;
2396         while ((opt = getNextOption()) != null) {
2397             switch (opt) {
2398                 case "--user":
2399                     userId = UserHandle.parseUserArg(getNextArgRequired());
2400                     break;
2401                 case "--flag":
2402                     final String flag = getNextArgRequired();
2403                     switch (flag) {
2404                         case "hide-notifications":
2405                             flags |= PackageManager.RESTRICTION_HIDE_NOTIFICATIONS;
2406                             break;
2407                         case "hide-from-suggestions":
2408                             flags |= PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
2409                             break;
2410                         default:
2411                             pw.println("Unrecognized flag: " + flag);
2412                             return 1;
2413                     }
2414                     break;
2415                 default:
2416                     pw.println("Error: Unknown option: " + opt);
2417                     return 1;
2418             }
2419         }
2420 
2421         final List<String> packageNames = getRemainingArgs();
2422         if (packageNames.isEmpty()) {
2423             pw.println("Error: package name not specified");
2424             return 1;
2425         }
2426         try {
2427             final int translatedUserId = translateUserId(userId, UserHandle.USER_NULL,
2428                     "set-distracting");
2429             final String[] errored = mInterface.setDistractingPackageRestrictionsAsUser(
2430                     packageNames.toArray(new String[]{}), flags, translatedUserId);
2431             if (errored.length > 0) {
2432                 pw.println("Could not set restriction for: " + Arrays.toString(errored));
2433                 return 1;
2434             }
2435             return 0;
2436         } catch (RemoteException | IllegalArgumentException e) {
2437             pw.println(e.toString());
2438             return 1;
2439         }
2440     }
2441 
runSuspend(boolean suspendedState)2442     private int runSuspend(boolean suspendedState) {
2443         final PrintWriter pw = getOutPrintWriter();
2444         int userId = UserHandle.USER_SYSTEM;
2445         String dialogMessage = null;
2446         final PersistableBundle appExtras = new PersistableBundle();
2447         final PersistableBundle launcherExtras = new PersistableBundle();
2448         String opt;
2449         while ((opt = getNextOption()) != null) {
2450             switch (opt) {
2451                 case "--user":
2452                     userId = UserHandle.parseUserArg(getNextArgRequired());
2453                     break;
2454                 case "--dialogMessage":
2455                     dialogMessage = getNextArgRequired();
2456                     break;
2457                 case "--ael":
2458                 case "--aes":
2459                 case "--aed":
2460                 case "--lel":
2461                 case "--les":
2462                 case "--led":
2463                     final String key = getNextArgRequired();
2464                     final String val = getNextArgRequired();
2465                     if (!suspendedState) {
2466                         break;
2467                     }
2468                     final PersistableBundle bundleToInsert =
2469                             opt.startsWith("--a") ? appExtras : launcherExtras;
2470                     switch (opt.charAt(4)) {
2471                         case 'l':
2472                             bundleToInsert.putLong(key, Long.valueOf(val));
2473                             break;
2474                         case 'd':
2475                             bundleToInsert.putDouble(key, Double.valueOf(val));
2476                             break;
2477                         case 's':
2478                             bundleToInsert.putString(key, val);
2479                             break;
2480                     }
2481                     break;
2482                 default:
2483                     pw.println("Error: Unknown option: " + opt);
2484                     return 1;
2485             }
2486         }
2487 
2488         final List<String> packageNames = getRemainingArgs();
2489         if (packageNames.isEmpty()) {
2490             pw.println("Error: package name not specified");
2491             return 1;
2492         }
2493         final String callingPackage =
2494                 (Binder.getCallingUid() == Process.ROOT_UID) ? "root" : "com.android.shell";
2495 
2496         final SuspendDialogInfo info;
2497         if (!TextUtils.isEmpty(dialogMessage)) {
2498             info = new SuspendDialogInfo.Builder()
2499                     .setMessage(dialogMessage)
2500                     .build();
2501         } else {
2502             info = null;
2503         }
2504         try {
2505             final int translatedUserId =
2506                     translateUserId(userId, UserHandle.USER_NULL, "runSuspend");
2507             mInterface.setPackagesSuspendedAsUser(packageNames.toArray(new String[] {}),
2508                     suspendedState, ((appExtras.size() > 0) ? appExtras : null),
2509                     ((launcherExtras.size() > 0) ? launcherExtras : null),
2510                     info, callingPackage, translatedUserId);
2511             for (int i = 0; i < packageNames.size(); i++) {
2512                 final String packageName = packageNames.get(i);
2513                 pw.println("Package " + packageName + " new suspended state: "
2514                         + mInterface.isPackageSuspendedForUser(packageName, translatedUserId));
2515             }
2516             return 0;
2517         } catch (RemoteException | IllegalArgumentException e) {
2518             pw.println(e.toString());
2519             return 1;
2520         }
2521     }
2522 
runGrantRevokePermission(boolean grant)2523     private int runGrantRevokePermission(boolean grant) throws RemoteException {
2524         int userId = UserHandle.USER_SYSTEM;
2525 
2526         String opt = null;
2527         while ((opt = getNextOption()) != null) {
2528             if (opt.equals("--user")) {
2529                 userId = UserHandle.parseUserArg(getNextArgRequired());
2530             }
2531         }
2532 
2533         String pkg = getNextArg();
2534         if (pkg == null) {
2535             getErrPrintWriter().println("Error: no package specified");
2536             return 1;
2537         }
2538         String perm = getNextArg();
2539         if (perm == null) {
2540             getErrPrintWriter().println("Error: no permission specified");
2541             return 1;
2542         }
2543         final UserHandle translatedUser = UserHandle.of(translateUserId(userId,
2544                 UserHandle.USER_NULL, "runGrantRevokePermission"));
2545         if (grant) {
2546             mPermissionManager.grantRuntimePermission(pkg, perm, translatedUser);
2547         } else {
2548             mPermissionManager.revokeRuntimePermission(pkg, perm, translatedUser, null);
2549         }
2550         return 0;
2551     }
2552 
runResetPermissions()2553     private int runResetPermissions() throws RemoteException {
2554         mLegacyPermissionManager.resetRuntimePermissions();
2555         return 0;
2556     }
2557 
setOrClearPermissionFlags(boolean setFlags)2558     private int setOrClearPermissionFlags(boolean setFlags) {
2559         int userId = UserHandle.USER_SYSTEM;
2560 
2561         String opt;
2562         while ((opt = getNextOption()) != null) {
2563             if (opt.equals("--user")) {
2564                 userId = UserHandle.parseUserArg(getNextArgRequired());
2565             }
2566         }
2567 
2568         String pkg = getNextArg();
2569         if (pkg == null) {
2570             getErrPrintWriter().println("Error: no package specified");
2571             return 1;
2572         }
2573         String perm = getNextArg();
2574         if (perm == null) {
2575             getErrPrintWriter().println("Error: no permission specified");
2576             return 1;
2577         }
2578 
2579         int flagMask = 0;
2580         String flagName = getNextArg();
2581         if (flagName == null) {
2582             getErrPrintWriter().println("Error: no permission flags specified");
2583             return 1;
2584         }
2585         while (flagName != null) {
2586             if (!SUPPORTED_PERMISSION_FLAGS.containsKey(flagName)) {
2587                 getErrPrintWriter().println("Error: specified flag " + flagName + " is not one of "
2588                         + SUPPORTED_PERMISSION_FLAGS_LIST);
2589                 return 1;
2590             }
2591             flagMask |= SUPPORTED_PERMISSION_FLAGS.get(flagName);
2592             flagName = getNextArg();
2593         }
2594 
2595         final UserHandle translatedUser = UserHandle.of(translateUserId(userId,
2596                 UserHandle.USER_NULL, "runGrantRevokePermission"));
2597         int flagSet = setFlags ? flagMask : 0;
2598         mPermissionManager.updatePermissionFlags(pkg, perm, flagMask, flagSet, translatedUser);
2599         return 0;
2600     }
2601 
runSetPermissionEnforced()2602     private int runSetPermissionEnforced() throws RemoteException {
2603         final String permission = getNextArg();
2604         if (permission == null) {
2605             getErrPrintWriter().println("Error: no permission specified");
2606             return 1;
2607         }
2608         final String enforcedRaw = getNextArg();
2609         if (enforcedRaw == null) {
2610             getErrPrintWriter().println("Error: no enforcement specified");
2611             return 1;
2612         }
2613         // Permissions are always enforced now.
2614         return 0;
2615     }
2616 
isVendorApp(String pkg)2617     private boolean isVendorApp(String pkg) {
2618         try {
2619             final PackageInfo info = mInterface.getPackageInfo(
2620                      pkg, PackageManager.MATCH_ANY_USER, UserHandle.USER_SYSTEM);
2621             return info != null && info.applicationInfo.isVendor();
2622         } catch (RemoteException e) {
2623             return false;
2624         }
2625     }
2626 
isProductApp(String pkg)2627     private boolean isProductApp(String pkg) {
2628         try {
2629             final PackageInfo info = mInterface.getPackageInfo(
2630                     pkg, PackageManager.MATCH_ANY_USER, UserHandle.USER_SYSTEM);
2631             return info != null && info.applicationInfo.isProduct();
2632         } catch (RemoteException e) {
2633             return false;
2634         }
2635     }
2636 
isSystemExtApp(String pkg)2637     private boolean isSystemExtApp(String pkg) {
2638         try {
2639             final PackageInfo info = mInterface.getPackageInfo(
2640                     pkg, PackageManager.MATCH_ANY_USER, UserHandle.USER_SYSTEM);
2641             return info != null && info.applicationInfo.isSystemExt();
2642         } catch (RemoteException e) {
2643             return false;
2644         }
2645     }
2646 
getApexPackageNameContainingPackage(String pkg)2647     private String getApexPackageNameContainingPackage(String pkg) {
2648         ApexManager apexManager = ApexManager.getInstance();
2649         return apexManager.getActiveApexPackageNameContainingPackage(pkg);
2650     }
2651 
isApexApp(String pkg)2652     private boolean isApexApp(String pkg) {
2653         return getApexPackageNameContainingPackage(pkg) != null;
2654     }
2655 
runGetPrivappPermissions()2656     private int runGetPrivappPermissions() {
2657         final String pkg = getNextArg();
2658         if (pkg == null) {
2659             getErrPrintWriter().println("Error: no package specified.");
2660             return 1;
2661         }
2662 
2663         ArraySet<String> privAppPermissions = null;
2664         if (isVendorApp(pkg)) {
2665             privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
2666         } else if (isProductApp(pkg)) {
2667             privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
2668         } else if (isSystemExtApp(pkg)) {
2669             privAppPermissions = SystemConfig.getInstance()
2670                     .getSystemExtPrivAppPermissions(pkg);
2671         } else if (isApexApp(pkg)) {
2672             final String apexName = ApexManager.getInstance().getApexModuleNameForPackageName(
2673                     getApexPackageNameContainingPackage(pkg));
2674             privAppPermissions = SystemConfig.getInstance()
2675                     .getApexPrivAppPermissions(apexName, pkg);
2676         } else {
2677             privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
2678         }
2679 
2680         getOutPrintWriter().println(privAppPermissions == null
2681                 ? "{}" : privAppPermissions.toString());
2682         return 0;
2683     }
2684 
runGetPrivappDenyPermissions()2685     private int runGetPrivappDenyPermissions() {
2686         final String pkg = getNextArg();
2687         if (pkg == null) {
2688             getErrPrintWriter().println("Error: no package specified.");
2689             return 1;
2690         }
2691 
2692         ArraySet<String> privAppPermissions = null;
2693         if (isVendorApp(pkg)) {
2694             privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
2695         } else if (isProductApp(pkg)) {
2696             privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
2697         } else if (isSystemExtApp(pkg)) {
2698             privAppPermissions = SystemConfig.getInstance()
2699                     .getSystemExtPrivAppDenyPermissions(pkg);
2700         } else if (isApexApp(pkg)) {
2701             final String apexName = ApexManager.getInstance().getApexModuleNameForPackageName(
2702                     getApexPackageNameContainingPackage(pkg));
2703             privAppPermissions = SystemConfig.getInstance()
2704                     .getApexPrivAppDenyPermissions(apexName, pkg);
2705         } else {
2706             privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
2707         }
2708 
2709         getOutPrintWriter().println(privAppPermissions == null
2710                 ? "{}" : privAppPermissions.toString());
2711         return 0;
2712     }
2713 
runGetOemPermissions()2714     private int runGetOemPermissions() {
2715         final String pkg = getNextArg();
2716         if (pkg == null) {
2717             getErrPrintWriter().println("Error: no package specified.");
2718             return 1;
2719         }
2720         final Map<String, Boolean> oemPermissions = SystemConfig.getInstance()
2721                 .getOemPermissions(pkg);
2722         if (oemPermissions == null || oemPermissions.isEmpty()) {
2723             getOutPrintWriter().println("{}");
2724         } else {
2725             oemPermissions.forEach((permission, granted) ->
2726                     getOutPrintWriter().println(permission + " granted:" + granted)
2727             );
2728         }
2729         return 0;
2730     }
2731 
runTrimCaches()2732     private int runTrimCaches() throws RemoteException {
2733         String size = getNextArg();
2734         if (size == null) {
2735             getErrPrintWriter().println("Error: no size specified");
2736             return 1;
2737         }
2738         long multiplier = 1;
2739         int len = size.length();
2740         char c = size.charAt(len - 1);
2741         if (c < '0' || c > '9') {
2742             if (c == 'K' || c == 'k') {
2743                 multiplier = 1024L;
2744             } else if (c == 'M' || c == 'm') {
2745                 multiplier = 1024L*1024L;
2746             } else if (c == 'G' || c == 'g') {
2747                 multiplier = 1024L*1024L*1024L;
2748             } else {
2749                 getErrPrintWriter().println("Invalid suffix: " + c);
2750                 return 1;
2751             }
2752             size = size.substring(0, len-1);
2753         }
2754         long sizeVal;
2755         try {
2756             sizeVal = Long.parseLong(size) * multiplier;
2757         } catch (NumberFormatException e) {
2758             getErrPrintWriter().println("Error: expected number at: " + size);
2759             return 1;
2760         }
2761         String volumeUuid = getNextArg();
2762         if ("internal".equals(volumeUuid)) {
2763             volumeUuid = null;
2764         }
2765         ClearDataObserver obs = new ClearDataObserver();
2766         mInterface.freeStorageAndNotify(volumeUuid, sizeVal,
2767                 StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs);
2768         synchronized (obs) {
2769             while (!obs.finished) {
2770                 try {
2771                     obs.wait();
2772                 } catch (InterruptedException e) {
2773                 }
2774             }
2775         }
2776         return 0;
2777     }
2778 
isNumber(String s)2779     private static boolean isNumber(String s) {
2780         try {
2781             Integer.parseInt(s);
2782         } catch (NumberFormatException nfe) {
2783             return false;
2784         }
2785         return true;
2786     }
2787 
runCreateUser()2788     public int runCreateUser() throws RemoteException {
2789         String name;
2790         int userId = -1;
2791         int flags = 0;
2792         String userType = null;
2793         String opt;
2794         boolean preCreateOnly = false;
2795         while ((opt = getNextOption()) != null) {
2796             String newUserType = null;
2797             if ("--profileOf".equals(opt)) {
2798                 userId = translateUserId(UserHandle.parseUserArg(getNextArgRequired()),
2799                             UserHandle.USER_ALL, "runCreateUser");
2800             } else if ("--managed".equals(opt)) {
2801                 newUserType = UserManager.USER_TYPE_PROFILE_MANAGED;
2802             } else if ("--restricted".equals(opt)) {
2803                 newUserType = UserManager.USER_TYPE_FULL_RESTRICTED;
2804             } else if ("--guest".equals(opt)) {
2805                 newUserType = UserManager.USER_TYPE_FULL_GUEST;
2806             } else if ("--demo".equals(opt)) {
2807                 newUserType = UserManager.USER_TYPE_FULL_DEMO;
2808             } else if ("--ephemeral".equals(opt)) {
2809                 flags |= UserInfo.FLAG_EPHEMERAL;
2810             } else if ("--pre-create-only".equals(opt)) {
2811                 preCreateOnly = true;
2812             } else if ("--user-type".equals(opt)) {
2813                 newUserType = getNextArgRequired();
2814             } else {
2815                 getErrPrintWriter().println("Error: unknown option " + opt);
2816                 return 1;
2817             }
2818             // Ensure only one user-type was specified.
2819             if (newUserType != null) {
2820                 if (userType != null && !userType.equals(newUserType)) {
2821                     getErrPrintWriter().println("Error: more than one user type was specified ("
2822                             + userType + " and " + newUserType + ")");
2823                     return 1;
2824                 }
2825                 userType = newUserType;
2826             }
2827         }
2828         String arg = getNextArg();
2829         if (arg == null && !preCreateOnly) {
2830             getErrPrintWriter().println("Error: no user name specified.");
2831             return 1;
2832         }
2833         if (arg != null && preCreateOnly) {
2834             getErrPrintWriter().println("Warning: name is ignored for pre-created users");
2835         }
2836 
2837         name = arg;
2838         UserInfo info = null;
2839         IUserManager um = IUserManager.Stub.asInterface(
2840                 ServiceManager.getService(Context.USER_SERVICE));
2841         IAccountManager accm = IAccountManager.Stub.asInterface(
2842                 ServiceManager.getService(Context.ACCOUNT_SERVICE));
2843         if (userType == null) {
2844             userType = UserInfo.getDefaultUserType(flags);
2845         }
2846         Trace.traceBegin(Trace.TRACE_TAG_PACKAGE_MANAGER, "shell_runCreateUser");
2847         try {
2848             if (UserManager.isUserTypeRestricted(userType)) {
2849                 // In non-split user mode, userId can only be SYSTEM
2850                 int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
2851                 info = um.createRestrictedProfileWithThrow(name, parentUserId);
2852                 accm.addSharedAccountsFromParentUser(parentUserId, userId,
2853                         (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
2854             } else if (userId < 0) {
2855                 info = preCreateOnly ?
2856                         um.preCreateUserWithThrow(userType) :
2857                         um.createUserWithThrow(name, userType, flags);
2858             } else {
2859                 info = um.createProfileForUserWithThrow(name, userType, flags, userId, null);
2860             }
2861         } catch (ServiceSpecificException e) {
2862             getErrPrintWriter().println("Error: " + e);
2863         } finally {
2864             Trace.traceEnd(Trace.TRACE_TAG_PACKAGE_MANAGER);
2865         }
2866 
2867         if (info != null) {
2868             getOutPrintWriter().println("Success: created user id " + info.id);
2869             return 0;
2870         } else {
2871             getErrPrintWriter().println("Error: couldn't create User.");
2872             return 1;
2873         }
2874     }
2875 
2876     // pm remove-user [--set-ephemeral-if-in-use][--wait] USER_ID
runRemoveUser()2877     public int runRemoveUser() throws RemoteException {
2878         int userId;
2879         String arg;
2880         boolean setEphemeralIfInUse = false;
2881         boolean wait = false;
2882 
2883         while ((arg = getNextOption()) != null) {
2884             switch (arg) {
2885                 case "--set-ephemeral-if-in-use":
2886                     setEphemeralIfInUse = true;
2887                     break;
2888                 case "--wait": // fallthrough
2889                 case "-w":
2890                     wait = true;
2891                     break;
2892                 default:
2893                     getErrPrintWriter().println("Error: unknown option: " + arg);
2894                     return -1;
2895             }
2896         }
2897 
2898         arg = getNextArg();
2899         if (arg == null) {
2900             getErrPrintWriter().println("Error: no user id specified.");
2901             return 1;
2902         }
2903         userId = UserHandle.parseUserArg(arg);
2904         IUserManager um = IUserManager.Stub.asInterface(
2905                 ServiceManager.getService(Context.USER_SERVICE));
2906         if (setEphemeralIfInUse) {
2907             return removeUserWhenPossible(um, userId);
2908         } else {
2909             final boolean success = wait ? removeUserAndWait(um, userId) : removeUser(um, userId);
2910             if (success) {
2911                 getOutPrintWriter().println("Success: removed user");
2912                 return 0;
2913             } else {
2914                 // Error message should already have been printed.
2915                 return 1;
2916             }
2917         }
2918     }
2919 
removeUser(IUserManager um, @UserIdInt int userId)2920     private boolean removeUser(IUserManager um, @UserIdInt int userId) throws RemoteException {
2921         Slog.i(TAG, "Removing user " + userId);
2922         if (um.removeUser(userId)) {
2923             return true;
2924         } else {
2925             getErrPrintWriter().println("Error: couldn't remove user id " + userId);
2926             return false;
2927         }
2928     }
2929 
removeUserAndWait(IUserManager um, @UserIdInt int userId)2930     private boolean removeUserAndWait(IUserManager um, @UserIdInt int userId)
2931             throws RemoteException {
2932         Slog.i(TAG, "Removing (and waiting for completion) user " + userId);
2933 
2934         final CountDownLatch waitLatch = new CountDownLatch(1);
2935         final UserManagerInternal.UserLifecycleListener listener =
2936                 new UserManagerInternal.UserLifecycleListener() {
2937                     @Override
2938                     public void onUserRemoved(UserInfo user) {
2939                         if (userId == user.id) {
2940                             waitLatch.countDown();
2941                         }
2942                     }
2943                 };
2944 
2945         final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
2946         umi.addUserLifecycleListener(listener);
2947 
2948         try {
2949             if (um.removeUser(userId)) {
2950                 final boolean awaitSuccess = waitLatch.await(10, TimeUnit.MINUTES);
2951                 if (!awaitSuccess) {
2952                     getErrPrintWriter().printf("Error: Remove user %d timed out\n", userId);
2953                     return false;
2954                 }
2955                 // Success!
2956                 return true;
2957             } else {
2958                 getErrPrintWriter().println("Error: couldn't remove user id " + userId);
2959                 return false;
2960             }
2961         } catch (InterruptedException e) {
2962             getErrPrintWriter().printf("Error: Remove user %d wait interrupted: %s\n", userId, e);
2963             Thread.currentThread().interrupt();
2964             return false;
2965         } finally {
2966             umi.removeUserLifecycleListener(listener);
2967         }
2968     }
2969 
removeUserWhenPossible(IUserManager um, @UserIdInt int userId)2970     private int removeUserWhenPossible(IUserManager um, @UserIdInt int userId)
2971             throws RemoteException {
2972         Slog.i(TAG, "Removing " + userId + " or set as ephemeral if in use.");
2973         int result = um.removeUserWhenPossible(userId, /* overrideDevicePolicy= */ false);
2974         switch (result) {
2975             case UserManager.REMOVE_RESULT_REMOVED:
2976                 getOutPrintWriter().printf("Success: user %d removed\n", userId);
2977                 return 0;
2978             case UserManager.REMOVE_RESULT_DEFERRED:
2979                 getOutPrintWriter().printf("Success: user %d set as ephemeral\n", userId);
2980                 return 0;
2981             case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED:
2982                 getOutPrintWriter().printf("Success: user %d is already being removed\n", userId);
2983                 return 0;
2984             default:
2985                 getErrPrintWriter().printf("Error: couldn't remove or mark ephemeral user id %d\n",
2986                         userId);
2987                 return 1;
2988         }
2989     }
2990 
runSetUserRestriction()2991     public int runSetUserRestriction() throws RemoteException {
2992         int userId = UserHandle.USER_SYSTEM;
2993         String opt = getNextOption();
2994         if (opt != null && "--user".equals(opt)) {
2995             userId = UserHandle.parseUserArg(getNextArgRequired());
2996         }
2997 
2998         String restriction = getNextArg();
2999         String arg = getNextArg();
3000         boolean value;
3001         if ("1".equals(arg)) {
3002             value = true;
3003         } else if ("0".equals(arg)) {
3004             value = false;
3005         } else {
3006             getErrPrintWriter().println("Error: valid value not specified");
3007             return 1;
3008         }
3009         final int translatedUserId =
3010                 translateUserId(userId, UserHandle.USER_NULL, "runSetUserRestriction");
3011         final IUserManager um = IUserManager.Stub.asInterface(
3012                 ServiceManager.getService(Context.USER_SERVICE));
3013         um.setUserRestriction(restriction, value, translatedUserId);
3014         return 0;
3015     }
3016 
runGetMaxUsers()3017     public int runGetMaxUsers() {
3018         getOutPrintWriter().println("Maximum supported users: "
3019                 + UserManager.getMaxSupportedUsers());
3020         return 0;
3021     }
3022 
runGetMaxRunningUsers()3023     public int runGetMaxRunningUsers() {
3024         ActivityManagerInternal activityManagerInternal =
3025                 LocalServices.getService(ActivityManagerInternal.class);
3026         getOutPrintWriter().println("Maximum supported running users: "
3027                 + activityManagerInternal.getMaxRunningUsers());
3028         return 0;
3029     }
3030 
3031     private static class InstallParams {
3032         SessionParams sessionParams;
3033         String installerPackageName;
3034         int userId = UserHandle.USER_ALL;
3035         long stagedReadyTimeoutMs = DEFAULT_STAGED_READY_TIMEOUT_MS;
3036     }
3037 
makeInstallParams(Set<String> unsupportedOptions)3038     private InstallParams makeInstallParams(Set<String> unsupportedOptions) {
3039         final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
3040         final InstallParams params = new InstallParams();
3041 
3042         params.sessionParams = sessionParams;
3043         // Allowlist all permissions by default
3044         sessionParams.installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
3045         // Set package source to other by default
3046         sessionParams.setPackageSource(PackageInstaller.PACKAGE_SOURCE_OTHER);
3047 
3048         String opt;
3049         boolean replaceExisting = true;
3050         boolean forceNonStaged = false;
3051         while ((opt = getNextOption()) != null) {
3052             if (unsupportedOptions.contains(opt)) {
3053                 throw new IllegalArgumentException("Unsupported option " + opt);
3054             }
3055             switch (opt) {
3056                 case "-r": // ignore
3057                     break;
3058                 case "-R":
3059                     replaceExisting = false;
3060                     break;
3061                 case "-i":
3062                     params.installerPackageName = getNextArg();
3063                     if (params.installerPackageName == null) {
3064                         throw new IllegalArgumentException("Missing installer package");
3065                     }
3066                     break;
3067                 case "-t":
3068                     sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
3069                     break;
3070                 case "-f":
3071                     sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
3072                     break;
3073                 case "-d":
3074                     sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
3075                     break;
3076                 case "-g":
3077                     sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
3078                     break;
3079                 case "--restrict-permissions":
3080                     sessionParams.installFlags &=
3081                             ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
3082                     break;
3083                 case "--dont-kill":
3084                     sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
3085                     break;
3086                 case "--originating-uri":
3087                     sessionParams.originatingUri = Uri.parse(getNextArg());
3088                     break;
3089                 case "--referrer":
3090                     sessionParams.referrerUri = Uri.parse(getNextArg());
3091                     break;
3092                 case "-p":
3093                     sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
3094                     sessionParams.appPackageName = getNextArg();
3095                     if (sessionParams.appPackageName == null) {
3096                         throw new IllegalArgumentException("Missing inherit package name");
3097                     }
3098                     break;
3099                 case "--pkg":
3100                     sessionParams.appPackageName = getNextArg();
3101                     if (sessionParams.appPackageName == null) {
3102                         throw new IllegalArgumentException("Missing package name");
3103                     }
3104                     break;
3105                 case "-S":
3106                     final long sizeBytes = Long.parseLong(getNextArg());
3107                     if (sizeBytes <= 0) {
3108                         throw new IllegalArgumentException("Size must be positive");
3109                     }
3110                     sessionParams.setSize(sizeBytes);
3111                     break;
3112                 case "--abi":
3113                     sessionParams.abiOverride = checkAbiArgument(getNextArg());
3114                     break;
3115                 case "--ephemeral":
3116                 case "--instant":
3117                 case "--instantapp":
3118                     sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
3119                     break;
3120                 case "--full":
3121                     sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
3122                     break;
3123                 case "--preload":
3124                     sessionParams.setInstallAsVirtualPreload();
3125                     break;
3126                 case "--user":
3127                     params.userId = UserHandle.parseUserArg(getNextArgRequired());
3128                     break;
3129                 case "--install-location":
3130                     sessionParams.installLocation = Integer.parseInt(getNextArg());
3131                     break;
3132                 case "--install-reason":
3133                     sessionParams.installReason = Integer.parseInt(getNextArg());
3134                     break;
3135                 case "--force-uuid":
3136                     sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
3137                     sessionParams.volumeUuid = getNextArg();
3138                     if ("internal".equals(sessionParams.volumeUuid)) {
3139                         sessionParams.volumeUuid = null;
3140                     }
3141                     break;
3142                 case "--force-sdk": // ignore
3143                     break;
3144                 case "--apex":
3145                     sessionParams.setInstallAsApex();
3146                     sessionParams.setStaged();
3147                     break;
3148                 case "--force-non-staged":
3149                     forceNonStaged = true;
3150                     break;
3151                 case "--multi-package":
3152                     sessionParams.setMultiPackage();
3153                     break;
3154                 case "--staged":
3155                     sessionParams.setStaged();
3156                     break;
3157                 case "--force-queryable":
3158                     sessionParams.setForceQueryable();
3159                     break;
3160                 case "--enable-rollback":
3161                     if (params.installerPackageName == null) {
3162                         // com.android.shell has the TEST_MANAGE_ROLLBACKS
3163                         // permission needed to enable rollback for non-module
3164                         // packages, which is likely what the user wants when
3165                         // enabling rollback through the shell command. Set
3166                         // the installer to com.android.shell if no installer
3167                         // has been provided so that the user doesn't have to
3168                         // remember to set it themselves.
3169                         params.installerPackageName = "com.android.shell";
3170                     }
3171                     sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
3172                     break;
3173                 case "--staged-ready-timeout":
3174                     params.stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired());
3175                     break;
3176                 case "--skip-verification":
3177                     sessionParams.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;
3178                     break;
3179                 default:
3180                     throw new IllegalArgumentException("Unknown option " + opt);
3181             }
3182         }
3183         if (replaceExisting) {
3184             sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
3185         }
3186         if (forceNonStaged) {
3187             sessionParams.isStaged = false;
3188         }
3189         return params;
3190     }
3191 
runSetHomeActivity()3192     private int runSetHomeActivity() {
3193         final PrintWriter pw = getOutPrintWriter();
3194         int userId = UserHandle.USER_SYSTEM;
3195         String opt;
3196         while ((opt = getNextOption()) != null) {
3197             switch (opt) {
3198                 case "--user":
3199                     userId = UserHandle.parseUserArg(getNextArgRequired());
3200                     break;
3201                 default:
3202                     pw.println("Error: Unknown option: " + opt);
3203                     return 1;
3204             }
3205         }
3206 
3207         String pkgName;
3208         String component = getNextArg();
3209         if (component.indexOf('/') < 0) {
3210             // No component specified, so assume it's just a package name.
3211             pkgName = component;
3212         } else {
3213             ComponentName componentName =
3214                     component != null ? ComponentName.unflattenFromString(component) : null;
3215             if (componentName == null) {
3216                 pw.println("Error: invalid component name");
3217                 return 1;
3218             }
3219             pkgName = componentName.getPackageName();
3220         }
3221         final int translatedUserId =
3222                 translateUserId(userId, UserHandle.USER_NULL, "runSetHomeActivity");
3223         final CompletableFuture<Boolean> future = new CompletableFuture<>();
3224         try {
3225             RoleManager roleManager = mContext.getSystemService(RoleManager.class);
3226             roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName, 0,
3227                     UserHandle.of(translatedUserId), FgThread.getExecutor(), future::complete);
3228             boolean success = future.get();
3229             if (success) {
3230                 pw.println("Success");
3231                 return 0;
3232             } else {
3233                 pw.println("Error: Failed to set default home.");
3234                 return 1;
3235             }
3236         } catch (Exception e) {
3237             pw.println(e.toString());
3238             return 1;
3239         }
3240     }
3241 
runSetInstaller()3242     private int runSetInstaller() throws RemoteException {
3243         final String targetPackage = getNextArg();
3244         final String installerPackageName = getNextArg();
3245 
3246         if (targetPackage == null || installerPackageName == null) {
3247             getErrPrintWriter().println("Must provide both target and installer package names");
3248             return 1;
3249         }
3250 
3251         mInterface.setInstallerPackageName(targetPackage, installerPackageName);
3252         getOutPrintWriter().println("Success");
3253         return 0;
3254     }
3255 
runGetInstantAppResolver()3256     private int runGetInstantAppResolver() {
3257         final PrintWriter pw = getOutPrintWriter();
3258         try {
3259             final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent();
3260             if (instantAppsResolver == null) {
3261                 return 1;
3262             }
3263             pw.println(instantAppsResolver.flattenToString());
3264             return 0;
3265         } catch (Exception e) {
3266             pw.println(e.toString());
3267             return 1;
3268         }
3269     }
3270 
runHasFeature()3271     private int runHasFeature() {
3272         final PrintWriter err = getErrPrintWriter();
3273         final String featureName = getNextArg();
3274         if (featureName == null) {
3275             err.println("Error: expected FEATURE name");
3276             return 1;
3277         }
3278         final String versionString = getNextArg();
3279         try {
3280             final int version = (versionString == null) ? 0 : Integer.parseInt(versionString);
3281             final boolean hasFeature = mInterface.hasSystemFeature(featureName, version);
3282             getOutPrintWriter().println(hasFeature);
3283             return hasFeature ? 0 : 1;
3284         } catch (NumberFormatException e) {
3285             err.println("Error: illegal version number " + versionString);
3286             return 1;
3287         } catch (RemoteException e) {
3288             err.println(e.toString());
3289             return 1;
3290         }
3291     }
3292 
runDump()3293     private int runDump() {
3294         String pkg = getNextArg();
3295         if (pkg == null) {
3296             getErrPrintWriter().println("Error: no package specified");
3297             return 1;
3298         }
3299         ActivityManager.dumpPackageStateStatic(getOutFileDescriptor(), pkg);
3300         return 0;
3301     }
3302 
runSetHarmfulAppWarning()3303     private int runSetHarmfulAppWarning() throws RemoteException {
3304         int userId = UserHandle.USER_CURRENT;
3305 
3306         String opt;
3307         while ((opt = getNextOption()) != null) {
3308             if (opt.equals("--user")) {
3309                 userId = UserHandle.parseUserArg(getNextArgRequired());
3310             } else {
3311                 getErrPrintWriter().println("Error: Unknown option: " + opt);
3312                 return -1;
3313             }
3314         }
3315 
3316         final int translatedUserId =
3317                 translateUserId(userId, UserHandle.USER_NULL, "runSetHarmfulAppWarning");
3318         final String packageName = getNextArgRequired();
3319         final String warning = getNextArg();
3320 
3321         mInterface.setHarmfulAppWarning(packageName, warning, translatedUserId);
3322 
3323         return 0;
3324     }
3325 
runGetHarmfulAppWarning()3326     private int runGetHarmfulAppWarning() throws RemoteException {
3327         int userId = UserHandle.USER_CURRENT;
3328 
3329         String opt;
3330         while ((opt = getNextOption()) != null) {
3331             if (opt.equals("--user")) {
3332                 userId = UserHandle.parseUserArg(getNextArgRequired());
3333             } else {
3334                 getErrPrintWriter().println("Error: Unknown option: " + opt);
3335                 return -1;
3336             }
3337         }
3338 
3339         final int translatedUserId =
3340                 translateUserId(userId, UserHandle.USER_NULL, "runGetHarmfulAppWarning");
3341         final String packageName = getNextArgRequired();
3342         final CharSequence warning = mInterface.getHarmfulAppWarning(packageName, translatedUserId);
3343         if (!TextUtils.isEmpty(warning)) {
3344             getOutPrintWriter().println(warning);
3345             return 0;
3346         } else {
3347             return 1;
3348         }
3349     }
3350 
runSetSilentUpdatesPolicy()3351     private int runSetSilentUpdatesPolicy() {
3352         final PrintWriter pw = getOutPrintWriter();
3353         String opt;
3354         String installerPackageName = null;
3355         Long throttleTimeInSeconds = null;
3356         boolean reset = false;
3357         while ((opt = getNextOption()) != null) {
3358             switch (opt) {
3359                 case "--allow-unlimited-silent-updates":
3360                     installerPackageName = getNextArgRequired();
3361                     break;
3362                 case "--throttle-time":
3363                     throttleTimeInSeconds = Long.parseLong(getNextArgRequired());
3364                     break;
3365                 case "--reset":
3366                     reset = true;
3367                     break;
3368                 default:
3369                     pw.println("Error: Unknown option: " + opt);
3370                     return -1;
3371             }
3372         }
3373         if (throttleTimeInSeconds != null && throttleTimeInSeconds < 0) {
3374             pw.println("Error: Invalid value for \"--throttle-time\":" + throttleTimeInSeconds);
3375             return -1;
3376         }
3377 
3378         try {
3379             final IPackageInstaller installer = mInterface.getPackageInstaller();
3380             if (reset) {
3381                 installer.setAllowUnlimitedSilentUpdates(null /* installerPackageName */);
3382                 installer.setSilentUpdatesThrottleTime(-1 /* restore to the default */);
3383             } else {
3384                 if (installerPackageName != null) {
3385                     installer.setAllowUnlimitedSilentUpdates(installerPackageName);
3386                 }
3387                 if (throttleTimeInSeconds != null) {
3388                     installer.setSilentUpdatesThrottleTime(throttleTimeInSeconds);
3389                 }
3390             }
3391         } catch (RemoteException e) {
3392             pw.println("Failure ["
3393                     + e.getClass().getName() + " - "
3394                     + e.getMessage() + "]");
3395             return -1;
3396         }
3397         return 1;
3398     }
3399 
checkAbiArgument(String abi)3400     private static String checkAbiArgument(String abi) {
3401         if (TextUtils.isEmpty(abi)) {
3402             throw new IllegalArgumentException("Missing ABI argument");
3403         }
3404 
3405         if ("-".equals(abi)) {
3406             return abi;
3407         }
3408 
3409         final String[] supportedAbis = Build.SUPPORTED_ABIS;
3410         for (String supportedAbi : supportedAbis) {
3411             if (supportedAbi.equals(abi)) {
3412                 return abi;
3413             }
3414         }
3415 
3416         throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
3417     }
3418 
translateUserId(int userId, int allUserId, String logContext)3419     private int translateUserId(int userId, int allUserId, String logContext) {
3420         final boolean allowAll = (allUserId != UserHandle.USER_NULL);
3421         final int translatedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
3422                 Binder.getCallingUid(), userId, allowAll, true, logContext, "pm command");
3423         return translatedUserId == UserHandle.USER_ALL ? allUserId : translatedUserId;
3424     }
3425 
doCreateSession(SessionParams params, String installerPackageName, int userId)3426     private int doCreateSession(SessionParams params, String installerPackageName, int userId)
3427             throws RemoteException {
3428         if (userId == UserHandle.USER_ALL) {
3429             params.installFlags |= PackageManager.INSTALL_ALL_USERS;
3430         }
3431         final int translatedUserId =
3432                 translateUserId(userId, UserHandle.USER_SYSTEM, "doCreateSession");
3433         final int sessionId = mInterface.getPackageInstaller()
3434                 .createSession(params, installerPackageName, null /*installerAttributionTag*/,
3435                         translatedUserId);
3436         return sessionId;
3437     }
3438 
doAddFiles(int sessionId, ArrayList<String> args, long sessionSizeBytes, boolean isApex)3439     private int doAddFiles(int sessionId, ArrayList<String> args, long sessionSizeBytes,
3440             boolean isApex) throws RemoteException {
3441         PackageInstaller.Session session = null;
3442         try {
3443             session = new PackageInstaller.Session(
3444                     mInterface.getPackageInstaller().openSession(sessionId));
3445 
3446             // 1. Single file from stdin.
3447             if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) {
3448                 final String name = "base" + RANDOM.nextInt() + "." + (isApex ? "apex" : "apk");
3449                 final Metadata metadata = Metadata.forStdIn(name);
3450                 session.addFile(LOCATION_DATA_APP, name, sessionSizeBytes,
3451                         metadata.toByteArray(), null);
3452                 return 0;
3453             }
3454 
3455             for (String arg : args) {
3456                 final int delimLocation = arg.indexOf(':');
3457 
3458                 if (delimLocation != -1) {
3459                     // 2. File with specified size read from stdin.
3460                     if (processArgForStdin(arg, session) != 0) {
3461                         return 1;
3462                     }
3463                 } else {
3464                     // 3. Local file.
3465                     processArgForLocalFile(arg, session);
3466                 }
3467             }
3468             return 0;
3469         } catch (IllegalArgumentException e) {
3470             getErrPrintWriter().println("Failed to add file(s), reason: " + e);
3471             getOutPrintWriter().println("Failure [failed to add file(s)]");
3472             return 1;
3473         } finally {
3474             IoUtils.closeQuietly(session);
3475         }
3476     }
3477 
processArgForStdin(String arg, PackageInstaller.Session session)3478     private int processArgForStdin(String arg, PackageInstaller.Session session) {
3479         final String[] fileDesc = arg.split(":");
3480         String name, fileId;
3481         long sizeBytes;
3482         byte[] signature = null;
3483         int streamingVersion = 0;
3484 
3485         try {
3486             if (fileDesc.length < 2) {
3487                 getErrPrintWriter().println("Must specify file name and size");
3488                 return 1;
3489             }
3490             name = fileDesc[0];
3491             sizeBytes = Long.parseUnsignedLong(fileDesc[1]);
3492             fileId = name;
3493 
3494             if (fileDesc.length > 2 && !TextUtils.isEmpty(fileDesc[2])) {
3495                 fileId = fileDesc[2];
3496             }
3497             if (fileDesc.length > 3) {
3498                 signature = Base64.getDecoder().decode(fileDesc[3]);
3499             }
3500             if (fileDesc.length > 4) {
3501                 streamingVersion = Integer.parseUnsignedInt(fileDesc[4]);
3502                 if (streamingVersion < 0 || streamingVersion > 1) {
3503                     getErrPrintWriter().println(
3504                             "Unsupported streaming version: " + streamingVersion);
3505                     return 1;
3506                 }
3507             }
3508         } catch (IllegalArgumentException e) {
3509             getErrPrintWriter().println(
3510                     "Unable to parse file parameters: " + arg + ", reason: " + e);
3511             return 1;
3512         }
3513 
3514         if (TextUtils.isEmpty(name)) {
3515             getErrPrintWriter().println("Empty file name in: " + arg);
3516             return 1;
3517         }
3518 
3519         final Metadata metadata;
3520 
3521         if (signature != null) {
3522             // Streaming/adb mode. Versions:
3523             // 0: data only streaming, tree has to be fully available,
3524             // 1: tree and data streaming.
3525             metadata = (streamingVersion == 0) ? Metadata.forDataOnlyStreaming(fileId)
3526                     : Metadata.forStreaming(fileId);
3527             try {
3528                 if ((signature.length > 0) && (V4Signature.readFrom(signature) == null)) {
3529                     getErrPrintWriter().println("V4 signature is invalid in: " + arg);
3530                     return 1;
3531                 }
3532             } catch (Exception e) {
3533                 getErrPrintWriter().println(
3534                         "V4 signature is invalid: " + e + " in " + arg);
3535                 return 1;
3536             }
3537         } else {
3538             // Single-shot read from stdin.
3539             metadata = Metadata.forStdIn(fileId);
3540         }
3541 
3542         session.addFile(LOCATION_DATA_APP, name, sizeBytes, metadata.toByteArray(), signature);
3543         return 0;
3544     }
3545 
getFileStatSize(File file)3546     private long getFileStatSize(File file) {
3547         final ParcelFileDescriptor pfd = openFileForSystem(file.getPath(), "r");
3548         if (pfd == null) {
3549             throw new IllegalArgumentException("Error: Can't open file: " + file.getPath());
3550         }
3551         try {
3552             return pfd.getStatSize();
3553         } finally {
3554             IoUtils.closeQuietly(pfd);
3555         }
3556     }
3557 
processArgForLocalFile(String arg, PackageInstaller.Session session)3558     private void processArgForLocalFile(String arg, PackageInstaller.Session session) {
3559         final String inPath = arg;
3560 
3561         final File file = new File(inPath);
3562         final String name = file.getName();
3563         final long size = getFileStatSize(file);
3564         final Metadata metadata = Metadata.forLocalFile(inPath);
3565 
3566         byte[] v4signatureBytes = null;
3567         // Try to load the v4 signature file for the APK; it might not exist.
3568         final String v4SignaturePath = inPath + V4Signature.EXT;
3569         final ParcelFileDescriptor pfd = openFileForSystem(v4SignaturePath, "r");
3570         if (pfd != null) {
3571             try {
3572                 final V4Signature v4signature = V4Signature.readFrom(pfd);
3573                 v4signatureBytes = v4signature.toByteArray();
3574             } catch (IOException ex) {
3575                 Slog.e(TAG, "V4 signature file exists but failed to be parsed.", ex);
3576             } finally {
3577                 IoUtils.closeQuietly(pfd);
3578             }
3579         }
3580 
3581         session.addFile(LOCATION_DATA_APP, name, size, metadata.toByteArray(), v4signatureBytes);
3582     }
3583 
doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes, boolean isApex)3584     private int doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes,
3585             boolean isApex) throws RemoteException {
3586         final boolean multipleSplits = splitPaths.size() > 1;
3587         for (String splitPath : splitPaths) {
3588             String splitName = multipleSplits ? new File(splitPath).getName()
3589                     : "base." + (isApex ? "apex" : "apk");
3590 
3591             if (doWriteSplit(sessionId, splitPath, sessionSizeBytes, splitName,
3592                     false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
3593                 return 1;
3594             }
3595         }
3596         return 0;
3597     }
3598 
doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName, boolean logSuccess)3599     private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
3600             boolean logSuccess) throws RemoteException {
3601         PackageInstaller.Session session = null;
3602         try {
3603             session = new PackageInstaller.Session(
3604                     mInterface.getPackageInstaller().openSession(sessionId));
3605 
3606             final PrintWriter pw = getOutPrintWriter();
3607 
3608             final ParcelFileDescriptor fd;
3609             if (STDIN_PATH.equals(inPath)) {
3610                 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
3611             } else if (inPath != null) {
3612                 fd = openFileForSystem(inPath, "r");
3613                 if (fd == null) {
3614                     return -1;
3615                 }
3616                 sizeBytes = fd.getStatSize();
3617                 if (sizeBytes < 0) {
3618                     getErrPrintWriter().println("Unable to get size of: " + inPath);
3619                     return -1;
3620                 }
3621             } else {
3622                 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
3623             }
3624             if (sizeBytes <= 0) {
3625                 getErrPrintWriter().println("Error: must specify a APK size");
3626                 return 1;
3627             }
3628 
3629             session.write(splitName, 0, sizeBytes, fd);
3630 
3631             if (logSuccess) {
3632                 pw.println("Success: streamed " + sizeBytes + " bytes");
3633             }
3634             return 0;
3635         } catch (IOException e) {
3636             getErrPrintWriter().println("Error: failed to write; " + e.getMessage());
3637             return 1;
3638         } finally {
3639             IoUtils.closeQuietly(session);
3640         }
3641     }
3642 
doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)3643     private int doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)
3644             throws RemoteException {
3645         final PrintWriter pw = getOutPrintWriter();
3646         PackageInstaller.Session session = null;
3647         try {
3648             session = new PackageInstaller.Session(
3649                     mInterface.getPackageInstaller().openSession(parentId));
3650             if (!session.isMultiPackage()) {
3651                 getErrPrintWriter().println(
3652                         "Error: parent session ID is not a multi-package session");
3653                 return 1;
3654             }
3655             for (int i = 0; i < sessionIds.length; i++) {
3656                 session.addChildSessionId(sessionIds[i]);
3657             }
3658             if (logSuccess) {
3659                 pw.println("Success");
3660             }
3661             return 0;
3662         } finally {
3663             IoUtils.closeQuietly(session);
3664         }
3665     }
3666 
doRemoveSplits(int sessionId, Collection<String> splitNames, boolean logSuccess)3667     private int doRemoveSplits(int sessionId, Collection<String> splitNames, boolean logSuccess)
3668             throws RemoteException {
3669         final PrintWriter pw = getOutPrintWriter();
3670         PackageInstaller.Session session = null;
3671         try {
3672             session = new PackageInstaller.Session(
3673                     mInterface.getPackageInstaller().openSession(sessionId));
3674             for (String splitName : splitNames) {
3675                 session.removeSplit(splitName);
3676             }
3677 
3678             if (logSuccess) {
3679                 pw.println("Success");
3680             }
3681             return 0;
3682         } catch (IOException e) {
3683             pw.println("Error: failed to remove split; " + e.getMessage());
3684             return 1;
3685         } finally {
3686             IoUtils.closeQuietly(session);
3687         }
3688     }
3689 
doCommitSession(int sessionId, boolean logSuccess)3690     private int doCommitSession(int sessionId, boolean logSuccess)
3691             throws RemoteException {
3692 
3693         final PrintWriter pw = getOutPrintWriter();
3694         PackageInstaller.Session session = null;
3695         try {
3696             session = new PackageInstaller.Session(
3697                     mInterface.getPackageInstaller().openSession(sessionId));
3698             if (!session.isMultiPackage() && !session.isStaged()) {
3699                 // Validity check that all .dm files match an apk.
3700                 // (The installer does not support standalone .dm files and will not process them.)
3701                 try {
3702                     DexMetadataHelper.validateDexPaths(session.getNames());
3703                 } catch (IllegalStateException | IOException e) {
3704                     pw.println(
3705                             "Warning [Could not validate the dex paths: " + e.getMessage() + "]");
3706                 }
3707             }
3708             final LocalIntentReceiver receiver = new LocalIntentReceiver();
3709             session.commit(receiver.getIntentSender());
3710             if (!session.isStaged()) {
3711                 final Intent result = receiver.getResult();
3712                 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
3713                         PackageInstaller.STATUS_FAILURE);
3714                 if (status == PackageInstaller.STATUS_SUCCESS) {
3715                     if (logSuccess) {
3716                         pw.println("Success");
3717                     }
3718                 } else {
3719                     pw.println("Failure ["
3720                             + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
3721                 }
3722                 return status;
3723             } else {
3724                 // Return immediately without retrieving the result. The caller will decide
3725                 // whether to wait for the session to become ready.
3726                 if (logSuccess) {
3727                     pw.println("Success");
3728                 }
3729                 return PackageInstaller.STATUS_SUCCESS;
3730             }
3731         } finally {
3732             IoUtils.closeQuietly(session);
3733         }
3734     }
3735 
doAbandonSession(int sessionId, boolean logSuccess)3736     private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
3737         final PrintWriter pw = getOutPrintWriter();
3738         PackageInstaller.Session session = null;
3739         try {
3740             session = new PackageInstaller.Session(
3741                     mInterface.getPackageInstaller().openSession(sessionId));
3742             session.abandon();
3743             if (logSuccess) {
3744                 pw.println("Success");
3745             }
3746             return 0;
3747         } finally {
3748             IoUtils.closeQuietly(session);
3749         }
3750     }
3751 
doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels, boolean summary, int startProtectionLevel, int endProtectionLevel)3752     private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
3753             boolean summary, int startProtectionLevel, int endProtectionLevel)
3754                     throws RemoteException {
3755         final PrintWriter pw = getOutPrintWriter();
3756         final int groupCount = groupList.size();
3757         for (int i = 0; i < groupCount; i++) {
3758             String groupName = groupList.get(i);
3759             String prefix = "";
3760             if (groups) {
3761                 if (i > 0) {
3762                     pw.println("");
3763                 }
3764                 if (groupName != null) {
3765                     PermissionGroupInfo pgi =
3766                             mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
3767                     if (summary) {
3768                         Resources res = getResources(pgi);
3769                         if (res != null) {
3770                             pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
3771                         } else {
3772                             pw.print(pgi.name + ": ");
3773 
3774                         }
3775                     } else {
3776                         pw.println((labels ? "+ " : "") + "group:" + pgi.name);
3777                         if (labels) {
3778                             pw.println("  package:" + pgi.packageName);
3779                             Resources res = getResources(pgi);
3780                             if (res != null) {
3781                                 pw.println("  label:"
3782                                         + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
3783                                 pw.println("  description:"
3784                                         + loadText(pgi, pgi.descriptionRes,
3785                                                 pgi.nonLocalizedDescription));
3786                             }
3787                         }
3788                     }
3789                 } else {
3790                     pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
3791                 }
3792                 prefix = "  ";
3793             }
3794             List<PermissionInfo> ps = mPermissionManager
3795                     .queryPermissionsByGroup(groupList.get(i), 0 /*flags*/);
3796             final int count = (ps == null ? 0 : ps.size());
3797             boolean first = true;
3798             for (int p = 0 ; p < count ; p++) {
3799                 PermissionInfo pi = ps.get(p);
3800                 if (groups && groupName == null && pi.group != null) {
3801                     continue;
3802                 }
3803                 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
3804                 if (base < startProtectionLevel
3805                         || base > endProtectionLevel) {
3806                     continue;
3807                 }
3808                 if (summary) {
3809                     if (first) {
3810                         first = false;
3811                     } else {
3812                         pw.print(", ");
3813                     }
3814                     Resources res = getResources(pi);
3815                     if (res != null) {
3816                         pw.print(loadText(pi, pi.labelRes,
3817                                 pi.nonLocalizedLabel));
3818                     } else {
3819                         pw.print(pi.name);
3820                     }
3821                 } else {
3822                     pw.println(prefix + (labels ? "+ " : "")
3823                             + "permission:" + pi.name);
3824                     if (labels) {
3825                         pw.println(prefix + "  package:" + pi.packageName);
3826                         Resources res = getResources(pi);
3827                         if (res != null) {
3828                             pw.println(prefix + "  label:"
3829                                     + loadText(pi, pi.labelRes,
3830                                             pi.nonLocalizedLabel));
3831                             pw.println(prefix + "  description:"
3832                                     + loadText(pi, pi.descriptionRes,
3833                                             pi.nonLocalizedDescription));
3834                         }
3835                         pw.println(prefix + "  protectionLevel:"
3836                                 + PermissionInfo.protectionToString(pi.protectionLevel));
3837                     }
3838                 }
3839             }
3840 
3841             if (summary) {
3842                 pw.println("");
3843             }
3844         }
3845     }
3846 
loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)3847     private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
3848             throws RemoteException {
3849         if (nonLocalized != null) {
3850             return nonLocalized.toString();
3851         }
3852         if (res != 0) {
3853             Resources r = getResources(pii);
3854             if (r != null) {
3855                 try {
3856                     return r.getString(res);
3857                 } catch (Resources.NotFoundException e) {
3858                 }
3859             }
3860         }
3861         return null;
3862     }
3863 
getResources(PackageItemInfo pii)3864     private Resources getResources(PackageItemInfo pii) throws RemoteException {
3865         Resources res = mResourceCache.get(pii.packageName);
3866         if (res != null) return res;
3867 
3868         ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName,
3869                 PackageManager.MATCH_DISABLED_COMPONENTS
3870                         | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
3871                         | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, 0);
3872         AssetManager am = new AssetManager();
3873         am.addAssetPath(ai.publicSourceDir);
3874         res = new Resources(am, null, null);
3875         mResourceCache.put(pii.packageName, res);
3876         return res;
3877     }
3878 
3879     @Override
onHelp()3880     public void onHelp() {
3881         final PrintWriter pw = getOutPrintWriter();
3882         pw.println("Package manager (package) commands:");
3883         pw.println("  help");
3884         pw.println("    Print this help text.");
3885         pw.println("");
3886         pw.println("  path [--user USER_ID] PACKAGE");
3887         pw.println("    Print the path to the .apk of the given PACKAGE.");
3888         pw.println("");
3889         pw.println("  dump PACKAGE");
3890         pw.println("    Print various system state associated with the given PACKAGE.");
3891         pw.println("");
3892         pw.println("  has-feature FEATURE_NAME [version]");
3893         pw.println("    Prints true and returns exit status 0 when system has a FEATURE_NAME,");
3894         pw.println("    otherwise prints false and returns exit status 1");
3895         pw.println("");
3896         pw.println("  list features");
3897         pw.println("    Prints all features of the system.");
3898         pw.println("");
3899         pw.println("  list instrumentation [-f] [TARGET-PACKAGE]");
3900         pw.println("    Prints all test packages; optionally only those targeting TARGET-PACKAGE");
3901         pw.println("    Options:");
3902         pw.println("      -f: dump the name of the .apk file containing the test package");
3903         pw.println("");
3904         pw.println("  list libraries");
3905         pw.println("    Prints all system libraries.");
3906         pw.println("");
3907         pw.println("  list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
3908         pw.println("      [--show-versioncode] [--apex-only] [--uid UID] [--user USER_ID] [FILTER]");
3909         pw.println("    Prints all packages; optionally only those whose name contains");
3910         pw.println("    the text in FILTER.  Options are:");
3911         pw.println("      -f: see their associated file");
3912         pw.println("      -a: all known packages (but excluding APEXes)");
3913         pw.println("      -d: filter to only show disabled packages");
3914         pw.println("      -e: filter to only show enabled packages");
3915         pw.println("      -s: filter to only show system packages");
3916         pw.println("      -3: filter to only show third party packages");
3917         pw.println("      -i: see the installer for the packages");
3918         pw.println("      -l: ignored (used for compatibility with older releases)");
3919         pw.println("      -U: also show the package UID");
3920         pw.println("      -u: also include uninstalled packages");
3921         pw.println("      --show-versioncode: also show the version code");
3922         pw.println("      --apex-only: only show APEX packages");
3923         pw.println("      --uid UID: filter to only show packages with the given UID");
3924         pw.println("      --user USER_ID: only list packages belonging to the given user");
3925         pw.println("");
3926         pw.println("  list permission-groups");
3927         pw.println("    Prints all known permission groups.");
3928         pw.println("");
3929         pw.println("  list permissions [-g] [-f] [-d] [-u] [GROUP]");
3930         pw.println("    Prints all known permissions; optionally only those in GROUP.  Options are:");
3931         pw.println("      -g: organize by group");
3932         pw.println("      -f: print all information");
3933         pw.println("      -s: short summary");
3934         pw.println("      -d: only list dangerous permissions");
3935         pw.println("      -u: list only the permissions users will see");
3936         pw.println("");
3937         pw.println("  list staged-sessions [--only-ready] [--only-sessionid] [--only-parent]");
3938         pw.println("    Prints all staged sessions.");
3939         pw.println("      --only-ready: show only staged sessions that are ready");
3940         pw.println("      --only-sessionid: show only sessionId of each session");
3941         pw.println("      --only-parent: hide all children sessions");
3942         pw.println("");
3943         pw.println("  list users");
3944         pw.println("    Prints all users.");
3945         pw.println("");
3946         pw.println("  resolve-activity [--brief] [--components] [--query-flags FLAGS]");
3947         pw.println("       [--user USER_ID] INTENT");
3948         pw.println("    Prints the activity that resolves to the given INTENT.");
3949         pw.println("");
3950         pw.println("  query-activities [--brief] [--components] [--query-flags FLAGS]");
3951         pw.println("       [--user USER_ID] INTENT");
3952         pw.println("    Prints all activities that can handle the given INTENT.");
3953         pw.println("");
3954         pw.println("  query-services [--brief] [--components] [--query-flags FLAGS]");
3955         pw.println("       [--user USER_ID] INTENT");
3956         pw.println("    Prints all services that can handle the given INTENT.");
3957         pw.println("");
3958         pw.println("  query-receivers [--brief] [--components] [--query-flags FLAGS]");
3959         pw.println("       [--user USER_ID] INTENT");
3960         pw.println("    Prints all broadcast receivers that can handle the given INTENT.");
3961         pw.println("");
3962         pw.println("  install [-rtfdg] [-i PACKAGE] [--user USER_ID|all|current]");
3963         pw.println("       [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
3964         pw.println("       [--install-reason 0/1/2/3/4] [--originating-uri URI]");
3965         pw.println("       [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
3966         pw.println("       [--preload] [--instant] [--full] [--dont-kill]");
3967         pw.println("       [--enable-rollback]");
3968         pw.println("       [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
3969         pw.println("       [--apex] [--staged-ready-timeout TIMEOUT]");
3970         pw.println("       [PATH [SPLIT...]|-]");
3971         pw.println("    Install an application.  Must provide the apk data to install, either as");
3972         pw.println("    file path(s) or '-' to read from stdin.  Options are:");
3973         pw.println("      -R: disallow replacement of existing application");
3974         pw.println("      -t: allow test packages");
3975         pw.println("      -i: specify package name of installer owning the app");
3976         pw.println("      -f: install application on internal flash");
3977         pw.println("      -d: allow version code downgrade (debuggable packages only)");
3978         pw.println("      -p: partial application install (new split on top of existing pkg)");
3979         pw.println("      -g: grant all runtime permissions");
3980         pw.println("      -S: size in bytes of package, required for stdin");
3981         pw.println("      --user: install under the given user.");
3982         pw.println("      --dont-kill: installing a new feature split, don't kill running app");
3983         pw.println("      --restrict-permissions: don't whitelist restricted permissions at install");
3984         pw.println("      --originating-uri: set URI where app was downloaded from");
3985         pw.println("      --referrer: set URI that instigated the install of the app");
3986         pw.println("      --pkg: specify expected package name of app being installed");
3987         pw.println("      --abi: override the default ABI of the platform");
3988         pw.println("      --instant: cause the app to be installed as an ephemeral install app");
3989         pw.println("      --full: cause the app to be installed as a non-ephemeral full app");
3990         pw.println("      --install-location: force the install location:");
3991         pw.println("          0=auto, 1=internal only, 2=prefer external");
3992         pw.println("      --install-reason: indicates why the app is being installed:");
3993         pw.println("          0=unknown, 1=admin policy, 2=device restore,");
3994         pw.println("          3=device setup, 4=user request");
3995         pw.println("      --force-uuid: force install on to disk volume with given UUID");
3996         pw.println("      --apex: install an .apex file, not an .apk");
3997         pw.println("      --staged-ready-timeout: By default, staged sessions wait "
3998                 + DEFAULT_STAGED_READY_TIMEOUT_MS);
3999         pw.println("          milliseconds for pre-reboot verification to complete when");
4000         pw.println("          performing staged install. This flag is used to alter the waiting");
4001         pw.println("          time. You can skip the waiting time by specifying a TIMEOUT of '0'");
4002         pw.println("");
4003         pw.println("  install-existing [--user USER_ID|all|current]");
4004         pw.println("       [--instant] [--full] [--wait] [--restrict-permissions] PACKAGE");
4005         pw.println("    Installs an existing application for a new user.  Options are:");
4006         pw.println("      --user: install for the given user.");
4007         pw.println("      --instant: install as an instant app");
4008         pw.println("      --full: install as a full app");
4009         pw.println("      --wait: wait until the package is installed");
4010         pw.println("      --restrict-permissions: don't whitelist restricted permissions");
4011         pw.println("");
4012         pw.println("  install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
4013         pw.println("       [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
4014         pw.println("       [--install-reason 0/1/2/3/4] [--originating-uri URI]");
4015         pw.println("       [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
4016         pw.println("       [--preload] [--instant] [--full] [--dont-kill]");
4017         pw.println("       [--force-uuid internal|UUID] [--pkg PACKAGE] [--apex] [-S BYTES]");
4018         pw.println("       [--multi-package] [--staged]");
4019         pw.println("    Like \"install\", but starts an install session.  Use \"install-write\"");
4020         pw.println("    to push data into the session, and \"install-commit\" to finish.");
4021         pw.println("");
4022         pw.println("  install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]");
4023         pw.println("    Write an apk into the given install session.  If the path is '-', data");
4024         pw.println("    will be read from stdin.  Options are:");
4025         pw.println("      -S: size in bytes of package, required for stdin");
4026         pw.println("");
4027         pw.println("  install-remove SESSION_ID SPLIT...");
4028         pw.println("    Mark SPLIT(s) as removed in the given install session.");
4029         pw.println("");
4030         pw.println("  install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs");
4031         pw.println("    Add one or more session IDs to a multi-package session.");
4032         pw.println("");
4033         pw.println("  install-commit SESSION_ID");
4034         pw.println("    Commit the given active install session, installing the app.");
4035         pw.println("");
4036         pw.println("  install-abandon SESSION_ID");
4037         pw.println("    Delete the given active install session.");
4038         pw.println("");
4039         pw.println("  set-install-location LOCATION");
4040         pw.println("    Changes the default install location.  NOTE this is only intended for debugging;");
4041         pw.println("    using this can cause applications to break and other undersireable behavior.");
4042         pw.println("    LOCATION is one of:");
4043         pw.println("    0 [auto]: Let system decide the best location");
4044         pw.println("    1 [internal]: Install on internal device storage");
4045         pw.println("    2 [external]: Install on external media");
4046         pw.println("");
4047         pw.println("  get-install-location");
4048         pw.println("    Returns the current install location: 0, 1 or 2 as per set-install-location.");
4049         pw.println("");
4050         pw.println("  move-package PACKAGE [internal|UUID]");
4051         pw.println("");
4052         pw.println("  move-primary-storage [internal|UUID]");
4053         pw.println("");
4054         pw.println("  uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE]");
4055         pw.println("       PACKAGE [SPLIT...]");
4056         pw.println("    Remove the given package name from the system.  May remove an entire app");
4057         pw.println("    if no SPLIT names specified, otherwise will remove only the splits of the");
4058         pw.println("    given app.  Options are:");
4059         pw.println("      -k: keep the data and cache directories around after package removal.");
4060         pw.println("      --user: remove the app from the given user.");
4061         pw.println("      --versionCode: only uninstall if the app has the given version code.");
4062         pw.println("");
4063         pw.println("  clear [--user USER_ID] [--cache-only] PACKAGE");
4064         pw.println("    Deletes data associated with a package. Options are:");
4065         pw.println("    --user: specifies the user for which we need to clear data");
4066         pw.println("    --cache-only: a flag which tells if we only need to clear cache data");
4067         pw.println("");
4068         pw.println("  enable [--user USER_ID] PACKAGE_OR_COMPONENT");
4069         pw.println("  disable [--user USER_ID] PACKAGE_OR_COMPONENT");
4070         pw.println("  disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
4071         pw.println("  disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
4072         pw.println("  default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
4073         pw.println("    These commands change the enabled state of a given package or");
4074         pw.println("    component (written as \"package/class\").");
4075         pw.println("");
4076         pw.println("  hide [--user USER_ID] PACKAGE_OR_COMPONENT");
4077         pw.println("  unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
4078         pw.println("");
4079         pw.println("  suspend [--user USER_ID] PACKAGE [PACKAGE...]");
4080         pw.println("    Suspends the specified package(s) (as user).");
4081         pw.println("");
4082         pw.println("  unsuspend [--user USER_ID] PACKAGE [PACKAGE...]");
4083         pw.println("    Unsuspends the specified package(s) (as user).");
4084         pw.println("");
4085         pw.println("  set-distracting-restriction [--user USER_ID] [--flag FLAG ...]");
4086         pw.println("      PACKAGE [PACKAGE...]");
4087         pw.println("    Sets the specified restriction flags to given package(s) (for user).");
4088         pw.println("    Flags are:");
4089         pw.println("      hide-notifications: Hides notifications from this package");
4090         pw.println("      hide-from-suggestions: Hides this package from suggestions");
4091         pw.println("        (by the launcher, etc.)");
4092         pw.println("    Any existing flags are overwritten, which also means that if no flags are");
4093         pw.println("    specified then all existing flags will be cleared.");
4094         pw.println("");
4095         pw.println("  grant [--user USER_ID] PACKAGE PERMISSION");
4096         pw.println("  revoke [--user USER_ID] PACKAGE PERMISSION");
4097         pw.println("    These commands either grant or revoke permissions to apps.  The permissions");
4098         pw.println("    must be declared as used in the app's manifest, be runtime permissions");
4099         pw.println("    (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
4100         pw.println("");
4101         pw.println("  set-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]");
4102         pw.println("  clear-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]");
4103         pw.println("    These commands either set or clear permission flags on apps.  The permissions");
4104         pw.println("    must be declared as used in the app's manifest, be runtime permissions");
4105         pw.println("    (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
4106         pw.println("    The flags must be one or more of " + SUPPORTED_PERMISSION_FLAGS_LIST);
4107         pw.println("");
4108         pw.println("  reset-permissions");
4109         pw.println("    Revert all runtime permissions to their default state.");
4110         pw.println("");
4111         pw.println("  set-permission-enforced PERMISSION [true|false]");
4112         pw.println("");
4113         pw.println("  get-privapp-permissions TARGET-PACKAGE");
4114         pw.println("    Prints all privileged permissions for a package.");
4115         pw.println("");
4116         pw.println("  get-privapp-deny-permissions TARGET-PACKAGE");
4117         pw.println("    Prints all privileged permissions that are denied for a package.");
4118         pw.println("");
4119         pw.println("  get-oem-permissions TARGET-PACKAGE");
4120         pw.println("    Prints all OEM permissions for a package.");
4121         pw.println("");
4122         pw.println("  trim-caches DESIRED_FREE_SPACE [internal|UUID]");
4123         pw.println("    Trim cache files to reach the given free space.");
4124         pw.println("");
4125         pw.println("  list users");
4126         pw.println("    Lists the current users.");
4127         pw.println("");
4128         pw.println("  create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
4129         pw.println("      [--guest] [--pre-create-only] [--user-type USER_TYPE] USER_NAME");
4130         pw.println("    Create a new user with the given USER_NAME, printing the new user identifier");
4131         pw.println("    of the user.");
4132         // TODO(b/142482943): Consider fetching the list of user types from UMS.
4133         pw.println("    USER_TYPE is the name of a user type, e.g. android.os.usertype.profile.MANAGED.");
4134         pw.println("      If not specified, the default user type is android.os.usertype.full.SECONDARY.");
4135         pw.println("      --managed is shorthand for '--user-type android.os.usertype.profile.MANAGED'.");
4136         pw.println("      --restricted is shorthand for '--user-type android.os.usertype.full.RESTRICTED'.");
4137         pw.println("      --guest is shorthand for '--user-type android.os.usertype.full.GUEST'.");
4138         pw.println("");
4139         pw.println("  remove-user [--set-ephemeral-if-in-use | --wait] USER_ID");
4140         pw.println("    Remove the user with the given USER_IDENTIFIER, deleting all data");
4141         pw.println("    associated with that user.");
4142         pw.println("      --set-ephemeral-if-in-use: If the user is currently running and");
4143         pw.println("        therefore cannot be removed immediately, mark the user as ephemeral");
4144         pw.println("        so that it will be automatically removed when possible (after user");
4145         pw.println("        switch or reboot)");
4146         pw.println("      --wait: Wait until user is removed. Ignored if set-ephemeral-if-in-use");
4147         pw.println("");
4148         pw.println("  set-user-restriction [--user USER_ID] RESTRICTION VALUE");
4149         pw.println("");
4150         pw.println("  get-max-users");
4151         pw.println("");
4152         pw.println("  get-max-running-users");
4153         pw.println("");
4154         pw.println("  compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
4155         pw.println("          [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
4156         pw.println("    Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".  Options are:");
4157         pw.println("      -a: compile all packages");
4158         pw.println("      -c: clear profile data before compiling");
4159         pw.println("      -f: force compilation even if not needed");
4160         pw.println("      -m: select compilation mode");
4161         pw.println("          MODE is one of the dex2oat compiler filters:");
4162         pw.println("            assume-verified");
4163         pw.println("            extract");
4164         pw.println("            verify");
4165         pw.println("            quicken");
4166         pw.println("            space-profile");
4167         pw.println("            space");
4168         pw.println("            speed-profile");
4169         pw.println("            speed");
4170         pw.println("            everything");
4171         pw.println("      -r: select compilation reason");
4172         pw.println("          REASON is one of:");
4173         for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
4174             pw.println("            " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
4175         }
4176         pw.println("      --reset: restore package to its post-install state");
4177         pw.println("      --check-prof (true | false): look at profiles when doing dexopt?");
4178         pw.println("      --secondary-dex: compile app secondary dex files");
4179         pw.println("      --split SPLIT: compile only the given split name");
4180         pw.println("      --compile-layouts: compile layout resources for faster inflation");
4181         pw.println("");
4182         pw.println("  force-dex-opt PACKAGE");
4183         pw.println("    Force immediate execution of dex opt for the given PACKAGE.");
4184         pw.println("");
4185         pw.println("  delete-dexopt PACKAGE");
4186         pw.println("    Delete dex optimization results for the given PACKAGE.");
4187         pw.println("");
4188         pw.println("  bg-dexopt-job");
4189         pw.println("    Execute the background optimizations immediately.");
4190         pw.println("    Note that the command only runs the background optimizer logic. It may");
4191         pw.println("    overlap with the actual job but the job scheduler will not be able to");
4192         pw.println("    cancel it. It will also run even if the device is not in the idle");
4193         pw.println("    maintenance mode.");
4194         pw.println("  cancel-bg-dexopt-job");
4195         pw.println("    Cancels currently running background optimizations immediately.");
4196         pw.println("    This cancels optimizations run from bg-dexopt-job or from JobScjeduler.");
4197         pw.println("    Note that cancelling currently running bg-dexopt-job command requires");
4198         pw.println("    running this command from separate adb shell.");
4199         pw.println("");
4200         pw.println("  reconcile-secondary-dex-files TARGET-PACKAGE");
4201         pw.println("    Reconciles the package secondary dex files with the generated oat files.");
4202         pw.println("");
4203         pw.println("  dump-profiles [--dump-classes-and-methods] TARGET-PACKAGE");
4204         pw.println("    Dumps method/class profile files to");
4205         pw.println("    " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION
4206                 + "TARGET-PACKAGE-primary.prof.txt.");
4207         pw.println("      --dump-classes-and-methods: passed along to the profman binary to");
4208         pw.println("        switch to the format used by 'profman --create-profile-from'.");
4209         pw.println("");
4210         pw.println("  snapshot-profile TARGET-PACKAGE [--code-path path]");
4211         pw.println("    Take a snapshot of the package profiles to");
4212         pw.println("    " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION
4213                 + "TARGET-PACKAGE[-code-path].prof");
4214         pw.println("    If TARGET-PACKAGE=android it will take a snapshot of the boot image");
4215         pw.println("");
4216         pw.println("  set-home-activity [--user USER_ID] TARGET-COMPONENT");
4217         pw.println("    Set the default home activity (aka launcher).");
4218         pw.println("    TARGET-COMPONENT can be a package name (com.package.my) or a full");
4219         pw.println("    component (com.package.my/component.name). However, only the package name");
4220         pw.println("    matters: the actual component used will be determined automatically from");
4221         pw.println("    the package.");
4222         pw.println("");
4223         pw.println("  set-installer PACKAGE INSTALLER");
4224         pw.println("    Set installer package name");
4225         pw.println("");
4226         pw.println("  get-instantapp-resolver");
4227         pw.println("    Return the name of the component that is the current instant app installer.");
4228         pw.println("");
4229         pw.println("  set-harmful-app-warning [--user <USER_ID>] <PACKAGE> [<WARNING>]");
4230         pw.println("    Mark the app as harmful with the given warning message.");
4231         pw.println("");
4232         pw.println("  get-harmful-app-warning [--user <USER_ID>] <PACKAGE>");
4233         pw.println("    Return the harmful app warning message for the given app, if present");
4234         pw.println();
4235         pw.println("  uninstall-system-updates [<PACKAGE>]");
4236         pw.println("    Removes updates to the given system application and falls back to its");
4237         pw.println("    /system version. Does nothing if the given package is not a system app.");
4238         pw.println("    If no package is specified, removes updates to all system applications.");
4239         pw.println("");
4240         pw.println("  get-moduleinfo [--all | --installed] [module-name]");
4241         pw.println("    Displays module info. If module-name is specified only that info is shown");
4242         pw.println("    By default, without any argument only installed modules are shown.");
4243         pw.println("      --all: show all module info");
4244         pw.println("      --installed: show only installed modules");
4245         pw.println("");
4246         pw.println("  log-visibility [--enable|--disable] <PACKAGE>");
4247         pw.println("    Turns on debug logging when visibility is blocked for the given package.");
4248         pw.println("      --enable: turn on debug logging (default)");
4249         pw.println("      --disable: turn off debug logging");
4250         pw.println("");
4251         pw.println("  set-silent-updates-policy [--allow-unlimited-silent-updates <INSTALLER>]");
4252         pw.println("                            [--throttle-time <SECONDS>] [--reset]");
4253         pw.println("    Sets the policies of the silent updates.");
4254         pw.println("      --allow-unlimited-silent-updates: allows unlimited silent updated");
4255         pw.println("        installation requests from the installer without the throttle time.");
4256         pw.println("      --throttle-time: update the silent updates throttle time in seconds.");
4257         pw.println("      --reset: restore the installer and throttle time to the default, and");
4258         pw.println("        clear tracks of silent updates in the system.");
4259         pw.println("");
4260         mDomainVerificationShell.printHelp(pw);
4261         pw.println("");
4262         Intent.printIntentArgsHelp(pw , "");
4263     }
4264 
4265     private static class LocalIntentReceiver {
4266         private final LinkedBlockingQueue<Intent> mResult = new LinkedBlockingQueue<>();
4267 
4268         private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
4269             @Override
4270             public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
4271                     IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
4272                 try {
4273                     mResult.offer(intent, 5, TimeUnit.SECONDS);
4274                 } catch (InterruptedException e) {
4275                     throw new RuntimeException(e);
4276                 }
4277             }
4278         };
4279 
getIntentSender()4280         public IntentSender getIntentSender() {
4281             return new IntentSender((IIntentSender) mLocalSender);
4282         }
4283 
getResult()4284         public Intent getResult() {
4285             try {
4286                 return mResult.take();
4287             } catch (InterruptedException e) {
4288                 throw new RuntimeException(e);
4289             }
4290         }
4291     }
4292 }
4293