blob: e1f010f62232e0e7784ebf031f89f64b790a03c3 [file] [log] [blame]
Aurimas Liutikas88c7ff12023-08-10 12:42:26 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.pm;
18
19import static android.Manifest.permission.GET_APP_METADATA;
20import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
21import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
22import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
23import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
24import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
25import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
26
27import static com.android.server.LocalManagerRegistry.ManagerNotFoundException;
28import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
29
30import android.accounts.IAccountManager;
31import android.annotation.NonNull;
32import android.annotation.UserIdInt;
33import android.app.ActivityManager;
34import android.app.ActivityManagerInternal;
35import android.app.role.RoleManager;
36import android.content.ComponentName;
37import android.content.Context;
38import android.content.IIntentReceiver;
39import android.content.IIntentSender;
40import android.content.Intent;
41import android.content.IntentSender;
42import android.content.pm.ApplicationInfo;
43import android.content.pm.FeatureInfo;
44import android.content.pm.IPackageDataObserver;
45import android.content.pm.IPackageInstaller;
46import android.content.pm.IPackageManager;
47import android.content.pm.InstrumentationInfo;
48import android.content.pm.ModuleInfo;
49import android.content.pm.PackageInfo;
50import android.content.pm.PackageInstaller;
51import android.content.pm.PackageInstaller.SessionInfo;
52import android.content.pm.PackageInstaller.SessionParams;
53import android.content.pm.PackageItemInfo;
54import android.content.pm.PackageManager;
55import android.content.pm.PackageManager.NameNotFoundException;
56import android.content.pm.PackageManagerInternal;
57import android.content.pm.ParceledListSlice;
58import android.content.pm.PermissionGroupInfo;
59import android.content.pm.PermissionInfo;
60import android.content.pm.ResolveInfo;
61import android.content.pm.SharedLibraryInfo;
62import android.content.pm.SuspendDialogInfo;
63import android.content.pm.UserInfo;
64import android.content.pm.VersionedPackage;
65import android.content.pm.dex.ArtManager;
66import android.content.pm.dex.DexMetadataHelper;
67import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
68import android.content.pm.parsing.ApkLite;
69import android.content.pm.parsing.ApkLiteParseUtils;
70import android.content.pm.parsing.PackageLite;
71import android.content.pm.parsing.result.ParseResult;
72import android.content.pm.parsing.result.ParseTypeImpl;
73import android.content.res.AssetManager;
74import android.content.res.Resources;
75import android.content.rollback.PackageRollbackInfo;
76import android.content.rollback.RollbackInfo;
77import android.content.rollback.RollbackManager;
78import android.net.Uri;
79import android.os.Binder;
80import android.os.Build;
81import android.os.Bundle;
82import android.os.IBinder;
83import android.os.IUserManager;
84import android.os.ParcelFileDescriptor;
85import android.os.ParcelFileDescriptor.AutoCloseInputStream;
86import android.os.PersistableBundle;
87import android.os.Process;
88import android.os.RemoteException;
89import android.os.ServiceManager;
90import android.os.ServiceSpecificException;
91import android.os.ShellCommand;
92import android.os.SystemClock;
93import android.os.Trace;
94import android.os.UserHandle;
95import android.os.UserManager;
96import android.os.incremental.V4Signature;
97import android.os.storage.StorageManager;
98import android.permission.PermissionManager;
99import android.system.ErrnoException;
100import android.system.Os;
101import android.text.TextUtils;
102import android.text.format.DateUtils;
103import android.util.ArrayMap;
104import android.util.IntArray;
105import android.util.PrintWriterPrinter;
106import android.util.Slog;
107import android.util.SparseArray;
108
109import com.android.internal.content.InstallLocationUtils;
110import com.android.internal.util.ArrayUtils;
111import com.android.internal.util.IndentingPrintWriter;
112import com.android.internal.util.Preconditions;
113import com.android.server.FgThread;
114import com.android.server.LocalManagerRegistry;
115import com.android.server.LocalServices;
116import com.android.server.SystemConfig;
117import com.android.server.art.ArtManagerLocal;
118import com.android.server.pm.Installer.LegacyDexoptDisabledException;
119import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata;
120import com.android.server.pm.permission.LegacyPermissionManagerInternal;
121import com.android.server.pm.permission.PermissionAllowlist;
122import com.android.server.pm.verify.domain.DomainVerificationShell;
123
124import dalvik.system.DexFile;
125
126import libcore.io.IoUtils;
127import libcore.io.Streams;
128
129import java.io.BufferedReader;
130import java.io.File;
131import java.io.FileOutputStream;
132import java.io.IOException;
133import java.io.InputStream;
134import java.io.InputStreamReader;
135import java.io.OutputStream;
136import java.io.PrintWriter;
137import java.net.URISyntaxException;
138import java.security.SecureRandom;
139import java.util.ArrayList;
140import java.util.Arrays;
141import java.util.Base64;
142import java.util.Collection;
143import java.util.Collections;
144import java.util.Comparator;
145import java.util.HashMap;
146import java.util.List;
147import java.util.Map;
148import java.util.Objects;
149import java.util.Set;
150import java.util.WeakHashMap;
151import java.util.concurrent.CompletableFuture;
152import java.util.concurrent.CountDownLatch;
153import java.util.concurrent.LinkedBlockingQueue;
154import java.util.concurrent.TimeUnit;
155
156class 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
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
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
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 */
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
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
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
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
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
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
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
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 */
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
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
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
797 private int runGc() throws RemoteException {
798 Runtime.getRuntime().gc();
799 final PrintWriter pw = getOutPrintWriter();
800 pw.println("Ok");
801 return 0;
802 }
803
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
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
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
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
935 private int runListPackages(boolean showSourceDir) throws RemoteException {
936 return runListPackages(showSourceDir, false);
937 }
938
939 private int runListSdks() throws RemoteException {
940 return runListPackages(false, true);
941 }
942
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1522 private int runInstall() throws RemoteException {
1523 return doRunInstall(makeInstallParams(UNSUPPORTED_INSTALL_CMD_OPTS));
1524 }
1525
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
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
1642 private int runInstallAbandon() throws RemoteException {
1643 final int sessionId = Integer.parseInt(getNextArg());
1644 return doAbandonSession(sessionId, true /*logSuccess*/);
1645 }
1646
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
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
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
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
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
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
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
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
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
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
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
2045 private int runreconcileSecondaryDexFiles()
2046 throws RemoteException, LegacyDexoptDisabledException {
2047 String packageName = getNextArg();
2048 mPm.legacyReconcileSecondaryDexFiles(packageName);
2049 return 0;
2050 }
2051
2052 public int runForceDexOpt() throws RemoteException, LegacyDexoptDisabledException {
2053 mPm.legacyForceDexOpt(getNextArgRequired());
2054 return 0;
2055 }
2056
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
2100 private int cancelBgDexOptJob() throws RemoteException, LegacyDexoptDisabledException {
2101 BackgroundDexOptService.getService().cancelBackgroundDexoptJob();
2102 getOutPrintWriter().println("Success");
2103 return 0;
2104 }
2105
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
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
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
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
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
2251 public void onError(int errCode) {
2252 mSuccess = false;
2253 mErrCode = errCode;
2254 mDoneSignal.countDown();
2255 }
2256
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
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
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
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
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
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
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
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
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
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
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
2679 private int runResetPermissions() throws RemoteException {
2680 mLegacyPermissionManager.resetRuntimePermissions();
2681 return 0;
2682 }
2683
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
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
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
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
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
2773 private String getApexPackageNameContainingPackage(String pkg) {
2774 ApexManager apexManager = ApexManager.getInstance();
2775 return apexManager.getActiveApexPackageNameContainingPackage(pkg);
2776 }
2777
2778 private boolean isApexApp(String pkg) {
2779 return getApexPackageNameContainingPackage(pkg) != null;
2780 }
2781
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
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
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
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
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
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
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
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
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
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
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
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
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
3177 public int runSupportsMultipleUsers() {
3178 getOutPrintWriter().println("Is multiuser supported: "
3179 + UserManager.supportsMultipleUsers());
3180 return 0;
3181 }
3182
3183 public int runGetMaxUsers() {
3184 getOutPrintWriter().println("Maximum supported users: "
3185 + UserManager.getMaxSupportedUsers());
3186 return 0;
3187 }
3188
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 AssetManager am = new AssetManager();
4130 am.addAssetPath(ai.publicSourceDir);
4131 res = new Resources(am, null, null);
4132 mResourceCache.put(pii.packageName, res);
4133 return res;
4134 }
4135
4136 // Resolves the userId; supports UserHandle.USER_CURRENT, but not other special values
4137 private @UserIdInt int resolveUserId(@UserIdInt int userId) {
4138 return userId == UserHandle.USER_CURRENT ? ActivityManager.getCurrentUser() : userId;
4139 }
4140
4141 @Override
4142 public void onHelp() {
4143 final PrintWriter pw = getOutPrintWriter();
4144 pw.println("Package manager (package) commands:");
4145 pw.println(" help");
4146 pw.println(" Print this help text.");
4147 pw.println("");
4148 pw.println(" path [--user USER_ID] PACKAGE");
4149 pw.println(" Print the path to the .apk of the given PACKAGE.");
4150 pw.println("");
4151 pw.println(" dump PACKAGE");
4152 pw.println(" Print various system state associated with the given PACKAGE.");
4153 pw.println("");
4154 pw.println(" has-feature FEATURE_NAME [version]");
4155 pw.println(" Prints true and returns exit status 0 when system has a FEATURE_NAME,");
4156 pw.println(" otherwise prints false and returns exit status 1");
4157 pw.println("");
4158 pw.println(" list features");
4159 pw.println(" Prints all features of the system.");
4160 pw.println("");
4161 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
4162 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE");
4163 pw.println(" Options:");
4164 pw.println(" -f: dump the name of the .apk file containing the test package");
4165 pw.println("");
4166 pw.println(" list libraries");
4167 pw.println(" Prints all system libraries.");
4168 pw.println("");
4169 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
4170 pw.println(" [--show-versioncode] [--apex-only] [--factory-only]");
4171 pw.println(" [--uid UID] [--user USER_ID] [FILTER]");
4172 pw.println(" Prints all packages; optionally only those whose name contains");
4173 pw.println(" the text in FILTER. Options are:");
4174 pw.println(" -f: see their associated file");
4175 pw.println(" -a: all known packages (but excluding APEXes)");
4176 pw.println(" -d: filter to only show disabled packages");
4177 pw.println(" -e: filter to only show enabled packages");
4178 pw.println(" -s: filter to only show system packages");
4179 pw.println(" -3: filter to only show third party packages");
4180 pw.println(" -i: see the installer for the packages");
4181 pw.println(" -l: ignored (used for compatibility with older releases)");
4182 pw.println(" -U: also show the package UID");
4183 pw.println(" -u: also include uninstalled packages");
4184 pw.println(" --show-versioncode: also show the version code");
4185 pw.println(" --apex-only: only show APEX packages");
4186 pw.println(" --factory-only: only show system packages excluding updates");
4187 pw.println(" --uid UID: filter to only show packages with the given UID");
4188 pw.println(" --user USER_ID: only list packages belonging to the given user");
4189 pw.println(" --match-libraries: include packages that declare static shared and SDK libraries");
4190 pw.println("");
4191 pw.println(" list permission-groups");
4192 pw.println(" Prints all known permission groups.");
4193 pw.println("");
4194 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
4195 pw.println(" Prints all known permissions; optionally only those in GROUP. Options are:");
4196 pw.println(" -g: organize by group");
4197 pw.println(" -f: print all information");
4198 pw.println(" -s: short summary");
4199 pw.println(" -d: only list dangerous permissions");
4200 pw.println(" -u: list only the permissions users will see");
4201 pw.println("");
4202 pw.println(" list staged-sessions [--only-ready] [--only-sessionid] [--only-parent]");
4203 pw.println(" Prints all staged sessions.");
4204 pw.println(" --only-ready: show only staged sessions that are ready");
4205 pw.println(" --only-sessionid: show only sessionId of each session");
4206 pw.println(" --only-parent: hide all children sessions");
4207 pw.println("");
4208 pw.println(" list users");
4209 pw.println(" Prints all users.");
4210 pw.println("");
4211 pw.println(" resolve-activity [--brief] [--components] [--query-flags FLAGS]");
4212 pw.println(" [--user USER_ID] INTENT");
4213 pw.println(" Prints the activity that resolves to the given INTENT.");
4214 pw.println("");
4215 pw.println(" query-activities [--brief] [--components] [--query-flags FLAGS]");
4216 pw.println(" [--user USER_ID] INTENT");
4217 pw.println(" Prints all activities that can handle the given INTENT.");
4218 pw.println("");
4219 pw.println(" query-services [--brief] [--components] [--query-flags FLAGS]");
4220 pw.println(" [--user USER_ID] INTENT");
4221 pw.println(" Prints all services that can handle the given INTENT.");
4222 pw.println("");
4223 pw.println(" query-receivers [--brief] [--components] [--query-flags FLAGS]");
4224 pw.println(" [--user USER_ID] INTENT");
4225 pw.println(" Prints all broadcast receivers that can handle the given INTENT.");
4226 pw.println("");
4227 pw.println(" install [-rtfdg] [-i PACKAGE] [--user USER_ID|all|current]");
4228 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
4229 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
4230 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
4231 pw.println(" [--preload] [--instant] [--full] [--dont-kill]");
4232 pw.println(" [--enable-rollback]");
4233 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
4234 pw.println(" [--apex] [--staged-ready-timeout TIMEOUT]");
4235 pw.println(" [PATH [SPLIT...]|-]");
4236 pw.println(" Install an application. Must provide the apk data to install, either as");
4237 pw.println(" file path(s) or '-' to read from stdin. Options are:");
4238 pw.println(" -R: disallow replacement of existing application");
4239 pw.println(" -t: allow test packages");
4240 pw.println(" -i: specify package name of installer owning the app");
4241 pw.println(" -f: install application on internal flash");
4242 pw.println(" -d: allow version code downgrade (debuggable packages only)");
4243 pw.println(" -p: partial application install (new split on top of existing pkg)");
4244 pw.println(" -g: grant all runtime permissions");
4245 pw.println(" -S: size in bytes of package, required for stdin");
4246 pw.println(" --user: install under the given user.");
4247 pw.println(" --dont-kill: installing a new feature split, don't kill running app");
4248 pw.println(" --restrict-permissions: don't whitelist restricted permissions at install");
4249 pw.println(" --originating-uri: set URI where app was downloaded from");
4250 pw.println(" --referrer: set URI that instigated the install of the app");
4251 pw.println(" --pkg: specify expected package name of app being installed");
4252 pw.println(" --abi: override the default ABI of the platform");
4253 pw.println(" --instant: cause the app to be installed as an ephemeral install app");
4254 pw.println(" --full: cause the app to be installed as a non-ephemeral full app");
4255 pw.println(" --install-location: force the install location:");
4256 pw.println(" 0=auto, 1=internal only, 2=prefer external");
4257 pw.println(" --install-reason: indicates why the app is being installed:");
4258 pw.println(" 0=unknown, 1=admin policy, 2=device restore,");
4259 pw.println(" 3=device setup, 4=user request");
4260 pw.println(" --update-ownership: request the update ownership enforcement");
4261 pw.println(" --force-uuid: force install on to disk volume with given UUID");
4262 pw.println(" --apex: install an .apex file, not an .apk");
4263 pw.println(" --staged-ready-timeout: By default, staged sessions wait "
4264 + DEFAULT_STAGED_READY_TIMEOUT_MS);
4265 pw.println(" milliseconds for pre-reboot verification to complete when");
4266 pw.println(" performing staged install. This flag is used to alter the waiting");
4267 pw.println(" time. You can skip the waiting time by specifying a TIMEOUT of '0'");
4268 pw.println("");
4269 pw.println(" install-existing [--user USER_ID|all|current]");
4270 pw.println(" [--instant] [--full] [--wait] [--restrict-permissions] PACKAGE");
4271 pw.println(" Installs an existing application for a new user. Options are:");
4272 pw.println(" --user: install for the given user.");
4273 pw.println(" --instant: install as an instant app");
4274 pw.println(" --full: install as a full app");
4275 pw.println(" --wait: wait until the package is installed");
4276 pw.println(" --restrict-permissions: don't whitelist restricted permissions");
4277 pw.println("");
4278 pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
4279 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
4280 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
4281 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
4282 pw.println(" [--preload] [--instant] [--full] [--dont-kill]");
4283 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [--apex] [-S BYTES]");
4284 pw.println(" [--multi-package] [--staged] [--update-ownership]");
4285 pw.println(" Like \"install\", but starts an install session. Use \"install-write\"");
4286 pw.println(" to push data into the session, and \"install-commit\" to finish.");
4287 pw.println("");
4288 pw.println(" install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]");
4289 pw.println(" Write an apk into the given install session. If the path is '-', data");
4290 pw.println(" will be read from stdin. Options are:");
4291 pw.println(" -S: size in bytes of package, required for stdin");
4292 pw.println("");
4293 pw.println(" install-remove SESSION_ID SPLIT...");
4294 pw.println(" Mark SPLIT(s) as removed in the given install session.");
4295 pw.println("");
4296 pw.println(" install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs");
4297 pw.println(" Add one or more session IDs to a multi-package session.");
4298 pw.println("");
4299 pw.println(" install-commit SESSION_ID");
4300 pw.println(" Commit the given active install session, installing the app.");
4301 pw.println("");
4302 pw.println(" install-abandon SESSION_ID");
4303 pw.println(" Delete the given active install session.");
4304 pw.println("");
4305 pw.println(" set-install-location LOCATION");
4306 pw.println(" Changes the default install location. NOTE this is only intended for debugging;");
4307 pw.println(" using this can cause applications to break and other undersireable behavior.");
4308 pw.println(" LOCATION is one of:");
4309 pw.println(" 0 [auto]: Let system decide the best location");
4310 pw.println(" 1 [internal]: Install on internal device storage");
4311 pw.println(" 2 [external]: Install on external media");
4312 pw.println("");
4313 pw.println(" get-install-location");
4314 pw.println(" Returns the current install location: 0, 1 or 2 as per set-install-location.");
4315 pw.println("");
4316 pw.println(" move-package PACKAGE [internal|UUID]");
4317 pw.println("");
4318 pw.println(" move-primary-storage [internal|UUID]");
4319 pw.println("");
4320 pw.println(" uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE]");
4321 pw.println(" PACKAGE [SPLIT...]");
4322 pw.println(" Remove the given package name from the system. May remove an entire app");
4323 pw.println(" if no SPLIT names specified, otherwise will remove only the splits of the");
4324 pw.println(" given app. Options are:");
4325 pw.println(" -k: keep the data and cache directories around after package removal.");
4326 pw.println(" --user: remove the app from the given user.");
4327 pw.println(" --versionCode: only uninstall if the app has the given version code.");
4328 pw.println("");
4329 pw.println(" clear [--user USER_ID] [--cache-only] PACKAGE");
4330 pw.println(" Deletes data associated with a package. Options are:");
4331 pw.println(" --user: specifies the user for which we need to clear data");
4332 pw.println(" --cache-only: a flag which tells if we only need to clear cache data");
4333 pw.println("");
4334 pw.println(" enable [--user USER_ID] PACKAGE_OR_COMPONENT");
4335 pw.println(" disable [--user USER_ID] PACKAGE_OR_COMPONENT");
4336 pw.println(" disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
4337 pw.println(" disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
4338 pw.println(" default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
4339 pw.println(" These commands change the enabled state of a given package or");
4340 pw.println(" component (written as \"package/class\").");
4341 pw.println("");
4342 pw.println(" hide [--user USER_ID] PACKAGE_OR_COMPONENT");
4343 pw.println(" unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
4344 pw.println("");
4345 pw.println(" suspend [--user USER_ID] PACKAGE [PACKAGE...]");
4346 pw.println(" Suspends the specified package(s) (as user).");
4347 pw.println("");
4348 pw.println(" unsuspend [--user USER_ID] PACKAGE [PACKAGE...]");
4349 pw.println(" Unsuspends the specified package(s) (as user).");
4350 pw.println("");
4351 pw.println(" set-distracting-restriction [--user USER_ID] [--flag FLAG ...]");
4352 pw.println(" PACKAGE [PACKAGE...]");
4353 pw.println(" Sets the specified restriction flags to given package(s) (for user).");
4354 pw.println(" Flags are:");
4355 pw.println(" hide-notifications: Hides notifications from this package");
4356 pw.println(" hide-from-suggestions: Hides this package from suggestions");
4357 pw.println(" (by the launcher, etc.)");
4358 pw.println(" Any existing flags are overwritten, which also means that if no flags are");
4359 pw.println(" specified then all existing flags will be cleared.");
4360 pw.println("");
4361 pw.println(" grant [--user USER_ID] PACKAGE PERMISSION");
4362 pw.println(" revoke [--user USER_ID] PACKAGE PERMISSION");
4363 pw.println(" These commands either grant or revoke permissions to apps. The permissions");
4364 pw.println(" must be declared as used in the app's manifest, be runtime permissions");
4365 pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
4366 pw.println("");
4367 pw.println(" set-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]");
4368 pw.println(" clear-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]");
4369 pw.println(" These commands either set or clear permission flags on apps. The permissions");
4370 pw.println(" must be declared as used in the app's manifest, be runtime permissions");
4371 pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
4372 pw.println(" The flags must be one or more of " + SUPPORTED_PERMISSION_FLAGS_LIST);
4373 pw.println("");
4374 pw.println(" reset-permissions");
4375 pw.println(" Revert all runtime permissions to their default state.");
4376 pw.println("");
4377 pw.println(" set-permission-enforced PERMISSION [true|false]");
4378 pw.println("");
4379 pw.println(" get-privapp-permissions TARGET-PACKAGE");
4380 pw.println(" Prints all privileged permissions for a package.");
4381 pw.println("");
4382 pw.println(" get-privapp-deny-permissions TARGET-PACKAGE");
4383 pw.println(" Prints all privileged permissions that are denied for a package.");
4384 pw.println("");
4385 pw.println(" get-oem-permissions TARGET-PACKAGE");
4386 pw.println(" Prints all OEM permissions for a package.");
4387 pw.println("");
4388 pw.println(" trim-caches DESIRED_FREE_SPACE [internal|UUID]");
4389 pw.println(" Trim cache files to reach the given free space.");
4390 pw.println("");
4391 pw.println(" list users");
4392 pw.println(" Lists the current users.");
4393 pw.println("");
4394 pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--guest]");
4395 pw.println(" [--user-type USER_TYPE] [--ephemeral] [--for-testing] [--pre-create-only] USER_NAME");
4396 pw.println(" Create a new user with the given USER_NAME, printing the new user identifier");
4397 pw.println(" of the user.");
4398 // TODO(b/142482943): Consider fetching the list of user types from UMS.
4399 pw.println(" USER_TYPE is the name of a user type, e.g. android.os.usertype.profile.MANAGED.");
4400 pw.println(" If not specified, the default user type is android.os.usertype.full.SECONDARY.");
4401 pw.println(" --managed is shorthand for '--user-type android.os.usertype.profile.MANAGED'.");
4402 pw.println(" --restricted is shorthand for '--user-type android.os.usertype.full.RESTRICTED'.");
4403 pw.println(" --guest is shorthand for '--user-type android.os.usertype.full.GUEST'.");
4404 pw.println("");
4405 pw.println(" remove-user [--set-ephemeral-if-in-use | --wait] USER_ID");
4406 pw.println(" Remove the user with the given USER_IDENTIFIER, deleting all data");
4407 pw.println(" associated with that user.");
4408 pw.println(" --set-ephemeral-if-in-use: If the user is currently running and");
4409 pw.println(" therefore cannot be removed immediately, mark the user as ephemeral");
4410 pw.println(" so that it will be automatically removed when possible (after user");
4411 pw.println(" switch or reboot)");
4412 pw.println(" --wait: Wait until user is removed. Ignored if set-ephemeral-if-in-use");
4413 pw.println("");
4414 pw.println(" rename-user USER_ID [USER_NAME]");
4415 pw.println(" Rename USER_ID with USER_NAME (or null when [USER_NAME] is not set)");
4416 pw.println("");
4417 pw.println(" set-user-restriction [--user USER_ID] RESTRICTION VALUE");
4418 pw.println("");
4419 pw.println(" get-max-users");
4420 pw.println("");
4421 pw.println(" get-max-running-users");
4422 pw.println("");
4423 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
4424 pw.println(" Set the default home activity (aka launcher).");
4425 pw.println(" TARGET-COMPONENT can be a package name (com.package.my) or a full");
4426 pw.println(" component (com.package.my/component.name). However, only the package name");
4427 pw.println(" matters: the actual component used will be determined automatically from");
4428 pw.println(" the package.");
4429 pw.println("");
4430 pw.println(" set-installer PACKAGE INSTALLER");
4431 pw.println(" Set installer package name");
4432 pw.println("");
4433 pw.println(" get-instantapp-resolver");
4434 pw.println(
4435 " Return the name of the component that is the current instant app installer.");
4436 pw.println("");
4437 pw.println(" set-harmful-app-warning [--user <USER_ID>] <PACKAGE> [<WARNING>]");
4438 pw.println(" Mark the app as harmful with the given warning message.");
4439 pw.println("");
4440 pw.println(" get-harmful-app-warning [--user <USER_ID>] <PACKAGE>");
4441 pw.println(" Return the harmful app warning message for the given app, if present");
4442 pw.println();
4443 pw.println(" uninstall-system-updates [<PACKAGE>]");
4444 pw.println(" Removes updates to the given system application and falls back to its");
4445 pw.println(" /system version. Does nothing if the given package is not a system app.");
4446 pw.println(" If no package is specified, removes updates to all system applications.");
4447 pw.println("");
4448 pw.println(" get-moduleinfo [--all | --installed] [module-name]");
4449 pw.println(" Displays module info. If module-name is specified only that info is shown");
4450 pw.println(" By default, without any argument only installed modules are shown.");
4451 pw.println(" --all: show all module info");
4452 pw.println(" --installed: show only installed modules");
4453 pw.println("");
4454 pw.println(" log-visibility [--enable|--disable] <PACKAGE>");
4455 pw.println(" Turns on debug logging when visibility is blocked for the given package.");
4456 pw.println(" --enable: turn on debug logging (default)");
4457 pw.println(" --disable: turn off debug logging");
4458 pw.println("");
4459 pw.println(" set-silent-updates-policy [--allow-unlimited-silent-updates <INSTALLER>]");
4460 pw.println(" [--throttle-time <SECONDS>] [--reset]");
4461 pw.println(" Sets the policies of the silent updates.");
4462 pw.println(" --allow-unlimited-silent-updates: allows unlimited silent updated");
4463 pw.println(" installation requests from the installer without the throttle time.");
4464 pw.println(" --throttle-time: update the silent updates throttle time in seconds.");
4465 pw.println(" --reset: restore the installer and throttle time to the default, and");
4466 pw.println(" clear tracks of silent updates in the system.");
4467 pw.println("");
4468 pw.println(" wait-for-handler --timeout <MILLIS>");
4469 pw.println(" Wait for a given amount of time till the package manager handler finishes");
4470 pw.println(" handling all pending messages.");
4471 pw.println(" --timeout: wait for a given number of milliseconds. If the handler(s)");
4472 pw.println(" fail to finish before the timeout, the command returns error.");
4473 pw.println("");
4474 pw.println(" wait-for-background-handler --timeout <MILLIS>");
4475 pw.println(" Wait for a given amount of time till the package manager's background");
4476 pw.println(" handler finishes handling all pending messages.");
4477 pw.println(" --timeout: wait for a given number of milliseconds. If the handler(s)");
4478 pw.println(" fail to finish before the timeout, the command returns error.");
4479 pw.println("");
4480 if (DexOptHelper.useArtService()) {
4481 printArtServiceHelp();
4482 } else {
4483 printLegacyDexoptHelp();
4484 }
4485 pw.println("");
4486 mDomainVerificationShell.printHelp(pw);
4487 pw.println("");
4488 Intent.printIntentArgsHelp(pw, "");
4489 }
4490
4491 private void printArtServiceHelp() {
4492 final var ipw = new IndentingPrintWriter(getOutPrintWriter(), " " /* singleIndent */);
4493 ipw.increaseIndent();
4494 try {
4495 LocalManagerRegistry.getManagerOrThrow(ArtManagerLocal.class)
4496 .printShellCommandHelp(ipw);
4497 } catch (ManagerNotFoundException e) {
4498 ipw.println("ART Service is not ready. Please try again later");
4499 }
4500 ipw.decreaseIndent();
4501 }
4502
4503 private void printLegacyDexoptHelp() {
4504 final PrintWriter pw = getOutPrintWriter();
4505 pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
4506 pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
4507 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\". Options are:");
4508 pw.println(" -a: compile all packages");
4509 pw.println(" -c: clear profile data before compiling");
4510 pw.println(" -f: force compilation even if not needed");
4511 pw.println(" -m: select compilation mode");
4512 pw.println(" MODE is one of the dex2oat compiler filters:");
4513 pw.println(" verify");
4514 pw.println(" speed-profile");
4515 pw.println(" speed");
4516 pw.println(" -r: select compilation reason");
4517 pw.println(" REASON is one of:");
4518 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
4519 pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
4520 }
4521 pw.println(" --reset: restore package to its post-install state");
4522 pw.println(" --check-prof (true | false): ignored - this is always true");
4523 pw.println(" --secondary-dex: compile app secondary dex files");
4524 pw.println(" --split SPLIT: compile only the given split name");
4525 pw.println("");
4526 pw.println(" force-dex-opt PACKAGE");
4527 pw.println(" Force immediate execution of dex opt for the given PACKAGE.");
4528 pw.println("");
4529 pw.println(" delete-dexopt PACKAGE");
4530 pw.println(" Delete dex optimization results for the given PACKAGE.");
4531 pw.println("");
4532 pw.println(" bg-dexopt-job [PACKAGE... | --cancel | --disable | --enable]");
4533 pw.println(" Controls the background job that optimizes dex files:");
4534 pw.println(" Without flags, run background optimization immediately on the given");
4535 pw.println(" PACKAGEs, or all packages if none is specified, and wait until the job");
4536 pw.println(" finishes. Note that the command only runs the background optimizer logic.");
4537 pw.println(" It will run even if the device is not in the idle maintenance mode. If a");
4538 pw.println(" job is already running (including one started automatically by the");
4539 pw.println(" system) it will wait for it to finish before starting. A background job");
4540 pw.println(" will not be started automatically while one started this way is running.");
4541 pw.println(" --cancel: Cancels any currently running background optimization job");
4542 pw.println(" immediately. This cancels jobs started either automatically by the");
4543 pw.println(" system or through this command. Note that cancelling a currently");
4544 pw.println(" running bg-dexopt-job command requires running this command from a");
4545 pw.println(" separate adb shell.");
4546 pw.println(" --disable: Disables background jobs from being started by the job");
4547 pw.println(" scheduler. Does not affect bg-dexopt-job invocations from the shell.");
4548 pw.println(" Does not imply --cancel. This state will be lost when the");
4549 pw.println(" system_server process exits.");
4550 pw.println(" --enable: Enables background jobs to be started by the job scheduler");
4551 pw.println(" again, if previously disabled by --disable.");
4552 pw.println(" cancel-bg-dexopt-job");
4553 pw.println(" Same as bg-dexopt-job --cancel.");
4554 pw.println("");
4555 pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE");
4556 pw.println(" Reconciles the package secondary dex files with the generated oat files.");
4557 pw.println("");
4558 pw.println(" dump-profiles [--dump-classes-and-methods] TARGET-PACKAGE");
4559 pw.println(" Dumps method/class profile files to");
4560 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION
4561 + "TARGET-PACKAGE-primary.prof.txt.");
4562 pw.println(" --dump-classes-and-methods: passed along to the profman binary to");
4563 pw.println(" switch to the format used by 'profman --create-profile-from'.");
4564 pw.println("");
4565 pw.println(" snapshot-profile TARGET-PACKAGE [--code-path path]");
4566 pw.println(" Take a snapshot of the package profiles to");
4567 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION
4568 + "TARGET-PACKAGE[-code-path].prof");
4569 pw.println(" If TARGET-PACKAGE=android it will take a snapshot of the boot image");
4570 }
4571
4572 private static class LocalIntentReceiver {
4573 private final LinkedBlockingQueue<Intent> mResult = new LinkedBlockingQueue<>();
4574
4575 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
4576 @Override
4577 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
4578 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
4579 try {
4580 mResult.offer(intent, 5, TimeUnit.SECONDS);
4581 } catch (InterruptedException e) {
4582 throw new RuntimeException(e);
4583 }
4584 }
4585 };
4586
4587 public IntentSender getIntentSender() {
4588 return new IntentSender((IIntentSender) mLocalSender);
4589 }
4590
4591 public Intent getResult() {
4592 try {
4593 return mResult.take();
4594 } catch (InterruptedException e) {
4595 throw new RuntimeException(e);
4596 }
4597 }
4598 }
4599}