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