blob: bb69680fb9f94e2248494c847715896702badc4c [file] [log] [blame]
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001/*
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
Todd Kennedy60459ab2015-10-30 11:32:16 -070017package com.android.server.pm;
18
Alex Buynytskyye0697872020-01-13 09:25:21 -080019import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
Jeff Sharkey0451de62018-02-02 11:27:21 -070020import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
21import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
22import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
23import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
24import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
25
Dianne Hackbornc81983a2017-10-20 16:16:32 -070026import android.accounts.IAccountManager;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080027import android.app.ActivityManager;
Alex Chauc12189b2018-01-16 15:01:15 +000028import android.app.ActivityManagerInternal;
Bookatz2b5a6012019-04-16 19:41:28 -070029import android.app.role.IRoleManager;
30import android.app.role.RoleManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -070031import android.content.ComponentName;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070032import android.content.Context;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080033import android.content.IIntentReceiver;
34import android.content.IIntentSender;
35import android.content.Intent;
36import android.content.IntentSender;
Todd Kennedy60459ab2015-10-30 11:32:16 -070037import android.content.pm.ApplicationInfo;
38import android.content.pm.FeatureInfo;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070039import android.content.pm.IPackageDataObserver;
Patrick Baumanna980e142018-02-12 11:45:23 -080040import android.content.pm.IPackageInstaller;
Todd Kennedy60459ab2015-10-30 11:32:16 -070041import android.content.pm.IPackageManager;
42import android.content.pm.InstrumentationInfo;
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +010043import android.content.pm.ModuleInfo;
Todd Kennedy60459ab2015-10-30 11:32:16 -070044import android.content.pm.PackageInfo;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080045import android.content.pm.PackageInstaller;
Abhijeet Kaur84b1f5d2019-01-21 17:18:03 +000046import android.content.pm.PackageInstaller.SessionInfo;
Jeff Sharkey0451de62018-02-02 11:27:21 -070047import android.content.pm.PackageInstaller.SessionParams;
Todd Kennedy60459ab2015-10-30 11:32:16 -070048import android.content.pm.PackageItemInfo;
49import android.content.pm.PackageManager;
Jeff Sharkey0451de62018-02-02 11:27:21 -070050import android.content.pm.PackageManager.NameNotFoundException;
Dario Freni788ecb12019-01-23 18:49:32 +000051import android.content.pm.PackageManagerInternal;
Shunta Sato4f26cb52016-06-28 09:29:19 +090052import android.content.pm.PackageParser.ApkLite;
53import android.content.pm.PackageParser.PackageLite;
54import android.content.pm.PackageParser.PackageParserException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070055import android.content.pm.ParceledListSlice;
56import android.content.pm.PermissionGroupInfo;
57import android.content.pm.PermissionInfo;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080058import android.content.pm.ResolveInfo;
Suprabh Shukla389cb6f2018-10-01 18:20:39 -070059import android.content.pm.SuspendDialogInfo;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070060import android.content.pm.UserInfo;
Svet Ganov67882122016-12-11 16:36:34 -080061import android.content.pm.VersionedPackage;
Calin Juravle21216c62018-05-04 17:35:29 -070062import android.content.pm.dex.ArtManager;
Calin Juravle3fc56c32017-12-11 18:26:13 -080063import android.content.pm.dex.DexMetadataHelper;
Calin Juravle21216c62018-05-04 17:35:29 -070064import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
Winson14ff7172019-10-23 10:42:27 -070065import android.content.pm.parsing.ApkLiteParseUtils;
Todd Kennedy60459ab2015-10-30 11:32:16 -070066import android.content.res.AssetManager;
67import android.content.res.Resources;
Narayan Kamathc5d752e2019-01-23 14:06:35 +000068import android.content.rollback.IRollbackManager;
69import android.content.rollback.PackageRollbackInfo;
70import android.content.rollback.RollbackInfo;
71import android.content.rollback.RollbackManager;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080072import android.net.Uri;
73import android.os.Binder;
74import android.os.Build;
75import android.os.Bundle;
Dianne Hackborn98305522017-05-05 17:53:53 -070076import android.os.IBinder;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070077import android.os.IUserManager;
Dianne Hackbornca3872c2017-10-30 14:19:32 -070078import android.os.ParcelFileDescriptor;
Calin Juravle21216c62018-05-04 17:35:29 -070079import android.os.ParcelFileDescriptor.AutoCloseInputStream;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080080import android.os.PersistableBundle;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070081import android.os.Process;
Bookatz2b5a6012019-04-16 19:41:28 -070082import android.os.RemoteCallback;
Todd Kennedy60459ab2015-10-30 11:32:16 -070083import android.os.RemoteException;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070084import android.os.ServiceManager;
Valentin Iftime89df4c82019-08-23 13:02:50 +020085import android.os.ServiceSpecificException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070086import android.os.ShellCommand;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070087import android.os.SystemClock;
Calin Juravle8bc758b2016-03-28 12:31:52 +010088import android.os.SystemProperties;
Todd Kennedy60459ab2015-10-30 11:32:16 -070089import android.os.UserHandle;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070090import android.os.UserManager;
91import android.os.storage.StorageManager;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -070092import android.permission.IPermissionManager;
Calin Juravlebdd94d92018-05-17 01:23:15 -070093import android.system.ErrnoException;
94import android.system.Os;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080095import android.text.TextUtils;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070096import android.text.format.DateUtils;
Fyodor Kupolov51245c72016-12-01 11:34:10 -080097import android.util.ArraySet;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080098import android.util.PrintWriterPrinter;
Nikita Ioffebf883482019-08-08 22:09:31 +010099import android.util.SparseArray;
Dario Freni2bef1762018-06-01 14:02:08 +0100100
Shunta Sato4f26cb52016-06-28 09:29:19 +0900101import com.android.internal.content.PackageHelper;
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700102import com.android.internal.util.ArrayUtils;
Nikita Ioffebf883482019-08-08 22:09:31 +0100103import com.android.internal.util.IndentingPrintWriter;
Alex Chauc12189b2018-01-16 15:01:15 +0000104import com.android.server.LocalServices;
Fyodor Kupolov51245c72016-12-01 11:34:10 -0800105import com.android.server.SystemConfig;
Dario Freni2bef1762018-06-01 14:02:08 +0100106
Andreas Gampebdd30d82016-03-20 11:32:11 -0700107import dalvik.system.DexFile;
Dario Freni2bef1762018-06-01 14:02:08 +0100108
109import libcore.io.IoUtils;
110import libcore.io.Streams;
111
Calin Juravle21216c62018-05-04 17:35:29 -0700112import java.io.File;
113import java.io.FileOutputStream;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800114import java.io.IOException;
Calin Juravle21216c62018-05-04 17:35:29 -0700115import java.io.InputStream;
116import java.io.OutputStream;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700117import java.io.PrintWriter;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800118import java.net.URISyntaxException;
Alex Buynytskyyda208152019-11-11 09:34:05 -0800119import java.nio.charset.StandardCharsets;
Calin Juravle21216c62018-05-04 17:35:29 -0700120import java.util.ArrayList;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000121import java.util.Collection;
Calin Juravle21216c62018-05-04 17:35:29 -0700122import java.util.Collections;
123import java.util.Comparator;
124import java.util.LinkedList;
125import java.util.List;
126import java.util.Map;
127import java.util.Objects;
128import java.util.WeakHashMap;
Bookatz2b5a6012019-04-16 19:41:28 -0700129import java.util.concurrent.CompletableFuture;
Calin Juravle21216c62018-05-04 17:35:29 -0700130import java.util.concurrent.CountDownLatch;
wangmingming155414292018-04-10 09:35:25 +0800131import java.util.concurrent.LinkedBlockingQueue;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800132import java.util.concurrent.TimeUnit;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700133
134class PackageManagerShellCommand extends ShellCommand {
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700135 /** Path for streaming APK content */
136 private static final String STDIN_PATH = "-";
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -0800137 private static final byte[] STDIN_PATH_BYTES = "-".getBytes(StandardCharsets.UTF_8);
Calin Juravle21216c62018-05-04 17:35:29 -0700138 /** Path where ART profiles snapshots are dumped for the shell user */
139 private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +0100140 private static final int DEFAULT_WAIT_MS = 60 * 1000;
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700141
Todd Kennedy60459ab2015-10-30 11:32:16 -0700142 final IPackageManager mInterface;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700143 final IPermissionManager mPermissionManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700144 final private WeakHashMap<String, Resources> mResourceCache =
145 new WeakHashMap<String, Resources>();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800146 int mTargetUser;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700147 boolean mBrief;
148 boolean mComponents;
Ng Zhi An73971312018-09-11 21:39:14 -0700149 int mQueryFlags;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700150
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700151 PackageManagerShellCommand(
152 PackageManagerService service, IPermissionManager permissionManager) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700153 mInterface = service;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700154 mPermissionManager = permissionManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700155 }
156
157 @Override
158 public int onCommand(String cmd) {
159 if (cmd == null) {
160 return handleDefaultCommands(cmd);
161 }
162
163 final PrintWriter pw = getOutPrintWriter();
164 try {
Alex Buynytskyy476138c2019-12-20 14:41:47 -0800165 switch (cmd) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700166 case "path":
167 return runPath();
168 case "dump":
169 return runDump();
170 case "list":
171 return runList();
172 case "resolve-activity":
173 return runResolveActivity();
174 case "query-activities":
175 return runQueryIntentActivities();
176 case "query-services":
177 return runQueryIntentServices();
178 case "query-receivers":
179 return runQueryIntentReceivers();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800180 case "install":
181 return runInstall();
Alex Buynytskyyda208152019-11-11 09:34:05 -0800182 case "install-streaming":
183 return runStreamingInstall();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800184 case "install-abandon":
185 case "install-destroy":
186 return runInstallAbandon();
187 case "install-commit":
188 return runInstallCommit();
189 case "install-create":
190 return runInstallCreate();
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800191 case "install-remove":
192 return runInstallRemove();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800193 case "install-write":
194 return runInstallWrite();
Todd Kennedybe0b8892017-02-15 14:13:52 -0800195 case "install-existing":
196 return runInstallExisting();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700197 case "set-install-location":
198 return runSetInstallLocation();
199 case "get-install-location":
200 return runGetInstallLocation();
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000201 case "install-add-session":
202 return runInstallAddSession();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700203 case "move-package":
204 return runMovePackage();
205 case "move-primary-storage":
206 return runMovePrimaryStorage();
David Brazdil493411a2016-02-01 13:48:46 +0000207 case "compile":
208 return runCompile();
Calin Juravle1aa5f882017-01-25 01:05:50 -0800209 case "reconcile-secondary-dex-files":
210 return runreconcileSecondaryDexFiles();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700211 case "force-dex-opt":
212 return runForceDexOpt();
Calin Juravlecb5f41e2017-01-25 17:16:08 -0800213 case "bg-dexopt-job":
214 return runDexoptJob();
David Sehra8777082016-05-24 15:25:23 -0700215 case "dump-profiles":
216 return runDumpProfiles();
Calin Juravle21216c62018-05-04 17:35:29 -0700217 case "snapshot-profile":
218 return runSnapshotProfile();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800219 case "uninstall":
220 return runUninstall();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700221 case "clear":
222 return runClear();
223 case "enable":
224 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
225 case "disable":
226 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
227 case "disable-user":
228 return runSetEnabledSetting(
229 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
230 case "disable-until-used":
231 return runSetEnabledSetting(
232 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
233 case "default-state":
234 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
235 case "hide":
236 return runSetHiddenSetting(true);
237 case "unhide":
238 return runSetHiddenSetting(false);
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000239 case "suspend":
240 return runSuspend(true);
241 case "unsuspend":
242 return runSuspend(false);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700243 case "grant":
244 return runGrantRevokePermission(true);
245 case "revoke":
246 return runGrantRevokePermission(false);
247 case "reset-permissions":
248 return runResetPermissions();
249 case "set-permission-enforced":
250 return runSetPermissionEnforced();
Fyodor Kupolov51245c72016-12-01 11:34:10 -0800251 case "get-privapp-permissions":
252 return runGetPrivappPermissions();
Todd Kennedy74629e32017-08-15 14:48:07 -0700253 case "get-privapp-deny-permissions":
254 return runGetPrivappDenyPermissions();
Svet Ganov087dce22017-09-07 15:42:16 -0700255 case "get-oem-permissions":
256 return runGetOemPermissions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700257 case "set-app-link":
258 return runSetAppLink();
259 case "get-app-link":
260 return runGetAppLink();
261 case "trim-caches":
262 return runTrimCaches();
263 case "create-user":
264 return runCreateUser();
265 case "remove-user":
266 return runRemoveUser();
267 case "set-user-restriction":
268 return runSetUserRestriction();
269 case "get-max-users":
270 return runGetMaxUsers();
Alex Chauc12189b2018-01-16 15:01:15 +0000271 case "get-max-running-users":
272 return runGetMaxRunningUsers();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700273 case "set-home-activity":
274 return runSetHomeActivity();
275 case "set-installer":
276 return runSetInstaller();
Todd Kennedy0a3f0812017-05-08 14:43:15 -0700277 case "get-instantapp-resolver":
278 return runGetInstantAppResolver();
Tadashi G. Takaokabe5782f2017-02-14 16:41:49 +0900279 case "has-feature":
280 return runHasFeature();
Ben Gruver1ab3d6e2017-12-07 13:45:08 -0800281 case "set-harmful-app-warning":
282 return runSetHarmfulAppWarning();
Ben Gruver9ef60092018-01-10 11:32:30 -0800283 case "get-harmful-app-warning":
284 return runGetHarmfulAppWarning();
Abhijeet Kaur84b1f5d2019-01-21 17:18:03 +0000285 case "get-stagedsessions":
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100286 return runListStagedSessions();
Patrick Baumanna980e142018-02-12 11:45:23 -0800287 case "uninstall-system-updates":
288 return uninstallSystemUpdates();
Narayan Kamathc5d752e2019-01-23 14:06:35 +0000289 case "rollback-app":
290 return runRollbackApp();
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +0100291 case "get-moduleinfo":
292 return runGetModuleInfo();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700293 default: {
294 String nextArg = getNextArg();
295 if (nextArg == null) {
296 if (cmd.equalsIgnoreCase("-l")) {
297 return runListPackages(false);
298 } else if (cmd.equalsIgnoreCase("-lf")) {
299 return runListPackages(true);
300 }
301 } else if (getNextArg() == null) {
302 if (cmd.equalsIgnoreCase("-p")) {
303 return displayPackageFilePath(nextArg, UserHandle.USER_SYSTEM);
304 }
305 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700306 return handleDefaultCommands(cmd);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700307 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700308 }
309 } catch (RemoteException e) {
310 pw.println("Remote exception: " + e);
311 }
312 return -1;
313 }
314
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +0100315 /**
316 * Shows module info
317 *
318 * Usage: get-moduleinfo [--all | --installed] [module-name]
319 * Example: get-moduleinfo, get-moduleinfo --all, get-moduleinfo xyz
320 */
321 private int runGetModuleInfo() {
322 final PrintWriter pw = getOutPrintWriter();
323 int flags = 0;
324
325 String opt;
326 while ((opt = getNextOption()) != null) {
327 switch (opt) {
328 case "--all":
329 flags |= PackageManager.MATCH_ALL;
330 break;
331 case "--installed":
332 break;
333 default:
334 pw.println("Error: Unknown option: " + opt);
335 return -1;
336 }
337 }
338
339 String moduleName = getNextArg();
340 try {
341 if (moduleName != null) {
342 ModuleInfo m = mInterface.getModuleInfo(moduleName, flags);
343 pw.println(m.toString() + " packageName: " + m.getPackageName());
344
345 } else {
346 List<ModuleInfo> modules = mInterface.getInstalledModules(flags);
347 for (ModuleInfo m: modules) {
348 pw.println(m.toString() + " packageName: " + m.getPackageName());
349 }
350 }
351 } catch (RemoteException e) {
352 pw.println("Failure [" + e.getClass().getName() + " - " + e.getMessage() + "]");
353 return -1;
354 }
355 return 1;
356 }
357
Patrick Baumanna980e142018-02-12 11:45:23 -0800358 private int uninstallSystemUpdates() {
359 final PrintWriter pw = getOutPrintWriter();
360 List<String> failedUninstalls = new LinkedList<>();
361 try {
362 final ParceledListSlice<ApplicationInfo> packages =
363 mInterface.getInstalledApplications(
364 PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
365 final IPackageInstaller installer = mInterface.getPackageInstaller();
366 List<ApplicationInfo> list = packages.getList();
367 for (ApplicationInfo info : list) {
368 if (info.isUpdatedSystemApp()) {
369 pw.println("Uninstalling updates to " + info.packageName + "...");
370 final LocalIntentReceiver receiver = new LocalIntentReceiver();
371 installer.uninstall(new VersionedPackage(info.packageName,
372 info.versionCode), null /*callerPackageName*/, 0 /* flags */,
373 receiver.getIntentSender(), 0);
374
375 final Intent result = receiver.getResult();
376 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
377 PackageInstaller.STATUS_FAILURE);
378 if (status != PackageInstaller.STATUS_SUCCESS) {
379 failedUninstalls.add(info.packageName);
380 }
381 }
382 }
383 } catch (RemoteException e) {
384 pw.println("Failure ["
385 + e.getClass().getName() + " - "
386 + e.getMessage() + "]");
387 return 0;
388 }
389 if (!failedUninstalls.isEmpty()) {
390 pw.println("Failure [Couldn't uninstall packages: "
391 + TextUtils.join(", ", failedUninstalls)
392 + "]");
393 return 0;
394 }
395 pw.println("Success");
396 return 1;
397 }
398
Narayan Kamathc5d752e2019-01-23 14:06:35 +0000399 private int runRollbackApp() {
400 final PrintWriter pw = getOutPrintWriter();
401
402 final String packageName = getNextArgRequired();
403 if (packageName == null) {
404 pw.println("Error: package name not specified");
405 return 1;
406 }
407
408 final LocalIntentReceiver receiver = new LocalIntentReceiver();
409 try {
410 IRollbackManager rm = IRollbackManager.Stub.asInterface(
411 ServiceManager.getService(Context.ROLLBACK_SERVICE));
412
413 RollbackInfo rollback = null;
414 for (RollbackInfo r : (List<RollbackInfo>) rm.getAvailableRollbacks().getList()) {
415 for (PackageRollbackInfo info : r.getPackages()) {
416 if (packageName.equals(info.getPackageName())) {
417 rollback = r;
418 break;
419 }
420 }
421 }
422
423 if (rollback == null) {
424 pw.println("No available rollbacks for: " + packageName);
425 return 1;
426 }
427
428 rm.commitRollback(rollback.getRollbackId(),
429 ParceledListSlice.<VersionedPackage>emptyList(),
430 "com.android.shell", receiver.getIntentSender());
431 } catch (RemoteException re) {
432 // Cannot happen.
433 }
434
435 final Intent result = receiver.getResult();
436 final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
437 RollbackManager.STATUS_FAILURE);
438 if (status == RollbackManager.STATUS_SUCCESS) {
439 pw.println("Success");
440 return 0;
441 } else {
442 pw.println("Failure ["
443 + result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE) + "]");
444 return 1;
445 }
446 }
447
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000448 private void setParamsSize(InstallParams params, List<String> inPaths) {
449 if (params.sessionParams.sizeBytes != -1 || STDIN_PATH.equals(inPaths.get(0))) {
450 return;
451 }
452
453 long sessionSize = 0;
454
455 for (String inPath : inPaths) {
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700456 final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");
457 if (fd == null) {
458 getErrPrintWriter().println("Error: Can't open file: " + inPath);
459 throw new IllegalArgumentException("Error: Can't open file: " + inPath);
460 }
461 try {
Winson14ff7172019-10-23 10:42:27 -0700462 ApkLite baseApk = ApkLiteParseUtils.parseApkLite(fd.getFileDescriptor(), inPath, 0);
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700463 PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
464 null, null);
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000465 sessionSize += PackageHelper.calculateInstalledSize(pkgLite,
466 params.sessionParams.abiOverride, fd.getFileDescriptor());
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700467 } catch (PackageParserException | IOException e) {
468 getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath);
469 throw new IllegalArgumentException(
470 "Error: Failed to parse APK file: " + inPath, e);
471 } finally {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900472 try {
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700473 fd.close();
474 } catch (IOException e) {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900475 }
476 }
477 }
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -0800478
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000479 params.sessionParams.setSize(sessionSize);
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700480 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700481 /**
482 * Displays the package file for a package.
483 * @param pckg
484 */
485 private int displayPackageFilePath(String pckg, int userId) throws RemoteException {
Bill Lin7fd81af2019-10-04 00:31:21 +0800486 PackageInfo info = mInterface.getPackageInfo(pckg, PackageManager.MATCH_APEX, userId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700487 if (info != null && info.applicationInfo != null) {
488 final PrintWriter pw = getOutPrintWriter();
489 pw.print("package:");
490 pw.println(info.applicationInfo.sourceDir);
491 if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
492 for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
493 pw.print("package:");
494 pw.println(splitSourceDir);
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800495 }
496 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700497 return 0;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800498 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700499 return 1;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800500 }
501
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700502 private int runPath() throws RemoteException {
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000503 int userId = UserHandle.USER_SYSTEM;
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700504 String option = getNextOption();
505 if (option != null && option.equals("--user")) {
506 userId = UserHandle.parseUserArg(getNextArgRequired());
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000507 }
508
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700509 String pkg = getNextArgRequired();
510 if (pkg == null) {
511 getErrPrintWriter().println("Error: no package specified");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000512 return 1;
513 }
Todd Kennedyc3c52172019-11-26 13:20:59 -0800514 final int translatedUserId =
515 translateUserId(userId, UserHandle.USER_NULL, "runPath");
516 return displayPackageFilePath(pkg, translatedUserId);
David Sehra8777082016-05-24 15:25:23 -0700517 }
518
Todd Kennedy60459ab2015-10-30 11:32:16 -0700519 private int runList() throws RemoteException {
520 final PrintWriter pw = getOutPrintWriter();
521 final String type = getNextArg();
522 if (type == null) {
523 pw.println("Error: didn't specify type of data to list");
524 return -1;
525 }
526 switch(type) {
527 case "features":
528 return runListFeatures();
529 case "instrumentation":
530 return runListInstrumentation();
531 case "libraries":
532 return runListLibraries();
533 case "package":
534 case "packages":
535 return runListPackages(false /*showSourceDir*/);
536 case "permission-groups":
537 return runListPermissionGroups();
538 case "permissions":
539 return runListPermissions();
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100540 case "staged-sessions":
541 return runListStagedSessions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700542 case "users":
543 ServiceManager.getService("user").shellCommand(
544 getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
545 new String[] { "list" }, getShellCallback(), adoptResultReceiver());
546 return 0;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700547 }
548 pw.println("Error: unknown list type '" + type + "'");
549 return -1;
550 }
551
552 private int runListFeatures() throws RemoteException {
553 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700554 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700555
556 // sort by name
557 Collections.sort(list, new Comparator<FeatureInfo>() {
558 public int compare(FeatureInfo o1, FeatureInfo o2) {
559 if (o1.name == o2.name) return 0;
560 if (o1.name == null) return -1;
561 if (o2.name == null) return 1;
562 return o1.name.compareTo(o2.name);
563 }
564 });
565
566 final int count = (list != null) ? list.size() : 0;
567 for (int p = 0; p < count; p++) {
568 FeatureInfo fi = list.get(p);
569 pw.print("feature:");
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700570 if (fi.name != null) {
571 pw.print(fi.name);
572 if (fi.version > 0) {
573 pw.print("=");
574 pw.print(fi.version);
575 }
576 pw.println();
577 } else {
578 pw.println("reqGlEsVersion=0x"
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700579 + Integer.toHexString(fi.reqGlEsVersion));
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700580 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700581 }
582 return 0;
583 }
584
585 private int runListInstrumentation() throws RemoteException {
586 final PrintWriter pw = getOutPrintWriter();
587 boolean showSourceDir = false;
588 String targetPackage = null;
589
590 try {
591 String opt;
592 while ((opt = getNextArg()) != null) {
593 switch (opt) {
594 case "-f":
595 showSourceDir = true;
596 break;
597 default:
598 if (opt.charAt(0) != '-') {
599 targetPackage = opt;
600 } else {
601 pw.println("Error: Unknown option: " + opt);
602 return -1;
603 }
604 break;
605 }
606 }
607 } catch (RuntimeException ex) {
608 pw.println("Error: " + ex.toString());
609 return -1;
610 }
611
612 final List<InstrumentationInfo> list =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700613 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700614
615 // sort by target package
616 Collections.sort(list, new Comparator<InstrumentationInfo>() {
617 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
618 return o1.targetPackage.compareTo(o2.targetPackage);
619 }
620 });
621
622 final int count = (list != null) ? list.size() : 0;
623 for (int p = 0; p < count; p++) {
624 final InstrumentationInfo ii = list.get(p);
625 pw.print("instrumentation:");
626 if (showSourceDir) {
627 pw.print(ii.sourceDir);
628 pw.print("=");
629 }
630 final ComponentName cn = new ComponentName(ii.packageName, ii.name);
631 pw.print(cn.flattenToShortString());
632 pw.print(" (target=");
633 pw.print(ii.targetPackage);
634 pw.println(")");
635 }
636 return 0;
637 }
638
639 private int runListLibraries() throws RemoteException {
640 final PrintWriter pw = getOutPrintWriter();
641 final List<String> list = new ArrayList<String>();
642 final String[] rawList = mInterface.getSystemSharedLibraryNames();
643 for (int i = 0; i < rawList.length; i++) {
644 list.add(rawList[i]);
645 }
646
647 // sort by name
648 Collections.sort(list, new Comparator<String>() {
649 public int compare(String o1, String o2) {
650 if (o1 == o2) return 0;
651 if (o1 == null) return -1;
652 if (o2 == null) return 1;
653 return o1.compareTo(o2);
654 }
655 });
656
657 final int count = (list != null) ? list.size() : 0;
658 for (int p = 0; p < count; p++) {
659 String lib = list.get(p);
660 pw.print("library:");
661 pw.println(lib);
662 }
663 return 0;
664 }
665
666 private int runListPackages(boolean showSourceDir) throws RemoteException {
667 final PrintWriter pw = getOutPrintWriter();
668 int getFlags = 0;
669 boolean listDisabled = false, listEnabled = false;
670 boolean listSystem = false, listThirdParty = false;
671 boolean listInstaller = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700672 boolean showUid = false;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800673 boolean showVersionCode = false;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900674 boolean listApexOnly = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700675 int uid = -1;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700676 int userId = UserHandle.USER_SYSTEM;
677 try {
678 String opt;
679 while ((opt = getNextOption()) != null) {
680 switch (opt) {
681 case "-d":
682 listDisabled = true;
683 break;
684 case "-e":
685 listEnabled = true;
686 break;
Andreas Gampe1f110452018-06-04 11:47:48 -0700687 case "-a":
688 getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
689 getFlags |= PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS;
690 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700691 case "-f":
692 showSourceDir = true;
693 break;
694 case "-i":
695 listInstaller = true;
696 break;
697 case "-l":
698 // old compat
699 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700700 case "-s":
701 listSystem = true;
702 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700703 case "-U":
704 showUid = true;
705 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700706 case "-u":
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700707 getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700708 break;
709 case "-3":
710 listThirdParty = true;
711 break;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800712 case "--show-versioncode":
713 showVersionCode = true;
714 break;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900715 case "--apex-only":
716 getFlags |= PackageManager.MATCH_APEX;
717 listApexOnly = true;
718 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700719 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800720 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy60459ab2015-10-30 11:32:16 -0700721 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700722 case "--uid":
723 showUid = true;
724 uid = Integer.parseInt(getNextArgRequired());
725 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700726 default:
727 pw.println("Error: Unknown option: " + opt);
728 return -1;
729 }
730 }
731 } catch (RuntimeException ex) {
732 pw.println("Error: " + ex.toString());
733 return -1;
734 }
735
736 final String filter = getNextArg();
737
Todd Kennedy5385b512019-11-26 15:49:06 -0800738 if (userId == UserHandle.USER_ALL) {
739 getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
740 }
Todd Kennedyc3c52172019-11-26 13:20:59 -0800741 final int translatedUserId =
Todd Kennedy5385b512019-11-26 15:49:06 -0800742 translateUserId(userId, UserHandle.USER_SYSTEM, "runListPackages");
Todd Kennedy60459ab2015-10-30 11:32:16 -0700743 @SuppressWarnings("unchecked")
744 final ParceledListSlice<PackageInfo> slice =
Todd Kennedyc3c52172019-11-26 13:20:59 -0800745 mInterface.getInstalledPackages(getFlags, translatedUserId);
Todd Kennedy60459ab2015-10-30 11:32:16 -0700746 final List<PackageInfo> packages = slice.getList();
747
748 final int count = packages.size();
749 for (int p = 0; p < count; p++) {
750 final PackageInfo info = packages.get(p);
751 if (filter != null && !info.packageName.contains(filter)) {
752 continue;
753 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900754 final boolean isApex = info.isApex;
755 if (uid != -1 && !isApex && info.applicationInfo.uid != uid) {
Felipe Lemeeece9862016-06-29 11:45:03 -0700756 continue;
757 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900758
759 final boolean isSystem = !isApex &&
Todd Kennedy60459ab2015-10-30 11:32:16 -0700760 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900761 final boolean isEnabled = !isApex && info.applicationInfo.enabled;
762 if ((!listDisabled || !isEnabled) &&
763 (!listEnabled || isEnabled) &&
Todd Kennedy60459ab2015-10-30 11:32:16 -0700764 (!listSystem || isSystem) &&
Jiyong Park4f49abe2018-12-11 13:37:17 +0900765 (!listThirdParty || !isSystem) &&
766 (!listApexOnly || isApex)) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700767 pw.print("package:");
JW Wang9a722632019-09-30 10:42:30 +0800768 if (showSourceDir) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700769 pw.print(info.applicationInfo.sourceDir);
770 pw.print("=");
771 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800772 pw.print(info.packageName);
Jiyong Parkf50a2932018-12-17 13:54:40 +0900773 if (showVersionCode) {
Todd Kennedybadc69a2017-01-24 11:05:47 -0800774 pw.print(" versionCode:");
Jiyong Parkf50a2932018-12-17 13:54:40 +0900775 if (info.applicationInfo != null) {
Dario Freni788ecb12019-01-23 18:49:32 +0000776 pw.print(info.applicationInfo.longVersionCode);
Jiyong Parkf50a2932018-12-17 13:54:40 +0900777 } else {
Dario Freni788ecb12019-01-23 18:49:32 +0000778 pw.print(info.getLongVersionCode());
Jiyong Parkf50a2932018-12-17 13:54:40 +0900779 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800780 }
Mohammad Samiul Islam6b7ad942019-05-07 20:28:00 +0100781 if (listInstaller) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700782 pw.print(" installer=");
783 pw.print(mInterface.getInstallerPackageName(info.packageName));
784 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900785 if (showUid && !isApex) {
Felipe Lemeeece9862016-06-29 11:45:03 -0700786 pw.print(" uid:");
787 pw.print(info.applicationInfo.uid);
788 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700789 pw.println();
790 }
791 }
792 return 0;
793 }
794
795 private int runListPermissionGroups() throws RemoteException {
796 final PrintWriter pw = getOutPrintWriter();
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700797 final List<PermissionGroupInfo> pgs =
798 mPermissionManager.getAllPermissionGroups(0).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700799
800 final int count = pgs.size();
801 for (int p = 0; p < count ; p++) {
802 final PermissionGroupInfo pgi = pgs.get(p);
803 pw.print("permission group:");
804 pw.println(pgi.name);
805 }
806 return 0;
807 }
808
809 private int runListPermissions() throws RemoteException {
810 final PrintWriter pw = getOutPrintWriter();
811 boolean labels = false;
812 boolean groups = false;
813 boolean userOnly = false;
814 boolean summary = false;
815 boolean dangerousOnly = false;
816 String opt;
817 while ((opt = getNextOption()) != null) {
818 switch (opt) {
819 case "-d":
820 dangerousOnly = true;
821 break;
822 case "-f":
823 labels = true;
824 break;
825 case "-g":
826 groups = true;
827 break;
828 case "-s":
829 groups = true;
830 labels = true;
831 summary = true;
832 break;
833 case "-u":
834 userOnly = true;
835 break;
836 default:
837 pw.println("Error: Unknown option: " + opt);
838 return 1;
839 }
840 }
841
842 final ArrayList<String> groupList = new ArrayList<String>();
843 if (groups) {
844 final List<PermissionGroupInfo> infos =
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700845 mPermissionManager.getAllPermissionGroups(0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700846 final int count = infos.size();
847 for (int i = 0; i < count; i++) {
848 groupList.add(infos.get(i).name);
849 }
850 groupList.add(null);
851 } else {
852 final String grp = getNextArg();
853 groupList.add(grp);
854 }
855
856 if (dangerousOnly) {
857 pw.println("Dangerous Permissions:");
858 pw.println("");
859 doListPermissions(groupList, groups, labels, summary,
860 PermissionInfo.PROTECTION_DANGEROUS,
861 PermissionInfo.PROTECTION_DANGEROUS);
862 if (userOnly) {
863 pw.println("Normal Permissions:");
864 pw.println("");
865 doListPermissions(groupList, groups, labels, summary,
866 PermissionInfo.PROTECTION_NORMAL,
867 PermissionInfo.PROTECTION_NORMAL);
868 }
869 } else if (userOnly) {
870 pw.println("Dangerous and Normal Permissions:");
871 pw.println("");
872 doListPermissions(groupList, groups, labels, summary,
873 PermissionInfo.PROTECTION_NORMAL,
874 PermissionInfo.PROTECTION_DANGEROUS);
875 } else {
876 pw.println("All Permissions:");
877 pw.println("");
878 doListPermissions(groupList, groups, labels, summary,
879 -10000, 10000);
880 }
881 return 0;
882 }
883
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100884 private static class SessionDump {
885 boolean onlyParent; // Show parent sessions only
886 boolean onlyReady; // Show only staged sessions that are in ready state
887 boolean onlySessionId; // Show sessionId only
888 }
889
890 // Returns true if the provided flag is a session flag and given SessionDump was updated
891 private boolean setSessionFlag(String flag, SessionDump sessionDump) {
892 switch (flag) {
893 case "--only-parent":
894 sessionDump.onlyParent = true;
895 break;
896 case "--only-ready":
897 sessionDump.onlyReady = true;
898 break;
899 case "--only-sessionid":
900 sessionDump.onlySessionId = true;
901 break;
902 default:
903 return false;
904 }
905 return true;
906 }
907
908 private int runListStagedSessions() {
Todd Kennedy5385b512019-11-26 15:49:06 -0800909 try (IndentingPrintWriter pw = new IndentingPrintWriter(
910 getOutPrintWriter(), /* singleIndent */ " ", /* wrapLength */ 120)) {
911 final SessionDump sessionDump = new SessionDump();
912 String opt;
913 while ((opt = getNextOption()) != null) {
914 if (!setSessionFlag(opt, sessionDump)) {
915 pw.println("Error: Unknown option: " + opt);
916 return -1;
917 }
918 }
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100919
Todd Kennedy5385b512019-11-26 15:49:06 -0800920 try {
921 final List<SessionInfo> stagedSessions =
922 mInterface.getPackageInstaller().getStagedSessions().getList();
923 printSessionList(pw, stagedSessions, sessionDump);
924 } catch (RemoteException e) {
925 pw.println("Failure ["
926 + e.getClass().getName() + " - "
927 + e.getMessage() + "]");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100928 return -1;
929 }
Todd Kennedy5385b512019-11-26 15:49:06 -0800930 return 1;
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100931 }
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100932 }
933
934 private void printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions,
935 SessionDump sessionDump) {
936 final SparseArray<SessionInfo> sessionById = new SparseArray<>(stagedSessions.size());
937 for (SessionInfo session : stagedSessions) {
938 sessionById.put(session.getSessionId(), session);
939 }
940 for (SessionInfo session: stagedSessions) {
941 if (sessionDump.onlyReady && !session.isStagedSessionReady()) {
942 continue;
943 }
944 if (session.getParentSessionId() != SessionInfo.INVALID_ID) {
945 continue;
946 }
947 printSession(pw, session, sessionDump);
948 if (session.isMultiPackage() && !sessionDump.onlyParent) {
949 pw.increaseIndent();
950 final int[] childIds = session.getChildSessionIds();
951 for (int i = 0; i < childIds.length; i++) {
952 final SessionInfo childSession = sessionById.get(childIds[i]);
953 if (childSession == null) {
954 if (sessionDump.onlySessionId) {
955 pw.println(childIds[i]);
956 } else {
957 pw.println("sessionId = " + childIds[i] + "; not found");
958 }
959 } else {
960 printSession(pw, childSession, sessionDump);
961 }
962 }
963 pw.decreaseIndent();
964 }
965 }
966 }
967
968 private static void printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump) {
969 if (sessionDump.onlySessionId) {
970 pw.println(session.getSessionId());
971 return;
972 }
973 pw.println("sessionId = " + session.getSessionId()
974 + "; appPackageName = " + session.getAppPackageName()
975 + "; isStaged = " + session.isStaged()
976 + "; isReady = " + session.isStagedSessionReady()
977 + "; isApplied = " + session.isStagedSessionApplied()
978 + "; isFailed = " + session.isStagedSessionFailed() + ";");
979 }
980
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800981 private Intent parseIntentAndUser() throws URISyntaxException {
982 mTargetUser = UserHandle.USER_CURRENT;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700983 mBrief = false;
984 mComponents = false;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800985 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
986 @Override
987 public boolean handleOption(String opt, ShellCommand cmd) {
988 if ("--user".equals(opt)) {
989 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
990 return true;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700991 } else if ("--brief".equals(opt)) {
992 mBrief = true;
993 return true;
994 } else if ("--components".equals(opt)) {
995 mComponents = true;
996 return true;
Ng Zhi An73971312018-09-11 21:39:14 -0700997 } else if ("--query-flags".equals(opt)) {
998 mQueryFlags = Integer.decode(cmd.getNextArgRequired());
999 return true;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001000 }
1001 return false;
1002 }
1003 });
1004 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1005 Binder.getCallingUid(), mTargetUser, false, false, null, null);
1006 return intent;
1007 }
1008
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001009 private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri,
1010 boolean brief, boolean components) {
1011 if (brief || components) {
1012 final ComponentName comp;
1013 if (ri.activityInfo != null) {
1014 comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
1015 } else if (ri.serviceInfo != null) {
1016 comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
1017 } else if (ri.providerInfo != null) {
1018 comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name);
1019 } else {
1020 comp = null;
1021 }
1022 if (comp != null) {
1023 if (!components) {
1024 pr.println(prefix + "priority=" + ri.priority
1025 + " preferredOrder=" + ri.preferredOrder
1026 + " match=0x" + Integer.toHexString(ri.match)
1027 + " specificIndex=" + ri.specificIndex
1028 + " isDefault=" + ri.isDefault);
1029 }
1030 pr.println(prefix + comp.flattenToShortString());
1031 return;
1032 }
1033 }
1034 ri.dump(pr, prefix);
1035 }
1036
Dianne Hackborn99878e92015-12-02 16:27:41 -08001037 private int runResolveActivity() {
1038 Intent intent;
1039 try {
1040 intent = parseIntentAndUser();
1041 } catch (URISyntaxException e) {
1042 throw new RuntimeException(e.getMessage(), e);
1043 }
1044 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001045 ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), mQueryFlags,
1046 mTargetUser);
Dianne Hackborn99878e92015-12-02 16:27:41 -08001047 PrintWriter pw = getOutPrintWriter();
1048 if (ri == null) {
1049 pw.println("No activity found");
1050 } else {
1051 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001052 printResolveInfo(pr, "", ri, mBrief, mComponents);
Dianne Hackborn99878e92015-12-02 16:27:41 -08001053 }
1054 } catch (RemoteException e) {
1055 throw new RuntimeException("Failed calling service", e);
1056 }
1057 return 0;
1058 }
1059
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001060 private int runQueryIntentActivities() {
1061 Intent intent;
1062 try {
1063 intent = parseIntentAndUser();
1064 } catch (URISyntaxException e) {
1065 throw new RuntimeException(e.getMessage(), e);
1066 }
1067 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001068 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(),
1069 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001070 PrintWriter pw = getOutPrintWriter();
1071 if (result == null || result.size() <= 0) {
1072 pw.println("No activities found");
1073 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001074 if (!mComponents) {
1075 pw.print(result.size()); pw.println(" activities found:");
1076 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1077 for (int i = 0; i < result.size(); i++) {
1078 pw.print(" Activity #"); pw.print(i); pw.println(":");
1079 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1080 }
1081 } else {
1082 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1083 for (int i = 0; i < result.size(); i++) {
1084 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1085 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001086 }
1087 }
1088 } catch (RemoteException e) {
1089 throw new RuntimeException("Failed calling service", e);
1090 }
1091 return 0;
1092 }
1093
1094 private int runQueryIntentServices() {
1095 Intent intent;
1096 try {
1097 intent = parseIntentAndUser();
1098 } catch (URISyntaxException e) {
1099 throw new RuntimeException(e.getMessage(), e);
1100 }
1101 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001102 List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(),
1103 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001104 PrintWriter pw = getOutPrintWriter();
1105 if (result == null || result.size() <= 0) {
1106 pw.println("No services found");
1107 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001108 if (!mComponents) {
1109 pw.print(result.size()); pw.println(" services found:");
1110 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1111 for (int i = 0; i < result.size(); i++) {
1112 pw.print(" Service #"); pw.print(i); pw.println(":");
1113 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1114 }
1115 } else {
1116 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1117 for (int i = 0; i < result.size(); i++) {
1118 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1119 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001120 }
1121 }
1122 } catch (RemoteException e) {
1123 throw new RuntimeException("Failed calling service", e);
1124 }
1125 return 0;
1126 }
1127
1128 private int runQueryIntentReceivers() {
1129 Intent intent;
1130 try {
1131 intent = parseIntentAndUser();
1132 } catch (URISyntaxException e) {
1133 throw new RuntimeException(e.getMessage(), e);
1134 }
1135 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001136 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(),
1137 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001138 PrintWriter pw = getOutPrintWriter();
1139 if (result == null || result.size() <= 0) {
1140 pw.println("No receivers found");
1141 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001142 if (!mComponents) {
1143 pw.print(result.size()); pw.println(" receivers found:");
1144 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1145 for (int i = 0; i < result.size(); i++) {
1146 pw.print(" Receiver #"); pw.print(i); pw.println(":");
1147 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1148 }
1149 } else {
1150 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1151 for (int i = 0; i < result.size(); i++) {
1152 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1153 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001154 }
1155 }
1156 } catch (RemoteException e) {
1157 throw new RuntimeException("Failed calling service", e);
1158 }
1159 return 0;
1160 }
1161
Alex Buynytskyyda208152019-11-11 09:34:05 -08001162 private int runStreamingInstall() throws RemoteException {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001163 final InstallParams params = makeInstallParams();
Alex Buynytskyy1ecfcec2019-12-17 12:10:41 -08001164 if (params.sessionParams.dataLoaderParams == null) {
Alex Buynytskyy476138c2019-12-20 14:41:47 -08001165 params.sessionParams.setDataLoaderParams(
1166 PackageManagerShellCommandDataLoader.getDataLoaderParams(this));
Alex Buynytskyyda208152019-11-11 09:34:05 -08001167 }
1168 return doRunInstall(params);
1169 }
1170
1171 private int runInstall() throws RemoteException {
1172 return doRunInstall(makeInstallParams());
1173 }
1174
1175 private int doRunInstall(final InstallParams params) throws RemoteException {
1176 final PrintWriter pw = getOutPrintWriter();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001177
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001178 final boolean isStreaming = params.sessionParams.dataLoaderParams != null;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001179 final boolean isApex =
1180 (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0;
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001181
1182 ArrayList<String> args = getRemainingArgs();
1183
1184 final boolean fromStdIn = args.isEmpty() || STDIN_PATH.equals(args.get(0));
1185 final boolean hasSplits = args.size() > 1;
1186
1187 if (fromStdIn && params.sessionParams.sizeBytes == -1) {
1188 pw.println("Error: must either specify a package size or an APK file");
1189 return 1;
1190 }
1191
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001192 if (isApex && hasSplits) {
1193 pw.println("Error: can't specify SPLIT(s) for APEX");
1194 return 1;
1195 }
1196
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001197 if (!isStreaming) {
1198 if (fromStdIn && hasSplits) {
1199 pw.println("Error: can't specify SPLIT(s) along with STDIN");
1200 return 1;
1201 }
1202
1203 if (args.isEmpty()) {
1204 args.add(STDIN_PATH);
1205 } else {
1206 setParamsSize(params, args);
1207 }
Alex Buynytskyyda208152019-11-11 09:34:05 -08001208 }
1209
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001210 final int sessionId = doCreateSession(params.sessionParams,
1211 params.installerPackageName, params.userId);
1212 boolean abandonSession = true;
1213 try {
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001214 if (isStreaming) {
1215 if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex)
1216 != PackageInstaller.STATUS_SUCCESS) {
1217 return 1;
1218 }
1219 } else {
1220 if (doWriteSplits(sessionId, args, params.sessionParams.sizeBytes, isApex)
1221 != PackageInstaller.STATUS_SUCCESS) {
1222 return 1;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001223 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001224 }
1225 if (doCommitSession(sessionId, false /*logSuccess*/)
1226 != PackageInstaller.STATUS_SUCCESS) {
1227 return 1;
1228 }
1229 abandonSession = false;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01001230
Nikita Ioffe62d918c2020-01-18 01:20:42 +00001231 if (!params.sessionParams.isStaged || !params.mWaitForStagedSessionReady) {
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01001232 pw.println("Success");
1233 return 0;
1234 }
1235
1236 long timeoutMs = params.timeoutMs <= 0
1237 ? DEFAULT_WAIT_MS
1238 : params.timeoutMs;
1239 PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
1240 .getSessionInfo(sessionId);
1241 long currentTime = System.currentTimeMillis();
1242 long endTime = currentTime + timeoutMs;
1243 // Using a loop instead of BroadcastReceiver since we can receive session update
1244 // broadcast only if packageInstallerName is "android". We can't always force
1245 // "android" as packageIntallerName, e.g, rollback auto implies
1246 // "-i com.android.shell".
1247 while (currentTime < endTime) {
1248 if (si != null
1249 && (si.isStagedSessionReady() || si.isStagedSessionFailed())) {
1250 break;
1251 }
1252 SystemClock.sleep(Math.min(endTime - currentTime, 100));
1253 currentTime = System.currentTimeMillis();
1254 si = mInterface.getPackageInstaller().getSessionInfo(sessionId);
1255 }
1256 if (si == null) {
1257 pw.println("Failure [failed to retrieve SessionInfo]");
1258 return 1;
1259 }
1260 if (!si.isStagedSessionReady() && !si.isStagedSessionFailed()) {
1261 pw.println("Failure [timed out after " + timeoutMs + " ms]");
1262 return 1;
1263 }
1264 if (!si.isStagedSessionReady()) {
1265 pw.println("Error [" + si.getStagedSessionErrorCode() + "] ["
1266 + si.getStagedSessionErrorMessage() + "]");
1267 return 1;
1268 }
Nikita Ioffe62d918c2020-01-18 01:20:42 +00001269 pw.println("Success. Reboot device to apply staged session");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001270 return 0;
1271 } finally {
1272 if (abandonSession) {
1273 try {
1274 doAbandonSession(sessionId, false /*logSuccess*/);
1275 } catch (Exception ignore) {
1276 }
1277 }
1278 }
1279 }
1280
1281 private int runInstallAbandon() throws RemoteException {
1282 final int sessionId = Integer.parseInt(getNextArg());
1283 return doAbandonSession(sessionId, true /*logSuccess*/);
1284 }
1285
1286 private int runInstallCommit() throws RemoteException {
1287 final int sessionId = Integer.parseInt(getNextArg());
1288 return doCommitSession(sessionId, true /*logSuccess*/);
1289 }
1290
1291 private int runInstallCreate() throws RemoteException {
1292 final PrintWriter pw = getOutPrintWriter();
1293 final InstallParams installParams = makeInstallParams();
1294 final int sessionId = doCreateSession(installParams.sessionParams,
1295 installParams.installerPackageName, installParams.userId);
1296
1297 // NOTE: adb depends on parsing this string
1298 pw.println("Success: created install session [" + sessionId + "]");
1299 return 0;
1300 }
1301
1302 private int runInstallWrite() throws RemoteException {
1303 long sizeBytes = -1;
1304
1305 String opt;
1306 while ((opt = getNextOption()) != null) {
1307 if (opt.equals("-S")) {
1308 sizeBytes = Long.parseLong(getNextArg());
1309 } else {
1310 throw new IllegalArgumentException("Unknown option: " + opt);
1311 }
1312 }
1313
1314 final int sessionId = Integer.parseInt(getNextArg());
1315 final String splitName = getNextArg();
1316 final String path = getNextArg();
1317 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
1318 }
1319
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001320 private int runInstallAddSession() throws RemoteException {
1321 final PrintWriter pw = getOutPrintWriter();
1322 final int parentSessionId = Integer.parseInt(getNextArg());
1323
1324 List<Integer> otherSessionIds = new ArrayList<>();
1325 String opt;
1326 while ((opt = getNextArg()) != null) {
1327 otherSessionIds.add(Integer.parseInt(opt));
1328 }
1329 if (otherSessionIds.size() == 0) {
1330 pw.println("Error: At least two sessions are required.");
1331 return 1;
1332 }
1333 return doInstallAddSession(parentSessionId, ArrayUtils.convertToIntArray(otherSessionIds),
1334 true /*logSuccess*/);
1335 }
1336
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001337 private int runInstallRemove() throws RemoteException {
1338 final PrintWriter pw = getOutPrintWriter();
1339
1340 final int sessionId = Integer.parseInt(getNextArg());
1341
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001342 ArrayList<String> splitNames = getRemainingArgs();
1343 if (splitNames.isEmpty()) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001344 pw.println("Error: split name not specified");
1345 return 1;
1346 }
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001347 return doRemoveSplits(sessionId, splitNames, true /*logSuccess*/);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001348 }
1349
1350 private int runInstallExisting() throws RemoteException {
1351 final PrintWriter pw = getOutPrintWriter();
Todd Kennedybef39e02019-09-20 15:14:18 -07001352 int userId = UserHandle.USER_CURRENT;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001353 int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001354 String opt;
Chandan Nathe8e463b2019-01-28 15:23:38 +00001355 boolean waitTillComplete = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001356 while ((opt = getNextOption()) != null) {
1357 switch (opt) {
1358 case "--user":
1359 userId = UserHandle.parseUserArg(getNextArgRequired());
1360 break;
1361 case "--ephemeral":
1362 case "--instant":
1363 installFlags |= PackageManager.INSTALL_INSTANT_APP;
1364 installFlags &= ~PackageManager.INSTALL_FULL_APP;
1365 break;
1366 case "--full":
1367 installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1368 installFlags |= PackageManager.INSTALL_FULL_APP;
1369 break;
Chandan Nathe8e463b2019-01-28 15:23:38 +00001370 case "--wait":
1371 waitTillComplete = true;
1372 break;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001373 case "--restrict-permissions":
1374 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1375 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001376 default:
1377 pw.println("Error: Unknown option: " + opt);
1378 return 1;
1379 }
1380 }
1381
1382 final String packageName = getNextArg();
1383 if (packageName == null) {
1384 pw.println("Error: package name not specified");
1385 return 1;
1386 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08001387 final int translatedUserId =
1388 translateUserId(userId, UserHandle.USER_NULL, "runInstallExisting");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001389
Chandan Nathe8e463b2019-01-28 15:23:38 +00001390 int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001391 try {
Chandan Nathe8e463b2019-01-28 15:23:38 +00001392 if (waitTillComplete) {
1393 final LocalIntentReceiver receiver = new LocalIntentReceiver();
1394 final IPackageInstaller installer = mInterface.getPackageInstaller();
Todd Kennedyc3c52172019-11-26 13:20:59 -08001395 pw.println("Installing package " + packageName + " for user: " + translatedUserId);
Chandan Nathe8e463b2019-01-28 15:23:38 +00001396 installer.installExistingPackage(packageName, installFlags, installReason,
Todd Kennedyc3c52172019-11-26 13:20:59 -08001397 receiver.getIntentSender(), translatedUserId, null);
Chandan Nathe8e463b2019-01-28 15:23:38 +00001398 final Intent result = receiver.getResult();
1399 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1400 PackageInstaller.STATUS_FAILURE);
1401 pw.println("Received intent for package install");
1402 return status == PackageInstaller.STATUS_SUCCESS ? 0 : 1;
1403 }
1404
Todd Kennedyc3c52172019-11-26 13:20:59 -08001405 final int res = mInterface.installExistingPackageAsUser(packageName, translatedUserId,
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001406 installFlags, installReason, null);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001407 if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
1408 throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1409 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08001410 pw.println("Package " + packageName + " installed for user: " + translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001411 return 0;
1412 } catch (RemoteException | NameNotFoundException e) {
1413 pw.println(e.toString());
1414 return 1;
1415 }
1416 }
1417
1418 private int runSetInstallLocation() throws RemoteException {
1419 int loc;
1420
1421 String arg = getNextArg();
1422 if (arg == null) {
1423 getErrPrintWriter().println("Error: no install location specified.");
1424 return 1;
1425 }
1426 try {
1427 loc = Integer.parseInt(arg);
1428 } catch (NumberFormatException e) {
1429 getErrPrintWriter().println("Error: install location has to be a number.");
1430 return 1;
1431 }
1432 if (!mInterface.setInstallLocation(loc)) {
1433 getErrPrintWriter().println("Error: install location has to be a number.");
1434 return 1;
1435 }
1436 return 0;
1437 }
1438
1439 private int runGetInstallLocation() throws RemoteException {
1440 int loc = mInterface.getInstallLocation();
1441 String locStr = "invalid";
1442 if (loc == PackageHelper.APP_INSTALL_AUTO) {
1443 locStr = "auto";
1444 } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
1445 locStr = "internal";
1446 } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
1447 locStr = "external";
1448 }
1449 getOutPrintWriter().println(loc + "[" + locStr + "]");
1450 return 0;
1451 }
1452
1453 public int runMovePackage() throws RemoteException {
1454 final String packageName = getNextArg();
1455 if (packageName == null) {
1456 getErrPrintWriter().println("Error: package name not specified");
1457 return 1;
1458 }
1459 String volumeUuid = getNextArg();
1460 if ("internal".equals(volumeUuid)) {
1461 volumeUuid = null;
1462 }
1463
1464 final int moveId = mInterface.movePackage(packageName, volumeUuid);
1465
1466 int status = mInterface.getMoveStatus(moveId);
1467 while (!PackageManager.isMoveStatusFinished(status)) {
1468 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1469 status = mInterface.getMoveStatus(moveId);
1470 }
1471
1472 if (status == PackageManager.MOVE_SUCCEEDED) {
1473 getOutPrintWriter().println("Success");
1474 return 0;
1475 } else {
1476 getErrPrintWriter().println("Failure [" + status + "]");
1477 return 1;
1478 }
1479 }
1480
1481 public int runMovePrimaryStorage() throws RemoteException {
1482 String volumeUuid = getNextArg();
1483 if ("internal".equals(volumeUuid)) {
1484 volumeUuid = null;
1485 }
1486
1487 final int moveId = mInterface.movePrimaryStorage(volumeUuid);
1488
1489 int status = mInterface.getMoveStatus(moveId);
1490 while (!PackageManager.isMoveStatusFinished(status)) {
1491 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1492 status = mInterface.getMoveStatus(moveId);
1493 }
1494
1495 if (status == PackageManager.MOVE_SUCCEEDED) {
1496 getOutPrintWriter().println("Success");
1497 return 0;
1498 } else {
1499 getErrPrintWriter().println("Failure [" + status + "]");
1500 return 1;
1501 }
1502 }
1503
1504 private int runCompile() throws RemoteException {
1505 final PrintWriter pw = getOutPrintWriter();
1506 boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
1507 boolean forceCompilation = false;
1508 boolean allPackages = false;
1509 boolean clearProfileData = false;
1510 String compilerFilter = null;
1511 String compilationReason = null;
1512 String checkProfilesRaw = null;
1513 boolean secondaryDex = false;
1514 String split = null;
Eric Holka1485f62019-01-07 13:58:25 -08001515 boolean compileLayouts = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001516
1517 String opt;
1518 while ((opt = getNextOption()) != null) {
1519 switch (opt) {
1520 case "-a":
1521 allPackages = true;
1522 break;
1523 case "-c":
1524 clearProfileData = true;
1525 break;
1526 case "-f":
1527 forceCompilation = true;
1528 break;
1529 case "-m":
1530 compilerFilter = getNextArgRequired();
1531 break;
1532 case "-r":
1533 compilationReason = getNextArgRequired();
1534 break;
Eric Holka1485f62019-01-07 13:58:25 -08001535 case "--compile-layouts":
1536 compileLayouts = true;
1537 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001538 case "--check-prof":
1539 checkProfilesRaw = getNextArgRequired();
1540 break;
1541 case "--reset":
1542 forceCompilation = true;
1543 clearProfileData = true;
1544 compilationReason = "install";
1545 break;
1546 case "--secondary-dex":
1547 secondaryDex = true;
1548 break;
1549 case "--split":
1550 split = getNextArgRequired();
1551 break;
1552 default:
1553 pw.println("Error: Unknown option: " + opt);
1554 return 1;
1555 }
1556 }
1557
1558 if (checkProfilesRaw != null) {
1559 if ("true".equals(checkProfilesRaw)) {
1560 checkProfiles = true;
1561 } else if ("false".equals(checkProfilesRaw)) {
1562 checkProfiles = false;
1563 } else {
1564 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
1565 return 1;
1566 }
1567 }
1568
Eric Holka1485f62019-01-07 13:58:25 -08001569 final boolean compilerFilterGiven = compilerFilter != null;
1570 final boolean compilationReasonGiven = compilationReason != null;
1571 // Make sure exactly one of -m, -r, or --compile-layouts is given.
1572 if ((!compilerFilterGiven && !compilationReasonGiven && !compileLayouts)
1573 || (!compilerFilterGiven && compilationReasonGiven && compileLayouts)
1574 || (compilerFilterGiven && !compilationReasonGiven && compileLayouts)
1575 || (compilerFilterGiven && compilationReasonGiven && !compileLayouts)
1576 || (compilerFilterGiven && compilationReasonGiven && compileLayouts)) {
1577 pw.println("Must specify exactly one of compilation filter (\"-m\"), compilation " +
1578 "reason (\"-r\"), or compile layouts (\"--compile-layouts\")");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001579 return 1;
1580 }
1581
1582 if (allPackages && split != null) {
1583 pw.println("-a cannot be specified together with --split");
1584 return 1;
1585 }
1586
1587 if (secondaryDex && split != null) {
1588 pw.println("--secondary-dex cannot be specified together with --split");
1589 return 1;
1590 }
1591
Eric Holka1485f62019-01-07 13:58:25 -08001592 String targetCompilerFilter = null;
1593 if (compilerFilterGiven) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001594 if (!DexFile.isValidCompilerFilter(compilerFilter)) {
1595 pw.println("Error: \"" + compilerFilter +
1596 "\" is not a valid compilation filter.");
1597 return 1;
1598 }
1599 targetCompilerFilter = compilerFilter;
Eric Holka1485f62019-01-07 13:58:25 -08001600 }
1601 if (compilationReasonGiven) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001602 int reason = -1;
1603 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
1604 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
1605 compilationReason)) {
1606 reason = i;
1607 break;
1608 }
1609 }
1610 if (reason == -1) {
1611 pw.println("Error: Unknown compilation reason: " + compilationReason);
1612 return 1;
1613 }
1614 targetCompilerFilter =
1615 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
1616 }
1617
1618
1619 List<String> packageNames = null;
1620 if (allPackages) {
1621 packageNames = mInterface.getAllPackages();
1622 } else {
1623 String packageName = getNextArg();
1624 if (packageName == null) {
1625 pw.println("Error: package name not specified");
1626 return 1;
1627 }
1628 packageNames = Collections.singletonList(packageName);
1629 }
1630
1631 List<String> failedPackages = new ArrayList<>();
Andreas Gampecbd08d42017-11-20 17:03:17 -08001632 int index = 0;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001633 for (String packageName : packageNames) {
1634 if (clearProfileData) {
1635 mInterface.clearApplicationProfileData(packageName);
1636 }
1637
Andreas Gampecbd08d42017-11-20 17:03:17 -08001638 if (allPackages) {
1639 pw.println(++index + "/" + packageNames.size() + ": " + packageName);
1640 pw.flush();
1641 }
1642
Eric Holka1485f62019-01-07 13:58:25 -08001643 boolean result = true;
1644 if (compileLayouts) {
1645 PackageManagerInternal internal = LocalServices.getService(
1646 PackageManagerInternal.class);
1647 result = internal.compileLayouts(packageName);
1648 } else {
1649 result = secondaryDex
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001650 ? mInterface.performDexOptSecondary(packageName,
1651 targetCompilerFilter, forceCompilation)
1652 : mInterface.performDexOptMode(packageName,
1653 checkProfiles, targetCompilerFilter, forceCompilation,
1654 true /* bootComplete */, split);
Eric Holka1485f62019-01-07 13:58:25 -08001655 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001656 if (!result) {
1657 failedPackages.add(packageName);
1658 }
1659 }
1660
1661 if (failedPackages.isEmpty()) {
1662 pw.println("Success");
1663 return 0;
1664 } else if (failedPackages.size() == 1) {
1665 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
1666 return 1;
1667 } else {
1668 pw.print("Failure: the following packages could not be compiled: ");
1669 boolean is_first = true;
1670 for (String packageName : failedPackages) {
1671 if (is_first) {
1672 is_first = false;
1673 } else {
1674 pw.print(", ");
1675 }
1676 pw.print(packageName);
1677 }
1678 pw.println();
1679 return 1;
1680 }
1681 }
1682
1683 private int runreconcileSecondaryDexFiles() throws RemoteException {
1684 String packageName = getNextArg();
1685 mInterface.reconcileSecondaryDexFiles(packageName);
1686 return 0;
1687 }
1688
1689 public int runForceDexOpt() throws RemoteException {
1690 mInterface.forceDexOpt(getNextArgRequired());
1691 return 0;
1692 }
1693
1694 private int runDexoptJob() throws RemoteException {
Arthur Eubanks09dd1ec2017-09-15 09:28:51 -07001695 String arg;
1696 List<String> packageNames = new ArrayList<>();
1697 while ((arg = getNextArg()) != null) {
1698 packageNames.add(arg);
1699 }
1700 boolean result = mInterface.runBackgroundDexoptJob(packageNames.isEmpty() ? null :
1701 packageNames);
Andreas Gampefa8b57d2018-08-31 15:47:01 -07001702 getOutPrintWriter().println(result ? "Success" : "Failure");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001703 return result ? 0 : -1;
1704 }
1705
1706 private int runDumpProfiles() throws RemoteException {
1707 String packageName = getNextArg();
1708 mInterface.dumpProfiles(packageName);
1709 return 0;
1710 }
1711
Calin Juravle21216c62018-05-04 17:35:29 -07001712 private int runSnapshotProfile() throws RemoteException {
1713 PrintWriter pw = getOutPrintWriter();
1714
1715 // Parse the arguments
1716 final String packageName = getNextArg();
1717 final boolean isBootImage = "android".equals(packageName);
1718
1719 String codePath = null;
1720 String opt;
1721 while ((opt = getNextArg()) != null) {
1722 switch (opt) {
1723 case "--code-path":
1724 if (isBootImage) {
1725 pw.write("--code-path cannot be used for the boot image.");
1726 return -1;
1727 }
1728 codePath = getNextArg();
1729 break;
1730 default:
1731 pw.write("Unknown arg: " + opt);
1732 return -1;
1733 }
1734 }
1735
1736 // If no code path was explicitly requested, select the base code path.
1737 String baseCodePath = null;
1738 if (!isBootImage) {
1739 PackageInfo packageInfo = mInterface.getPackageInfo(packageName, /* flags */ 0,
1740 /* userId */0);
1741 if (packageInfo == null) {
1742 pw.write("Package not found " + packageName);
1743 return -1;
1744 }
1745 baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
1746 if (codePath == null) {
1747 codePath = baseCodePath;
1748 }
1749 }
1750
1751 // Create the profile snapshot.
1752 final SnapshotRuntimeProfileCallback callback = new SnapshotRuntimeProfileCallback();
1753 // The calling package is needed to debug permission access.
1754 final String callingPackage = (Binder.getCallingUid() == Process.ROOT_UID)
1755 ? "root" : "com.android.shell";
1756 final int profileType = isBootImage
1757 ? ArtManager.PROFILE_BOOT_IMAGE : ArtManager.PROFILE_APPS;
1758 if (!mInterface.getArtManager().isRuntimeProfilingEnabled(profileType, callingPackage)) {
1759 pw.println("Error: Runtime profiling is not enabled");
1760 return -1;
1761 }
1762 mInterface.getArtManager().snapshotRuntimeProfile(profileType, packageName,
1763 codePath, callback, callingPackage);
1764 if (!callback.waitTillDone()) {
1765 pw.println("Error: callback not called");
1766 return callback.mErrCode;
1767 }
1768
1769 // Copy the snapshot profile to the output profile file.
1770 try (InputStream inStream = new AutoCloseInputStream(callback.mProfileReadFd)) {
1771 final String outputFileSuffix = isBootImage || Objects.equals(baseCodePath, codePath)
1772 ? "" : ("-" + new File(codePath).getName());
1773 final String outputProfilePath =
1774 ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + packageName + outputFileSuffix + ".prof";
1775 try (OutputStream outStream = new FileOutputStream(outputProfilePath)) {
1776 Streams.copy(inStream, outStream);
1777 }
Calin Juravlebdd94d92018-05-17 01:23:15 -07001778 // Give read permissions to the other group.
1779 Os.chmod(outputProfilePath, /*mode*/ 0644 );
1780 } catch (IOException | ErrnoException e) {
Calin Juravle21216c62018-05-04 17:35:29 -07001781 pw.println("Error when reading the profile fd: " + e.getMessage());
1782 e.printStackTrace(pw);
1783 return -1;
1784 }
1785 return 0;
1786 }
1787
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001788 private ArrayList<String> getRemainingArgs() {
1789 ArrayList<String> args = new ArrayList<>();
1790 String arg;
1791 while ((arg = getNextArg()) != null) {
1792 args.add(arg);
1793 }
1794 return args;
1795 }
1796
Calin Juravle21216c62018-05-04 17:35:29 -07001797 private static class SnapshotRuntimeProfileCallback
1798 extends ISnapshotRuntimeProfileCallback.Stub {
1799 private boolean mSuccess = false;
1800 private int mErrCode = -1;
1801 private ParcelFileDescriptor mProfileReadFd = null;
1802 private CountDownLatch mDoneSignal = new CountDownLatch(1);
1803
1804 @Override
1805 public void onSuccess(ParcelFileDescriptor profileReadFd) {
1806 mSuccess = true;
1807 try {
1808 // We need to dup the descriptor. We are in the same process as system server
1809 // and we will be receiving the same object (which will be closed on the
1810 // server side).
1811 mProfileReadFd = profileReadFd.dup();
1812 } catch (IOException e) {
1813 e.printStackTrace();
1814 }
1815 mDoneSignal.countDown();
1816 }
1817
1818 @Override
1819 public void onError(int errCode) {
1820 mSuccess = false;
1821 mErrCode = errCode;
1822 mDoneSignal.countDown();
1823 }
1824
1825 boolean waitTillDone() {
1826 boolean done = false;
1827 try {
1828 // The time-out is an arbitrary large value. Since this is a local call the result
1829 // will come very fast.
1830 done = mDoneSignal.await(10000000, TimeUnit.MILLISECONDS);
1831 } catch (InterruptedException ignored) {
1832 }
1833 return done && mSuccess;
1834 }
1835 }
1836
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001837 private int runUninstall() throws RemoteException {
1838 final PrintWriter pw = getOutPrintWriter();
1839 int flags = 0;
1840 int userId = UserHandle.USER_ALL;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001841 long versionCode = PackageManager.VERSION_CODE_HIGHEST;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001842
1843 String opt;
1844 while ((opt = getNextOption()) != null) {
1845 switch (opt) {
1846 case "-k":
1847 flags |= PackageManager.DELETE_KEEP_DATA;
1848 break;
1849 case "--user":
1850 userId = UserHandle.parseUserArg(getNextArgRequired());
1851 break;
1852 case "--versionCode":
Dianne Hackborn3accca02013-09-20 09:32:11 -07001853 versionCode = Long.parseLong(getNextArgRequired());
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001854 break;
1855 default:
1856 pw.println("Error: Unknown option: " + opt);
1857 return 1;
1858 }
1859 }
1860
1861 final String packageName = getNextArg();
1862 if (packageName == null) {
1863 pw.println("Error: package name not specified");
1864 return 1;
1865 }
1866
1867 // if a split is specified, just remove it and not the whole package
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001868 ArrayList<String> splitNames = getRemainingArgs();
1869 if (!splitNames.isEmpty()) {
1870 return runRemoveSplits(packageName, splitNames);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001871 }
1872
Todd Kennedyc3c52172019-11-26 13:20:59 -08001873 if (userId == UserHandle.USER_ALL) {
1874 flags |= PackageManager.DELETE_ALL_USERS;
1875 }
1876 final int translatedUserId =
1877 translateUserId(userId, UserHandle.USER_SYSTEM, "runUninstall");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001878 final LocalIntentReceiver receiver = new LocalIntentReceiver();
Todd Kennedyc3c52172019-11-26 13:20:59 -08001879 final PackageManagerInternal internal =
1880 LocalServices.getService(PackageManagerInternal.class);
Nikita Ioffef012a222019-03-05 22:37:55 +00001881
1882 if (internal.isApexPackage(packageName)) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08001883 internal.uninstallApex(
Gavin Corkery4fd10882019-11-28 15:37:51 +00001884 packageName, versionCode, translatedUserId, receiver.getIntentSender(), flags);
Todd Kennedy2678a992019-11-27 10:21:23 -08001885 } else {
1886 if ((flags & PackageManager.DELETE_ALL_USERS) == 0) {
1887 final PackageInfo info = mInterface.getPackageInfo(packageName,
1888 PackageManager.MATCH_STATIC_SHARED_LIBRARIES, translatedUserId);
1889 if (info == null) {
1890 pw.println("Failure [not installed for " + translatedUserId + "]");
1891 return 1;
1892 }
1893 final boolean isSystem =
1894 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
1895 // If we are being asked to delete a system app for just one
1896 // user set flag so it disables rather than reverting to system
1897 // version of the app.
1898 if (isSystem) {
1899 flags |= PackageManager.DELETE_SYSTEM_APP;
1900 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08001901 }
Nikita Ioffef012a222019-03-05 22:37:55 +00001902 mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
1903 versionCode), null /*callerPackageName*/, flags,
Todd Kennedyc3c52172019-11-26 13:20:59 -08001904 receiver.getIntentSender(), translatedUserId);
Nikita Ioffef012a222019-03-05 22:37:55 +00001905 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001906
1907 final Intent result = receiver.getResult();
1908 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1909 PackageInstaller.STATUS_FAILURE);
1910 if (status == PackageInstaller.STATUS_SUCCESS) {
1911 pw.println("Success");
1912 return 0;
1913 } else {
1914 pw.println("Failure ["
1915 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
1916 return 1;
1917 }
1918 }
1919
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001920 private int runRemoveSplits(String packageName, Collection<String> splitNames)
1921 throws RemoteException {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001922 final PrintWriter pw = getOutPrintWriter();
1923 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
1924 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1925 sessionParams.appPackageName = packageName;
1926 final int sessionId =
1927 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
1928 boolean abandonSession = true;
1929 try {
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001930 if (doRemoveSplits(sessionId, splitNames, false /*logSuccess*/)
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001931 != PackageInstaller.STATUS_SUCCESS) {
1932 return 1;
1933 }
1934 if (doCommitSession(sessionId, false /*logSuccess*/)
1935 != PackageInstaller.STATUS_SUCCESS) {
1936 return 1;
1937 }
1938 abandonSession = false;
1939 pw.println("Success");
1940 return 0;
1941 } finally {
1942 if (abandonSession) {
1943 try {
1944 doAbandonSession(sessionId, false /*logSuccess*/);
1945 } catch (Exception ignore) {
1946 }
1947 }
1948 }
1949 }
1950
1951 static class ClearDataObserver extends IPackageDataObserver.Stub {
1952 boolean finished;
1953 boolean result;
1954
1955 @Override
1956 public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1957 synchronized (this) {
1958 finished = true;
1959 result = succeeded;
1960 notifyAll();
1961 }
1962 }
1963 }
1964
1965 private int runClear() throws RemoteException {
1966 int userId = UserHandle.USER_SYSTEM;
1967 String option = getNextOption();
1968 if (option != null && option.equals("--user")) {
1969 userId = UserHandle.parseUserArg(getNextArgRequired());
1970 }
1971
1972 String pkg = getNextArg();
1973 if (pkg == null) {
1974 getErrPrintWriter().println("Error: no package specified");
1975 return 1;
1976 }
1977
Todd Kennedy5385b512019-11-26 15:49:06 -08001978 final int translatedUserId =
1979 translateUserId(userId, UserHandle.USER_NULL, "runClear");
1980 final ClearDataObserver obs = new ClearDataObserver();
1981 ActivityManager.getService().clearApplicationUserData(pkg, false, obs, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001982 synchronized (obs) {
1983 while (!obs.finished) {
1984 try {
1985 obs.wait();
1986 } catch (InterruptedException e) {
1987 }
1988 }
1989 }
1990
1991 if (obs.result) {
1992 getOutPrintWriter().println("Success");
1993 return 0;
1994 } else {
1995 getErrPrintWriter().println("Failed");
1996 return 1;
1997 }
1998 }
1999
2000 private static String enabledSettingToString(int state) {
2001 switch (state) {
2002 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
2003 return "default";
2004 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
2005 return "enabled";
2006 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
2007 return "disabled";
2008 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
2009 return "disabled-user";
2010 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
2011 return "disabled-until-used";
2012 }
2013 return "unknown";
2014 }
2015
2016 private int runSetEnabledSetting(int state) throws RemoteException {
2017 int userId = UserHandle.USER_SYSTEM;
2018 String option = getNextOption();
2019 if (option != null && option.equals("--user")) {
2020 userId = UserHandle.parseUserArg(getNextArgRequired());
2021 }
2022
Todd Kennedyc3c52172019-11-26 13:20:59 -08002023 final String pkg = getNextArg();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002024 if (pkg == null) {
2025 getErrPrintWriter().println("Error: no package or component specified");
2026 return 1;
2027 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002028 final int translatedUserId =
2029 translateUserId(userId, UserHandle.USER_NULL, "runSetEnabledSetting");
2030 final ComponentName cn = ComponentName.unflattenFromString(pkg);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002031 if (cn == null) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002032 mInterface.setApplicationEnabledSetting(pkg, state, 0, translatedUserId,
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002033 "shell:" + android.os.Process.myUid());
2034 getOutPrintWriter().println("Package " + pkg + " new state: "
2035 + enabledSettingToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002036 mInterface.getApplicationEnabledSetting(pkg, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002037 return 0;
2038 } else {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002039 mInterface.setComponentEnabledSetting(cn, state, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002040 getOutPrintWriter().println("Component " + cn.toShortString() + " new state: "
2041 + enabledSettingToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002042 mInterface.getComponentEnabledSetting(cn, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002043 return 0;
2044 }
2045 }
2046
2047 private int runSetHiddenSetting(boolean state) throws RemoteException {
2048 int userId = UserHandle.USER_SYSTEM;
2049 String option = getNextOption();
2050 if (option != null && option.equals("--user")) {
2051 userId = UserHandle.parseUserArg(getNextArgRequired());
2052 }
2053
2054 String pkg = getNextArg();
2055 if (pkg == null) {
2056 getErrPrintWriter().println("Error: no package or component specified");
2057 return 1;
2058 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002059 final int translatedUserId =
2060 translateUserId(userId, UserHandle.USER_NULL, "runSetHiddenSetting");
2061 mInterface.setApplicationHiddenSettingAsUser(pkg, state, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002062 getOutPrintWriter().println("Package " + pkg + " new hidden state: "
Todd Kennedyc3c52172019-11-26 13:20:59 -08002063 + mInterface.getApplicationHiddenSettingAsUser(pkg, translatedUserId));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002064 return 0;
2065 }
2066
2067 private int runSuspend(boolean suspendedState) {
2068 final PrintWriter pw = getOutPrintWriter();
2069 int userId = UserHandle.USER_SYSTEM;
Suprabh Shukla3c3af142018-03-30 00:28:37 -07002070 String dialogMessage = null;
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002071 final PersistableBundle appExtras = new PersistableBundle();
2072 final PersistableBundle launcherExtras = new PersistableBundle();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002073 String opt;
2074 while ((opt = getNextOption()) != null) {
2075 switch (opt) {
2076 case "--user":
2077 userId = UserHandle.parseUserArg(getNextArgRequired());
2078 break;
Suprabh Shukla3c3af142018-03-30 00:28:37 -07002079 case "--dialogMessage":
2080 dialogMessage = getNextArgRequired();
2081 break;
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002082 case "--ael":
2083 case "--aes":
2084 case "--aed":
2085 case "--lel":
2086 case "--les":
2087 case "--led":
2088 final String key = getNextArgRequired();
2089 final String val = getNextArgRequired();
2090 if (!suspendedState) {
2091 break;
2092 }
2093 final PersistableBundle bundleToInsert =
2094 opt.startsWith("--a") ? appExtras : launcherExtras;
2095 switch (opt.charAt(4)) {
2096 case 'l':
2097 bundleToInsert.putLong(key, Long.valueOf(val));
2098 break;
2099 case 'd':
2100 bundleToInsert.putDouble(key, Double.valueOf(val));
2101 break;
2102 case 's':
2103 bundleToInsert.putString(key, val);
2104 break;
2105 }
2106 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002107 default:
2108 pw.println("Error: Unknown option: " + opt);
2109 return 1;
2110 }
2111 }
2112
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002113 final String packageName = getNextArg();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002114 if (packageName == null) {
2115 pw.println("Error: package name not specified");
2116 return 1;
2117 }
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002118 final String callingPackage =
2119 (Binder.getCallingUid() == Process.ROOT_UID) ? "root" : "com.android.shell";
Suprabh Shukla389cb6f2018-10-01 18:20:39 -07002120
2121 final SuspendDialogInfo info;
2122 if (!TextUtils.isEmpty(dialogMessage)) {
2123 info = new SuspendDialogInfo.Builder()
2124 .setMessage(dialogMessage)
2125 .build();
2126 } else {
2127 info = null;
2128 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002129 try {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002130 final int translatedUserId =
2131 translateUserId(userId, UserHandle.USER_NULL, "runSuspend");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002132 mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
Suprabh Shuklad3278442019-08-27 15:58:03 -07002133 ((appExtras.size() > 0) ? appExtras : null),
2134 ((launcherExtras.size() > 0) ? launcherExtras : null),
Todd Kennedyc3c52172019-11-26 13:20:59 -08002135 info, callingPackage, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002136 pw.println("Package " + packageName + " new suspended state: "
Todd Kennedyc3c52172019-11-26 13:20:59 -08002137 + mInterface.isPackageSuspendedForUser(packageName, translatedUserId));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002138 return 0;
2139 } catch (RemoteException | IllegalArgumentException e) {
2140 pw.println(e.toString());
2141 return 1;
2142 }
2143 }
2144
2145 private int runGrantRevokePermission(boolean grant) throws RemoteException {
2146 int userId = UserHandle.USER_SYSTEM;
2147
2148 String opt = null;
2149 while ((opt = getNextOption()) != null) {
2150 if (opt.equals("--user")) {
2151 userId = UserHandle.parseUserArg(getNextArgRequired());
2152 }
2153 }
2154
2155 String pkg = getNextArg();
2156 if (pkg == null) {
2157 getErrPrintWriter().println("Error: no package specified");
2158 return 1;
2159 }
2160 String perm = getNextArg();
2161 if (perm == null) {
2162 getErrPrintWriter().println("Error: no permission specified");
2163 return 1;
2164 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002165 final int translatedUserId =
2166 translateUserId(userId, UserHandle.USER_NULL, "runGrantRevokePermission");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002167 if (grant) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002168 mPermissionManager.grantRuntimePermission(pkg, perm, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002169 } else {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002170 mPermissionManager.revokeRuntimePermission(pkg, perm, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002171 }
2172 return 0;
2173 }
2174
2175 private int runResetPermissions() throws RemoteException {
Todd Kennedyc971a452019-07-08 16:04:52 -07002176 mPermissionManager.resetRuntimePermissions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002177 return 0;
2178 }
2179
2180 private int runSetPermissionEnforced() throws RemoteException {
2181 final String permission = getNextArg();
2182 if (permission == null) {
2183 getErrPrintWriter().println("Error: no permission specified");
2184 return 1;
2185 }
2186 final String enforcedRaw = getNextArg();
2187 if (enforcedRaw == null) {
2188 getErrPrintWriter().println("Error: no enforcement specified");
2189 return 1;
2190 }
Todd Kennedyc5b0e862019-07-16 09:47:58 -07002191 mPermissionManager.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002192 return 0;
2193 }
2194
Jiyong Park002fdbd2017-02-13 20:50:31 +09002195 private boolean isVendorApp(String pkg) {
2196 try {
2197 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
2198 return info != null && info.applicationInfo.isVendor();
2199 } catch (RemoteException e) {
2200 return false;
2201 }
2202 }
2203
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002204 private boolean isProductApp(String pkg) {
2205 try {
2206 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
2207 return info != null && info.applicationInfo.isProduct();
2208 } catch (RemoteException e) {
2209 return false;
2210 }
2211 }
2212
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002213 private boolean isSystemExtApp(String pkg) {
Dario Freni2bef1762018-06-01 14:02:08 +01002214 try {
2215 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002216 return info != null && info.applicationInfo.isSystemExt();
Dario Freni2bef1762018-06-01 14:02:08 +01002217 } catch (RemoteException e) {
2218 return false;
2219 }
2220 }
2221
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002222 private int runGetPrivappPermissions() {
2223 final String pkg = getNextArg();
2224 if (pkg == null) {
2225 getErrPrintWriter().println("Error: no package specified.");
2226 return 1;
2227 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002228
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002229 ArraySet<String> privAppPermissions = null;
2230 if (isVendorApp(pkg)) {
2231 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
2232 } else if (isProductApp(pkg)) {
2233 privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002234 } else if (isSystemExtApp(pkg)) {
Dario Freni2bef1762018-06-01 14:02:08 +01002235 privAppPermissions = SystemConfig.getInstance()
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002236 .getSystemExtPrivAppPermissions(pkg);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002237 } else {
2238 privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
2239 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002240
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002241 getOutPrintWriter().println(privAppPermissions == null
2242 ? "{}" : privAppPermissions.toString());
2243 return 0;
2244 }
2245
2246 private int runGetPrivappDenyPermissions() {
2247 final String pkg = getNextArg();
2248 if (pkg == null) {
2249 getErrPrintWriter().println("Error: no package specified.");
2250 return 1;
2251 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002252
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002253 ArraySet<String> privAppPermissions = null;
2254 if (isVendorApp(pkg)) {
2255 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
2256 } else if (isProductApp(pkg)) {
2257 privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002258 } else if (isSystemExtApp(pkg)) {
Dario Freni2bef1762018-06-01 14:02:08 +01002259 privAppPermissions = SystemConfig.getInstance()
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002260 .getSystemExtPrivAppDenyPermissions(pkg);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002261 } else {
2262 privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
2263 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002264
2265 getOutPrintWriter().println(privAppPermissions == null
2266 ? "{}" : privAppPermissions.toString());
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002267 return 0;
2268 }
2269
2270 private int runGetOemPermissions() {
2271 final String pkg = getNextArg();
2272 if (pkg == null) {
2273 getErrPrintWriter().println("Error: no package specified.");
2274 return 1;
2275 }
2276 final Map<String, Boolean> oemPermissions = SystemConfig.getInstance()
2277 .getOemPermissions(pkg);
2278 if (oemPermissions == null || oemPermissions.isEmpty()) {
2279 getOutPrintWriter().println("{}");
2280 } else {
2281 oemPermissions.forEach((permission, granted) ->
2282 getOutPrintWriter().println(permission + " granted:" + granted)
2283 );
2284 }
2285 return 0;
2286 }
2287
2288 private String linkStateToString(int state) {
2289 switch (state) {
2290 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
2291 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
2292 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
2293 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
2294 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
2295 }
2296 return "Unknown link state: " + state;
2297 }
2298
2299 // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
2300 private int runSetAppLink() throws RemoteException {
2301 int userId = UserHandle.USER_SYSTEM;
2302
2303 String opt;
2304 while ((opt = getNextOption()) != null) {
2305 if (opt.equals("--user")) {
2306 userId = UserHandle.parseUserArg(getNextArgRequired());
2307 } else {
2308 getErrPrintWriter().println("Error: unknown option: " + opt);
2309 return 1;
2310 }
2311 }
2312
2313 // Package name to act on; required
2314 final String pkg = getNextArg();
2315 if (pkg == null) {
2316 getErrPrintWriter().println("Error: no package specified.");
2317 return 1;
2318 }
2319
2320 // State to apply; {always|ask|never|undefined}, required
2321 final String modeString = getNextArg();
2322 if (modeString == null) {
2323 getErrPrintWriter().println("Error: no app link state specified.");
2324 return 1;
2325 }
2326
2327 final int newMode;
2328 switch (modeString.toLowerCase()) {
2329 case "undefined":
2330 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
2331 break;
2332
2333 case "always":
2334 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
2335 break;
2336
2337 case "ask":
2338 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
2339 break;
2340
2341 case "always-ask":
2342 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
2343 break;
2344
2345 case "never":
2346 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
2347 break;
2348
2349 default:
2350 getErrPrintWriter().println("Error: unknown app link state '" + modeString + "'");
2351 return 1;
2352 }
2353
Todd Kennedyc3c52172019-11-26 13:20:59 -08002354 final int translatedUserId =
2355 translateUserId(userId, UserHandle.USER_NULL, "runSetAppLink");
2356 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002357 if (info == null) {
2358 getErrPrintWriter().println("Error: package " + pkg + " not found.");
2359 return 1;
2360 }
2361
2362 if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2363 getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2364 return 1;
2365 }
2366
Todd Kennedyc3c52172019-11-26 13:20:59 -08002367 if (!mInterface.updateIntentVerificationStatus(pkg, newMode, translatedUserId)) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002368 getErrPrintWriter().println("Error: unable to update app link status for " + pkg);
2369 return 1;
2370 }
2371
2372 return 0;
2373 }
2374
2375 // pm get-app-link [--user USER_ID] PACKAGE
2376 private int runGetAppLink() throws RemoteException {
2377 int userId = UserHandle.USER_SYSTEM;
2378
2379 String opt;
2380 while ((opt = getNextOption()) != null) {
2381 if (opt.equals("--user")) {
2382 userId = UserHandle.parseUserArg(getNextArgRequired());
2383 } else {
2384 getErrPrintWriter().println("Error: unknown option: " + opt);
2385 return 1;
2386 }
2387 }
2388
2389 // Package name to act on; required
2390 final String pkg = getNextArg();
2391 if (pkg == null) {
2392 getErrPrintWriter().println("Error: no package specified.");
2393 return 1;
2394 }
2395
Todd Kennedyc3c52172019-11-26 13:20:59 -08002396 final int translatedUserId =
2397 translateUserId(userId, UserHandle.USER_NULL, "runGetAppLink");
2398 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002399 if (info == null) {
2400 getErrPrintWriter().println("Error: package " + pkg + " not found.");
2401 return 1;
2402 }
2403
2404 if ((info.applicationInfo.privateFlags
2405 & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2406 getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2407 return 1;
2408 }
2409
2410 getOutPrintWriter().println(linkStateToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002411 mInterface.getIntentVerificationStatus(pkg, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002412
2413 return 0;
2414 }
2415
2416 private int runTrimCaches() throws RemoteException {
2417 String size = getNextArg();
2418 if (size == null) {
2419 getErrPrintWriter().println("Error: no size specified");
2420 return 1;
2421 }
2422 long multiplier = 1;
2423 int len = size.length();
2424 char c = size.charAt(len - 1);
2425 if (c < '0' || c > '9') {
2426 if (c == 'K' || c == 'k') {
2427 multiplier = 1024L;
2428 } else if (c == 'M' || c == 'm') {
2429 multiplier = 1024L*1024L;
2430 } else if (c == 'G' || c == 'g') {
2431 multiplier = 1024L*1024L*1024L;
2432 } else {
2433 getErrPrintWriter().println("Invalid suffix: " + c);
2434 return 1;
2435 }
2436 size = size.substring(0, len-1);
2437 }
2438 long sizeVal;
2439 try {
2440 sizeVal = Long.parseLong(size) * multiplier;
2441 } catch (NumberFormatException e) {
2442 getErrPrintWriter().println("Error: expected number at: " + size);
2443 return 1;
2444 }
2445 String volumeUuid = getNextArg();
2446 if ("internal".equals(volumeUuid)) {
2447 volumeUuid = null;
2448 }
2449 ClearDataObserver obs = new ClearDataObserver();
2450 mInterface.freeStorageAndNotify(volumeUuid, sizeVal,
2451 StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs);
2452 synchronized (obs) {
2453 while (!obs.finished) {
2454 try {
2455 obs.wait();
2456 } catch (InterruptedException e) {
2457 }
2458 }
2459 }
2460 return 0;
2461 }
2462
2463 private static boolean isNumber(String s) {
2464 try {
2465 Integer.parseInt(s);
2466 } catch (NumberFormatException nfe) {
2467 return false;
2468 }
2469 return true;
2470 }
2471
2472 public int runCreateUser() throws RemoteException {
2473 String name;
2474 int userId = -1;
2475 int flags = 0;
Bookatz029832a2019-10-04 16:50:22 -07002476 String userType = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002477 String opt;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002478 boolean preCreateOnly = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002479 while ((opt = getNextOption()) != null) {
Bookatz029832a2019-10-04 16:50:22 -07002480 String newUserType = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002481 if ("--profileOf".equals(opt)) {
2482 userId = UserHandle.parseUserArg(getNextArgRequired());
2483 } else if ("--managed".equals(opt)) {
Bookatz029832a2019-10-04 16:50:22 -07002484 newUserType = UserManager.USER_TYPE_PROFILE_MANAGED;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002485 } else if ("--restricted".equals(opt)) {
Bookatz029832a2019-10-04 16:50:22 -07002486 newUserType = UserManager.USER_TYPE_FULL_RESTRICTED;
2487 } else if ("--guest".equals(opt)) {
2488 newUserType = UserManager.USER_TYPE_FULL_GUEST;
2489 } else if ("--demo".equals(opt)) {
2490 newUserType = UserManager.USER_TYPE_FULL_DEMO;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002491 } else if ("--ephemeral".equals(opt)) {
2492 flags |= UserInfo.FLAG_EPHEMERAL;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002493 } else if ("--pre-create-only".equals(opt)) {
2494 preCreateOnly = true;
Bookatz029832a2019-10-04 16:50:22 -07002495 } else if ("--user-type".equals(opt)) {
2496 newUserType = getNextArgRequired();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002497 } else {
2498 getErrPrintWriter().println("Error: unknown option " + opt);
2499 return 1;
2500 }
Bookatz029832a2019-10-04 16:50:22 -07002501 // Ensure only one user-type was specified.
2502 if (newUserType != null) {
2503 if (userType != null && !userType.equals(newUserType)) {
2504 getErrPrintWriter().println("Error: more than one user type was specified ("
2505 + userType + " and " + newUserType + ")");
2506 return 1;
2507 }
2508 userType = newUserType;
2509 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002510 }
2511 String arg = getNextArg();
Felipe Lemee35f5b02019-10-14 15:37:44 -07002512 if (arg == null && !preCreateOnly) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002513 getErrPrintWriter().println("Error: no user name specified.");
2514 return 1;
2515 }
Felipe Lemee35f5b02019-10-14 15:37:44 -07002516 if (arg != null && preCreateOnly) {
2517 getErrPrintWriter().println("Warning: name is ignored for pre-created users");
2518 }
2519
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002520 name = arg;
Valentin Iftime89df4c82019-08-23 13:02:50 +02002521 UserInfo info = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002522 IUserManager um = IUserManager.Stub.asInterface(
2523 ServiceManager.getService(Context.USER_SERVICE));
2524 IAccountManager accm = IAccountManager.Stub.asInterface(
2525 ServiceManager.getService(Context.ACCOUNT_SERVICE));
Bookatz029832a2019-10-04 16:50:22 -07002526 if (userType == null) {
2527 userType = UserInfo.getDefaultUserType(flags);
2528 }
Valentin Iftime89df4c82019-08-23 13:02:50 +02002529 try {
2530 if (UserManager.isUserTypeRestricted(userType)) {
2531 // In non-split user mode, userId can only be SYSTEM
2532 int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
2533 info = um.createRestrictedProfileWithThrow(name, parentUserId);
2534 accm.addSharedAccountsFromParentUser(parentUserId, userId,
2535 (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
2536 } else if (userId < 0) {
2537 info = preCreateOnly ?
2538 um.preCreateUserWithThrow(userType) :
2539 um.createUserWithThrow(name, userType, flags);
2540 } else {
2541 info = um.createProfileForUserWithThrow(name, userType, flags, userId, null);
2542 }
2543 } catch (ServiceSpecificException e) {
2544 getErrPrintWriter().println("Error: " + e);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002545 }
2546
2547 if (info != null) {
2548 getOutPrintWriter().println("Success: created user id " + info.id);
2549 return 0;
2550 } else {
2551 getErrPrintWriter().println("Error: couldn't create User.");
2552 return 1;
2553 }
2554 }
2555
2556 public int runRemoveUser() throws RemoteException {
2557 int userId;
2558 String arg = getNextArg();
2559 if (arg == null) {
2560 getErrPrintWriter().println("Error: no user id specified.");
2561 return 1;
2562 }
2563 userId = UserHandle.parseUserArg(arg);
2564 IUserManager um = IUserManager.Stub.asInterface(
2565 ServiceManager.getService(Context.USER_SERVICE));
2566 if (um.removeUser(userId)) {
2567 getOutPrintWriter().println("Success: removed user");
2568 return 0;
2569 } else {
2570 getErrPrintWriter().println("Error: couldn't remove user id " + userId);
2571 return 1;
2572 }
2573 }
2574
2575 public int runSetUserRestriction() throws RemoteException {
2576 int userId = UserHandle.USER_SYSTEM;
2577 String opt = getNextOption();
2578 if (opt != null && "--user".equals(opt)) {
2579 userId = UserHandle.parseUserArg(getNextArgRequired());
2580 }
2581
2582 String restriction = getNextArg();
2583 String arg = getNextArg();
2584 boolean value;
2585 if ("1".equals(arg)) {
2586 value = true;
2587 } else if ("0".equals(arg)) {
2588 value = false;
2589 } else {
2590 getErrPrintWriter().println("Error: valid value not specified");
2591 return 1;
2592 }
Todd Kennedy5385b512019-11-26 15:49:06 -08002593 final int translatedUserId =
2594 translateUserId(userId, UserHandle.USER_NULL, "runSetUserRestriction");
2595 final IUserManager um = IUserManager.Stub.asInterface(
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002596 ServiceManager.getService(Context.USER_SERVICE));
Todd Kennedy5385b512019-11-26 15:49:06 -08002597 um.setUserRestriction(restriction, value, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002598 return 0;
2599 }
2600
2601 public int runGetMaxUsers() {
2602 getOutPrintWriter().println("Maximum supported users: "
2603 + UserManager.getMaxSupportedUsers());
2604 return 0;
2605 }
2606
Alex Chauc12189b2018-01-16 15:01:15 +00002607 public int runGetMaxRunningUsers() {
2608 ActivityManagerInternal activityManagerInternal =
2609 LocalServices.getService(ActivityManagerInternal.class);
2610 getOutPrintWriter().println("Maximum supported running users: "
2611 + activityManagerInternal.getMaxRunningUsers());
2612 return 0;
2613 }
2614
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002615 private static class InstallParams {
2616 SessionParams sessionParams;
2617 String installerPackageName;
2618 int userId = UserHandle.USER_ALL;
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002619 boolean mWaitForStagedSessionReady = true;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002620 long timeoutMs = DEFAULT_WAIT_MS;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002621 }
2622
2623 private InstallParams makeInstallParams() {
2624 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2625 final InstallParams params = new InstallParams();
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07002626
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002627 params.sessionParams = sessionParams;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07002628 // Whitelist all permissions by default
2629 sessionParams.installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
2630
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002631 String opt;
Patrick Baumanna9333492017-11-28 15:23:49 -08002632 boolean replaceExisting = true;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002633 while ((opt = getNextOption()) != null) {
2634 switch (opt) {
Patrick Baumanna9333492017-11-28 15:23:49 -08002635 case "-r": // ignore
2636 break;
2637 case "-R":
2638 replaceExisting = false;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002639 break;
2640 case "-i":
2641 params.installerPackageName = getNextArg();
2642 if (params.installerPackageName == null) {
2643 throw new IllegalArgumentException("Missing installer package");
2644 }
2645 break;
2646 case "-t":
2647 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
2648 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002649 case "-f":
2650 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
2651 break;
2652 case "-d":
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00002653 sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002654 break;
2655 case "-g":
2656 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
Svet Ganov83a3a4a2019-05-03 18:50:43 -07002657 break;
2658 case "--restrict-permissions":
2659 sessionParams.installFlags &=
2660 ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002661 break;
Todd Kennedyb1072712016-04-26 15:41:20 -07002662 case "--dont-kill":
2663 sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
2664 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002665 case "--originating-uri":
2666 sessionParams.originatingUri = Uri.parse(getNextArg());
2667 break;
2668 case "--referrer":
2669 sessionParams.referrerUri = Uri.parse(getNextArg());
2670 break;
2671 case "-p":
2672 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
2673 sessionParams.appPackageName = getNextArg();
2674 if (sessionParams.appPackageName == null) {
2675 throw new IllegalArgumentException("Missing inherit package name");
2676 }
2677 break;
Dianne Hackbornca3872c2017-10-30 14:19:32 -07002678 case "--pkg":
2679 sessionParams.appPackageName = getNextArg();
2680 if (sessionParams.appPackageName == null) {
2681 throw new IllegalArgumentException("Missing package name");
2682 }
2683 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002684 case "-S":
Todd Kennedy9caf94e2016-10-12 15:26:08 -07002685 final long sizeBytes = Long.parseLong(getNextArg());
2686 if (sizeBytes <= 0) {
2687 throw new IllegalArgumentException("Size must be positive");
2688 }
2689 sessionParams.setSize(sizeBytes);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002690 break;
2691 case "--abi":
2692 sessionParams.abiOverride = checkAbiArgument(getNextArg());
2693 break;
Todd Kennedy2699f062015-11-20 13:07:17 -08002694 case "--ephemeral":
Dianne Hackbornca3872c2017-10-30 14:19:32 -07002695 case "--instant":
Todd Kennedybe0b8892017-02-15 14:13:52 -08002696 case "--instantapp":
Todd Kennedyb7717682016-11-30 15:41:21 -08002697 sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
Todd Kennedy2699f062015-11-20 13:07:17 -08002698 break;
Todd Kennedybe0b8892017-02-15 14:13:52 -08002699 case "--full":
2700 sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
2701 break;
Todd Kennedy78a72502017-07-19 12:49:30 -07002702 case "--preload":
2703 sessionParams.setInstallAsVirtualPreload();
2704 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002705 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08002706 params.userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002707 break;
2708 case "--install-location":
2709 sessionParams.installLocation = Integer.parseInt(getNextArg());
2710 break;
Sunny Goyalabd4d442018-09-19 15:49:50 -07002711 case "--install-reason":
2712 sessionParams.installReason = Integer.parseInt(getNextArg());
2713 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002714 case "--force-uuid":
2715 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
2716 sessionParams.volumeUuid = getNextArg();
2717 if ("internal".equals(sessionParams.volumeUuid)) {
2718 sessionParams.volumeUuid = null;
2719 }
2720 break;
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002721 case "--force-sdk": // ignore
Todd Kennedyb1072712016-04-26 15:41:20 -07002722 break;
Dario Frenid8bf22e2018-08-31 14:18:04 +01002723 case "--apex":
Dario Freni3fa46d82019-01-23 19:31:47 +00002724 sessionParams.setInstallAsApex();
Dario Freni505b8152019-01-08 12:30:43 +00002725 sessionParams.setStaged();
Dario Frenid8bf22e2018-08-31 14:18:04 +01002726 break;
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002727 case "--multi-package":
2728 sessionParams.setMultiPackage();
2729 break;
Dario Freniaac4ba42018-12-06 15:47:16 +00002730 case "--staged":
2731 sessionParams.setStaged();
2732 break;
Patrick Baumann5ff0f9e2019-11-27 11:40:07 -08002733 case "--force-queryable":
2734 sessionParams.setForceQueryable();
2735 break;
Richard Uhlerb29f1452018-09-12 16:38:15 +01002736 case "--enable-rollback":
Richard Uhler88184a62019-04-16 11:30:25 +01002737 if (params.installerPackageName == null) {
2738 // com.android.shell has the TEST_MANAGE_ROLLBACKS
2739 // permission needed to enable rollback for non-module
2740 // packages, which is likely what the user wants when
2741 // enabling rollback through the shell command. Set
2742 // the installer to com.android.shell if no installer
2743 // has been provided so that the user doesn't have to
2744 // remember to set it themselves.
2745 params.installerPackageName = "com.android.shell";
2746 }
Richard Uhlerb29f1452018-09-12 16:38:15 +01002747 sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
2748 break;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002749 case "--wait":
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002750 params.mWaitForStagedSessionReady = true;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002751 try {
2752 params.timeoutMs = Long.parseLong(peekNextArg());
2753 getNextArg();
2754 } catch (NumberFormatException ignore) {
2755 }
2756 break;
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002757 case "--no-wait":
2758 params.mWaitForStagedSessionReady = false;
2759 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002760 default:
2761 throw new IllegalArgumentException("Unknown option " + opt);
2762 }
Patrick Baumanndcf19162019-05-29 09:18:58 -07002763 }
2764 if (replaceExisting) {
2765 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002766 }
2767 return params;
2768 }
2769
Makoto Onuki4828a592016-03-15 18:06:57 -07002770 private int runSetHomeActivity() {
2771 final PrintWriter pw = getOutPrintWriter();
2772 int userId = UserHandle.USER_SYSTEM;
2773 String opt;
2774 while ((opt = getNextOption()) != null) {
2775 switch (opt) {
2776 case "--user":
2777 userId = UserHandle.parseUserArg(getNextArgRequired());
2778 break;
2779 default:
2780 pw.println("Error: Unknown option: " + opt);
2781 return 1;
2782 }
2783 }
2784
Bookatz2b5a6012019-04-16 19:41:28 -07002785 String pkgName;
Makoto Onuki4828a592016-03-15 18:06:57 -07002786 String component = getNextArg();
Bookatz2b5a6012019-04-16 19:41:28 -07002787 if (component.indexOf('/') < 0) {
2788 // No component specified, so assume it's just a package name.
2789 pkgName = component;
2790 } else {
2791 ComponentName componentName =
2792 component != null ? ComponentName.unflattenFromString(component) : null;
2793 if (componentName == null) {
2794 pw.println("Error: invalid component name");
2795 return 1;
2796 }
2797 pkgName = componentName.getPackageName();
Makoto Onuki4828a592016-03-15 18:06:57 -07002798 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002799 final int translatedUserId =
2800 translateUserId(userId, UserHandle.USER_NULL, "runSetHomeActivity");
Bookatz2b5a6012019-04-16 19:41:28 -07002801 final CompletableFuture<Boolean> future = new CompletableFuture<>();
2802 final RemoteCallback callback = new RemoteCallback(res -> future.complete(res != null));
Makoto Onuki4828a592016-03-15 18:06:57 -07002803 try {
Bookatz2b5a6012019-04-16 19:41:28 -07002804 IRoleManager roleManager = android.app.role.IRoleManager.Stub.asInterface(
2805 ServiceManager.getServiceOrThrow(Context.ROLE_SERVICE));
2806 roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName,
Todd Kennedyc3c52172019-11-26 13:20:59 -08002807 0, translatedUserId, callback);
Bookatz2b5a6012019-04-16 19:41:28 -07002808 boolean success = future.get();
2809 if (success) {
2810 pw.println("Success");
2811 return 0;
2812 } else {
2813 pw.println("Error: Failed to set default home.");
2814 return 1;
2815 }
Makoto Onuki3bdbf982016-06-23 16:56:35 -07002816 } catch (Exception e) {
Makoto Onuki4828a592016-03-15 18:06:57 -07002817 pw.println(e.toString());
2818 return 1;
2819 }
2820 }
2821
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002822 private int runSetInstaller() throws RemoteException {
2823 final String targetPackage = getNextArg();
2824 final String installerPackageName = getNextArg();
Fyodor Kupolov51245c72016-12-01 11:34:10 -08002825
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002826 if (targetPackage == null || installerPackageName == null) {
2827 getErrPrintWriter().println("Must provide both target and installer package names");
Todd Kennedy74629e32017-08-15 14:48:07 -07002828 return 1;
2829 }
Todd Kennedy74629e32017-08-15 14:48:07 -07002830
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002831 mInterface.setInstallerPackageName(targetPackage, installerPackageName);
2832 getOutPrintWriter().println("Success");
Svet Ganov087dce22017-09-07 15:42:16 -07002833 return 0;
2834 }
2835
Todd Kennedy0a3f0812017-05-08 14:43:15 -07002836 private int runGetInstantAppResolver() {
2837 final PrintWriter pw = getOutPrintWriter();
2838 try {
2839 final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent();
2840 if (instantAppsResolver == null) {
2841 return 1;
2842 }
2843 pw.println(instantAppsResolver.flattenToString());
2844 return 0;
2845 } catch (Exception e) {
2846 pw.println(e.toString());
2847 return 1;
2848 }
2849 }
2850
Tadashi G. Takaokabe5782f2017-02-14 16:41:49 +09002851 private int runHasFeature() {
2852 final PrintWriter err = getErrPrintWriter();
2853 final String featureName = getNextArg();
2854 if (featureName == null) {
2855 err.println("Error: expected FEATURE name");
2856 return 1;
2857 }
2858 final String versionString = getNextArg();
2859 try {
2860 final int version = (versionString == null) ? 0 : Integer.parseInt(versionString);
2861 final boolean hasFeature = mInterface.hasSystemFeature(featureName, version);
2862 getOutPrintWriter().println(hasFeature);
2863 return hasFeature ? 0 : 1;
2864 } catch (NumberFormatException e) {
2865 err.println("Error: illegal version number " + versionString);
2866 return 1;
2867 } catch (RemoteException e) {
2868 err.println(e.toString());
2869 return 1;
2870 }
2871 }
2872
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002873 private int runDump() {
2874 String pkg = getNextArg();
2875 if (pkg == null) {
2876 getErrPrintWriter().println("Error: no package specified");
2877 return 1;
2878 }
2879 ActivityManager.dumpPackageStateStatic(getOutFileDescriptor(), pkg);
2880 return 0;
2881 }
2882
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002883 private int runSetHarmfulAppWarning() throws RemoteException {
2884 int userId = UserHandle.USER_CURRENT;
2885
2886 String opt;
2887 while ((opt = getNextOption()) != null) {
2888 if (opt.equals("--user")) {
2889 userId = UserHandle.parseUserArg(getNextArgRequired());
2890 } else {
2891 getErrPrintWriter().println("Error: Unknown option: " + opt);
2892 return -1;
2893 }
2894 }
2895
Todd Kennedyc3c52172019-11-26 13:20:59 -08002896 final int translatedUserId =
2897 translateUserId(userId, UserHandle.USER_NULL, "runSetHarmfulAppWarning");
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002898 final String packageName = getNextArgRequired();
2899 final String warning = getNextArg();
2900
Todd Kennedyc3c52172019-11-26 13:20:59 -08002901 mInterface.setHarmfulAppWarning(packageName, warning, translatedUserId);
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002902
2903 return 0;
2904 }
2905
Ben Gruver9ef60092018-01-10 11:32:30 -08002906 private int runGetHarmfulAppWarning() throws RemoteException {
2907 int userId = UserHandle.USER_CURRENT;
2908
2909 String opt;
2910 while ((opt = getNextOption()) != null) {
2911 if (opt.equals("--user")) {
2912 userId = UserHandle.parseUserArg(getNextArgRequired());
2913 } else {
2914 getErrPrintWriter().println("Error: Unknown option: " + opt);
2915 return -1;
2916 }
2917 }
2918
Todd Kennedyc3c52172019-11-26 13:20:59 -08002919 final int translatedUserId =
2920 translateUserId(userId, UserHandle.USER_NULL, "runGetHarmfulAppWarning");
Ben Gruver9ef60092018-01-10 11:32:30 -08002921 final String packageName = getNextArgRequired();
Todd Kennedyc3c52172019-11-26 13:20:59 -08002922 final CharSequence warning = mInterface.getHarmfulAppWarning(packageName, translatedUserId);
Ben Gruver9ef60092018-01-10 11:32:30 -08002923 if (!TextUtils.isEmpty(warning)) {
2924 getOutPrintWriter().println(warning);
2925 return 0;
2926 } else {
2927 return 1;
2928 }
2929 }
2930
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002931 private static String checkAbiArgument(String abi) {
2932 if (TextUtils.isEmpty(abi)) {
2933 throw new IllegalArgumentException("Missing ABI argument");
2934 }
2935
2936 if ("-".equals(abi)) {
2937 return abi;
2938 }
2939
2940 final String[] supportedAbis = Build.SUPPORTED_ABIS;
2941 for (String supportedAbi : supportedAbis) {
2942 if (supportedAbi.equals(abi)) {
2943 return abi;
2944 }
2945 }
2946
2947 throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
2948 }
2949
Todd Kennedyc3c52172019-11-26 13:20:59 -08002950 private int translateUserId(int userId, int allUserId, String logContext) {
2951 final boolean allowAll = (allUserId != UserHandle.USER_NULL);
2952 final int translatedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2953 Binder.getCallingUid(), userId, allowAll, true, logContext, "pm command");
2954 return translatedUserId == UserHandle.USER_ALL ? allUserId : translatedUserId;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002955 }
2956
2957 private int doCreateSession(SessionParams params, String installerPackageName, int userId)
2958 throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002959 if (userId == UserHandle.USER_ALL) {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002960 params.installFlags |= PackageManager.INSTALL_ALL_USERS;
2961 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002962 final int translatedUserId =
2963 translateUserId(userId, UserHandle.USER_SYSTEM, "doCreateSession");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002964 final int sessionId = mInterface.getPackageInstaller()
Todd Kennedyc3c52172019-11-26 13:20:59 -08002965 .createSession(params, installerPackageName, translatedUserId);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002966 return sessionId;
2967 }
2968
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08002969 private int doAddFiles(int sessionId, ArrayList<String> args, long sessionSizeBytes,
2970 boolean isApex) throws RemoteException {
Alex Buynytskyyda208152019-11-11 09:34:05 -08002971 PackageInstaller.Session session = new PackageInstaller.Session(
2972 mInterface.getPackageInstaller().openSession(sessionId));
2973 try {
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08002974 // 1. Single file from stdin.
2975 if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) {
2976 String name = "base." + (isApex ? "apex" : "apk");
Alex Buynytskyye0697872020-01-13 09:25:21 -08002977 session.addFile(LOCATION_DATA_APP, name, sessionSizeBytes, STDIN_PATH_BYTES, null);
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08002978 return 0;
Alex Buynytskyyda208152019-11-11 09:34:05 -08002979 }
2980
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08002981 for (String arg : args) {
2982 final int delimLocation = arg.indexOf(':');
2983
2984 // 2. File with specified size read from stdin.
2985 if (delimLocation != -1) {
2986 String name = arg.substring(0, delimLocation);
2987 String sizeStr = arg.substring(delimLocation + 1);
2988 long sizeBytes;
2989
2990 if (TextUtils.isEmpty(name)) {
2991 getErrPrintWriter().println("Empty file name in: " + arg);
2992 return 1;
2993 }
2994 try {
2995 sizeBytes = Long.parseUnsignedLong(sizeStr);
2996 } catch (NumberFormatException e) {
2997 getErrPrintWriter().println("Unable to parse size from: " + arg);
2998 return 1;
2999 }
3000
Alex Buynytskyye0697872020-01-13 09:25:21 -08003001 session.addFile(LOCATION_DATA_APP, name, sizeBytes, STDIN_PATH_BYTES, null);
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003002 continue;
3003 }
3004
3005 // 3. Local file.
3006 final String inPath = arg;
3007
3008 String name = new File(inPath).getName();
3009 byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8);
3010
Alex Buynytskyye0697872020-01-13 09:25:21 -08003011 session.addFile(LOCATION_DATA_APP, name, -1, metadata, null);
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003012 }
Alex Buynytskyyda208152019-11-11 09:34:05 -08003013 return 0;
3014 } finally {
3015 IoUtils.closeQuietly(session);
3016 }
3017 }
3018
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003019 private int doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes,
3020 boolean isApex) throws RemoteException {
3021 final boolean multipleSplits = splitPaths.size() > 1;
3022 for (String splitPath : splitPaths) {
3023 String splitName = multipleSplits ? new File(splitPath).getName()
3024 : "base." + (isApex ? "apex" : "apk");
3025
3026 if (doWriteSplit(sessionId, splitPath, sessionSizeBytes, splitName,
3027 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
3028 return 1;
3029 }
3030 }
3031 return 0;
3032 }
3033
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003034 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003035 boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003036 PackageInstaller.Session session = null;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003037 try {
Alex Buynytskyyda208152019-11-11 09:34:05 -08003038 session = new PackageInstaller.Session(
3039 mInterface.getPackageInstaller().openSession(sessionId));
3040
Jeff Sharkeya651b782018-07-23 13:45:28 -06003041 final PrintWriter pw = getOutPrintWriter();
Alex Buynytskyyda208152019-11-11 09:34:05 -08003042
Jeff Sharkeya651b782018-07-23 13:45:28 -06003043 final ParcelFileDescriptor fd;
3044 if (STDIN_PATH.equals(inPath)) {
3045 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
3046 } else if (inPath != null) {
3047 fd = openFileForSystem(inPath, "r");
3048 if (fd == null) {
3049 return -1;
3050 }
3051 sizeBytes = fd.getStatSize();
3052 if (sizeBytes < 0) {
3053 getErrPrintWriter().println("Unable to get size of: " + inPath);
3054 return -1;
3055 }
3056 } else {
3057 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
3058 }
3059 if (sizeBytes <= 0) {
3060 getErrPrintWriter().println("Error: must specify a APK size");
3061 return 1;
3062 }
3063
Jeff Sharkey0451de62018-02-02 11:27:21 -07003064 session.write(splitName, 0, sizeBytes, fd);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003065
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003066 if (logSuccess) {
Jeff Sharkey0451de62018-02-02 11:27:21 -07003067 pw.println("Success: streamed " + sizeBytes + " bytes");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003068 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003069 return 0;
3070 } catch (IOException e) {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07003071 getErrPrintWriter().println("Error: failed to write; " + e.getMessage());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003072 return 1;
3073 } finally {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003074 IoUtils.closeQuietly(session);
3075 }
3076 }
3077
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003078 private int doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)
3079 throws RemoteException {
3080 final PrintWriter pw = getOutPrintWriter();
3081 PackageInstaller.Session session = null;
3082 try {
3083 session = new PackageInstaller.Session(
3084 mInterface.getPackageInstaller().openSession(parentId));
3085 if (!session.isMultiPackage()) {
3086 getErrPrintWriter().println(
3087 "Error: parent session ID is not a multi-package session");
3088 return 1;
3089 }
3090 for (int i = 0; i < sessionIds.length; i++) {
3091 session.addChildSessionId(sessionIds[i]);
3092 }
3093 if (logSuccess) {
3094 pw.println("Success");
3095 }
3096 return 0;
3097 } finally {
3098 IoUtils.closeQuietly(session);
3099 }
3100 }
3101
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003102 private int doRemoveSplits(int sessionId, Collection<String> splitNames, boolean logSuccess)
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003103 throws RemoteException {
3104 final PrintWriter pw = getOutPrintWriter();
3105 PackageInstaller.Session session = null;
3106 try {
3107 session = new PackageInstaller.Session(
3108 mInterface.getPackageInstaller().openSession(sessionId));
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003109 for (String splitName : splitNames) {
3110 session.removeSplit(splitName);
3111 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003112
3113 if (logSuccess) {
3114 pw.println("Success");
3115 }
3116 return 0;
3117 } catch (IOException e) {
3118 pw.println("Error: failed to remove split; " + e.getMessage());
3119 return 1;
3120 } finally {
3121 IoUtils.closeQuietly(session);
3122 }
3123 }
3124
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003125 private int doCommitSession(int sessionId, boolean logSuccess)
3126 throws RemoteException {
3127
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003128 final PrintWriter pw = getOutPrintWriter();
3129 PackageInstaller.Session session = null;
3130 try {
3131 session = new PackageInstaller.Session(
3132 mInterface.getPackageInstaller().openSession(sessionId));
Dario Frenia8f4b132018-12-30 00:36:49 +00003133 if (!session.isMultiPackage() && !session.isStaged()) {
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003134 // Sanity check that all .dm files match an apk.
3135 // (The installer does not support standalone .dm files and will not process them.)
3136 try {
3137 DexMetadataHelper.validateDexPaths(session.getNames());
3138 } catch (IllegalStateException | IOException e) {
3139 pw.println(
3140 "Warning [Could not validate the dex paths: " + e.getMessage() + "]");
3141 }
Calin Juravle3fc56c32017-12-11 18:26:13 -08003142 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003143 final LocalIntentReceiver receiver = new LocalIntentReceiver();
3144 session.commit(receiver.getIntentSender());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003145 final Intent result = receiver.getResult();
3146 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
3147 PackageInstaller.STATUS_FAILURE);
3148 if (status == PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003149 if (logSuccess) {
Todd Kennedyb6e96e52016-07-20 16:27:39 -07003150 pw.println("Success");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003151 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003152 } else {
3153 pw.println("Failure ["
3154 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003155 }
3156 return status;
3157 } finally {
3158 IoUtils.closeQuietly(session);
3159 }
3160 }
3161
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003162 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003163 final PrintWriter pw = getOutPrintWriter();
3164 PackageInstaller.Session session = null;
3165 try {
3166 session = new PackageInstaller.Session(
3167 mInterface.getPackageInstaller().openSession(sessionId));
3168 session.abandon();
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003169 if (logSuccess) {
3170 pw.println("Success");
3171 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003172 return 0;
3173 } finally {
3174 IoUtils.closeQuietly(session);
3175 }
3176 }
3177
Todd Kennedy60459ab2015-10-30 11:32:16 -07003178 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
3179 boolean summary, int startProtectionLevel, int endProtectionLevel)
3180 throws RemoteException {
3181 final PrintWriter pw = getOutPrintWriter();
3182 final int groupCount = groupList.size();
3183 for (int i = 0; i < groupCount; i++) {
3184 String groupName = groupList.get(i);
3185 String prefix = "";
3186 if (groups) {
3187 if (i > 0) {
3188 pw.println("");
3189 }
3190 if (groupName != null) {
3191 PermissionGroupInfo pgi =
3192 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
3193 if (summary) {
3194 Resources res = getResources(pgi);
3195 if (res != null) {
3196 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
3197 } else {
3198 pw.print(pgi.name + ": ");
3199
3200 }
3201 } else {
3202 pw.println((labels ? "+ " : "") + "group:" + pgi.name);
3203 if (labels) {
3204 pw.println(" package:" + pgi.packageName);
3205 Resources res = getResources(pgi);
3206 if (res != null) {
3207 pw.println(" label:"
3208 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
3209 pw.println(" description:"
3210 + loadText(pgi, pgi.descriptionRes,
3211 pgi.nonLocalizedDescription));
3212 }
3213 }
3214 }
3215 } else {
3216 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
3217 }
3218 prefix = " ";
3219 }
Todd Kennedy1d29b4a2019-07-02 14:49:28 -07003220 List<PermissionInfo> ps = mPermissionManager
3221 .queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -07003222 final int count = ps.size();
3223 boolean first = true;
3224 for (int p = 0 ; p < count ; p++) {
3225 PermissionInfo pi = ps.get(p);
3226 if (groups && groupName == null && pi.group != null) {
3227 continue;
3228 }
3229 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
3230 if (base < startProtectionLevel
3231 || base > endProtectionLevel) {
3232 continue;
3233 }
3234 if (summary) {
3235 if (first) {
3236 first = false;
3237 } else {
3238 pw.print(", ");
3239 }
3240 Resources res = getResources(pi);
3241 if (res != null) {
3242 pw.print(loadText(pi, pi.labelRes,
3243 pi.nonLocalizedLabel));
3244 } else {
3245 pw.print(pi.name);
3246 }
3247 } else {
3248 pw.println(prefix + (labels ? "+ " : "")
3249 + "permission:" + pi.name);
3250 if (labels) {
3251 pw.println(prefix + " package:" + pi.packageName);
3252 Resources res = getResources(pi);
3253 if (res != null) {
3254 pw.println(prefix + " label:"
3255 + loadText(pi, pi.labelRes,
3256 pi.nonLocalizedLabel));
3257 pw.println(prefix + " description:"
3258 + loadText(pi, pi.descriptionRes,
3259 pi.nonLocalizedDescription));
3260 }
3261 pw.println(prefix + " protectionLevel:"
3262 + PermissionInfo.protectionToString(pi.protectionLevel));
3263 }
3264 }
3265 }
3266
3267 if (summary) {
3268 pw.println("");
3269 }
3270 }
3271 }
3272
3273 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
3274 throws RemoteException {
3275 if (nonLocalized != null) {
3276 return nonLocalized.toString();
3277 }
3278 if (res != 0) {
3279 Resources r = getResources(pii);
3280 if (r != null) {
3281 try {
3282 return r.getString(res);
3283 } catch (Resources.NotFoundException e) {
3284 }
3285 }
3286 }
3287 return null;
3288 }
3289
3290 private Resources getResources(PackageItemInfo pii) throws RemoteException {
3291 Resources res = mResourceCache.get(pii.packageName);
3292 if (res != null) return res;
3293
Patrick Baumannbc883f62019-05-21 11:20:11 -07003294 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName,
3295 PackageManager.MATCH_DISABLED_COMPONENTS
3296 | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
3297 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, 0);
Todd Kennedy60459ab2015-10-30 11:32:16 -07003298 AssetManager am = new AssetManager();
3299 am.addAssetPath(ai.publicSourceDir);
3300 res = new Resources(am, null, null);
3301 mResourceCache.put(pii.packageName, res);
3302 return res;
3303 }
3304
3305 @Override
3306 public void onHelp() {
3307 final PrintWriter pw = getOutPrintWriter();
3308 pw.println("Package manager (package) commands:");
3309 pw.println(" help");
3310 pw.println(" Print this help text.");
3311 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003312 pw.println(" path [--user USER_ID] PACKAGE");
3313 pw.println(" Print the path to the .apk of the given PACKAGE.");
3314 pw.println("");
3315 pw.println(" dump PACKAGE");
3316 pw.println(" Print various system state associated with the given PACKAGE.");
3317 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003318 pw.println(" has-feature FEATURE_NAME [version]");
3319 pw.println(" Prints true and returns exit status 0 when system has a FEATURE_NAME,");
3320 pw.println(" otherwise prints false and returns exit status 1");
3321 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003322 pw.println(" list features");
3323 pw.println(" Prints all features of the system.");
3324 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003325 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
3326 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE");
3327 pw.println(" Options:");
3328 pw.println(" -f: dump the name of the .apk file containing the test package");
3329 pw.println("");
3330 pw.println(" list libraries");
3331 pw.println(" Prints all system libraries.");
3332 pw.println("");
3333 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
Jiyong Parkf50a2932018-12-17 13:54:40 +09003334 pw.println(" [--show-versioncode] [--apex-only] [--uid UID] [--user USER_ID] [FILTER]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003335 pw.println(" Prints all packages; optionally only those whose name contains");
3336 pw.println(" the text in FILTER. Options are:");
3337 pw.println(" -f: see their associated file");
Jiyong Park4f49abe2018-12-11 13:37:17 +09003338 pw.println(" -a: all known packages (but excluding APEXes)");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003339 pw.println(" -d: filter to only show disabled packages");
3340 pw.println(" -e: filter to only show enabled packages");
3341 pw.println(" -s: filter to only show system packages");
3342 pw.println(" -3: filter to only show third party packages");
3343 pw.println(" -i: see the installer for the packages");
3344 pw.println(" -l: ignored (used for compatibility with older releases)");
3345 pw.println(" -U: also show the package UID");
3346 pw.println(" -u: also include uninstalled packages");
Jiyong Parkf50a2932018-12-17 13:54:40 +09003347 pw.println(" --show-versioncode: also show the version code");
Jiyong Park4f49abe2018-12-11 13:37:17 +09003348 pw.println(" --apex-only: only show APEX packages");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003349 pw.println(" --uid UID: filter to only show packages with the given UID");
3350 pw.println(" --user USER_ID: only list packages belonging to the given user");
3351 pw.println("");
3352 pw.println(" list permission-groups");
3353 pw.println(" Prints all known permission groups.");
3354 pw.println("");
3355 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
3356 pw.println(" Prints all known permissions; optionally only those in GROUP. Options are:");
3357 pw.println(" -g: organize by group");
3358 pw.println(" -f: print all information");
3359 pw.println(" -s: short summary");
3360 pw.println(" -d: only list dangerous permissions");
3361 pw.println(" -u: list only the permissions users will see");
3362 pw.println("");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003363 pw.println(" list staged-sessions [--only-ready] [--only-sessionid] [--only-parent]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003364 pw.println(" Prints all staged sessions.");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003365 pw.println(" --only-ready: show only staged sessions that are ready");
3366 pw.println(" --only-sessionid: show only sessionId of each session");
3367 pw.println(" --only-parent: hide all children sessions");
3368 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003369 pw.println(" list users");
3370 pw.println(" Prints all users.");
3371 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003372 pw.println(" resolve-activity [--brief] [--components] [--query-flags FLAGS]");
3373 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003374 pw.println(" Prints the activity that resolves to the given INTENT.");
3375 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003376 pw.println(" query-activities [--brief] [--components] [--query-flags FLAGS]");
3377 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003378 pw.println(" Prints all activities that can handle the given INTENT.");
3379 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003380 pw.println(" query-services [--brief] [--components] [--query-flags FLAGS]");
3381 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003382 pw.println(" Prints all services that can handle the given INTENT.");
3383 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003384 pw.println(" query-receivers [--brief] [--components] [--query-flags FLAGS]");
3385 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003386 pw.println(" Prints all broadcast receivers that can handle the given INTENT.");
3387 pw.println("");
Mark De Ruyterbfcd3392019-11-21 12:08:58 -08003388 pw.println(" install [-rtfdgw] [-i PACKAGE] [--user USER_ID|all|current]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003389 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003390 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
3391 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003392 pw.println(" [--preload] [--instant] [--full] [--dont-kill]");
Richard Uhlerb29f1452018-09-12 16:38:15 +01003393 pw.println(" [--enable-rollback]");
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01003394 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
3395 pw.println(" [--apex] [--wait TIMEOUT]");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003396 pw.println(" [PATH [SPLIT...]|-]");
3397 pw.println(" Install an application. Must provide the apk data to install, either as");
3398 pw.println(" file path(s) or '-' to read from stdin. Options are:");
Patrick Baumanna9333492017-11-28 15:23:49 -08003399 pw.println(" -R: disallow replacement of existing application");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003400 pw.println(" -t: allow test packages");
3401 pw.println(" -i: specify package name of installer owning the app");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003402 pw.println(" -f: install application on internal flash");
3403 pw.println(" -d: allow version code downgrade (debuggable packages only)");
3404 pw.println(" -p: partial application install (new split on top of existing pkg)");
3405 pw.println(" -g: grant all runtime permissions");
3406 pw.println(" -S: size in bytes of package, required for stdin");
3407 pw.println(" --user: install under the given user.");
3408 pw.println(" --dont-kill: installing a new feature split, don't kill running app");
Svet Ganov83a3a4a2019-05-03 18:50:43 -07003409 pw.println(" --restrict-permissions: don't whitelist restricted permissions at install");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003410 pw.println(" --originating-uri: set URI where app was downloaded from");
3411 pw.println(" --referrer: set URI that instigated the install of the app");
3412 pw.println(" --pkg: specify expected package name of app being installed");
3413 pw.println(" --abi: override the default ABI of the platform");
Todd Kennedybef39e02019-09-20 15:14:18 -07003414 pw.println(" --instant: cause the app to be installed as an ephemeral install app");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003415 pw.println(" --full: cause the app to be installed as a non-ephemeral full app");
3416 pw.println(" --install-location: force the install location:");
3417 pw.println(" 0=auto, 1=internal only, 2=prefer external");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003418 pw.println(" --install-reason: indicates why the app is being installed:");
3419 pw.println(" 0=unknown, 1=admin policy, 2=device restore,");
3420 pw.println(" 3=device setup, 4=user request");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003421 pw.println(" --force-uuid: force install on to disk volume with given UUID");
MÃ¥rten Kongstad2a5989342018-11-16 15:04:44 +01003422 pw.println(" --apex: install an .apex file, not an .apk");
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01003423 pw.println(" --wait: when performing staged install, wait TIMEOUT milliseconds");
3424 pw.println(" for pre-reboot verification to complete. If TIMEOUT is not");
3425 pw.println(" specified it will wait for " + DEFAULT_WAIT_MS + " milliseconds.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003426 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003427 pw.println(" install-existing [--user USER_ID|all|current]");
3428 pw.println(" [--instant] [--full] [--wait] [--restrict-permissions] PACKAGE");
3429 pw.println(" Installs an existing application for a new user. Options are:");
3430 pw.println(" --user: install for the given user.");
3431 pw.println(" --instant: install as an instant app");
3432 pw.println(" --full: install as a full app");
3433 pw.println(" --wait: wait until the package is installed");
3434 pw.println(" --restrict-permissions: don't whitelist restricted permissions");
3435 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003436 pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
3437 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003438 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
3439 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003440 pw.println(" [--preload] [--instant] [--full] [--dont-kill]");
MÃ¥rten Kongstad2a5989342018-11-16 15:04:44 +01003441 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [--apex] [-S BYTES]");
Dario Freniaac4ba42018-12-06 15:47:16 +00003442 pw.println(" [--multi-package] [--staged]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003443 pw.println(" Like \"install\", but starts an install session. Use \"install-write\"");
3444 pw.println(" to push data into the session, and \"install-commit\" to finish.");
3445 pw.println("");
3446 pw.println(" install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]");
3447 pw.println(" Write an apk into the given install session. If the path is '-', data");
3448 pw.println(" will be read from stdin. Options are:");
3449 pw.println(" -S: size in bytes of package, required for stdin");
3450 pw.println("");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003451 pw.println(" install-remove SESSION_ID SPLIT...");
3452 pw.println(" Mark SPLIT(s) as removed in the given install session.");
3453 pw.println("");
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003454 pw.println(" install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs");
3455 pw.println(" Add one or more session IDs to a multi-package session.");
3456 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003457 pw.println(" install-commit SESSION_ID");
3458 pw.println(" Commit the given active install session, installing the app.");
3459 pw.println("");
3460 pw.println(" install-abandon SESSION_ID");
3461 pw.println(" Delete the given active install session.");
3462 pw.println("");
3463 pw.println(" set-install-location LOCATION");
3464 pw.println(" Changes the default install location. NOTE this is only intended for debugging;");
3465 pw.println(" using this can cause applications to break and other undersireable behavior.");
3466 pw.println(" LOCATION is one of:");
3467 pw.println(" 0 [auto]: Let system decide the best location");
3468 pw.println(" 1 [internal]: Install on internal device storage");
3469 pw.println(" 2 [external]: Install on external media");
3470 pw.println("");
3471 pw.println(" get-install-location");
3472 pw.println(" Returns the current install location: 0, 1 or 2 as per set-install-location.");
3473 pw.println("");
3474 pw.println(" move-package PACKAGE [internal|UUID]");
3475 pw.println("");
3476 pw.println(" move-primary-storage [internal|UUID]");
3477 pw.println("");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003478 pw.println(" uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE]");
3479 pw.println(" PACKAGE [SPLIT...]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003480 pw.println(" Remove the given package name from the system. May remove an entire app");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003481 pw.println(" if no SPLIT names specified, otherwise will remove only the splits of the");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003482 pw.println(" given app. Options are:");
3483 pw.println(" -k: keep the data and cache directories around after package removal.");
3484 pw.println(" --user: remove the app from the given user.");
3485 pw.println(" --versionCode: only uninstall if the app has the given version code.");
3486 pw.println("");
3487 pw.println(" clear [--user USER_ID] PACKAGE");
3488 pw.println(" Deletes all data associated with a package.");
3489 pw.println("");
3490 pw.println(" enable [--user USER_ID] PACKAGE_OR_COMPONENT");
3491 pw.println(" disable [--user USER_ID] PACKAGE_OR_COMPONENT");
3492 pw.println(" disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
3493 pw.println(" disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
3494 pw.println(" default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
3495 pw.println(" These commands change the enabled state of a given package or");
3496 pw.println(" component (written as \"package/class\").");
3497 pw.println("");
3498 pw.println(" hide [--user USER_ID] PACKAGE_OR_COMPONENT");
3499 pw.println(" unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
3500 pw.println("");
3501 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE");
3502 pw.println(" Suspends the specified package (as user).");
3503 pw.println("");
3504 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE");
3505 pw.println(" Unsuspends the specified package (as user).");
3506 pw.println("");
3507 pw.println(" grant [--user USER_ID] PACKAGE PERMISSION");
3508 pw.println(" revoke [--user USER_ID] PACKAGE PERMISSION");
3509 pw.println(" These commands either grant or revoke permissions to apps. The permissions");
3510 pw.println(" must be declared as used in the app's manifest, be runtime permissions");
3511 pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
3512 pw.println("");
3513 pw.println(" reset-permissions");
3514 pw.println(" Revert all runtime permissions to their default state.");
3515 pw.println("");
3516 pw.println(" set-permission-enforced PERMISSION [true|false]");
3517 pw.println("");
3518 pw.println(" get-privapp-permissions TARGET-PACKAGE");
3519 pw.println(" Prints all privileged permissions for a package.");
3520 pw.println("");
3521 pw.println(" get-privapp-deny-permissions TARGET-PACKAGE");
3522 pw.println(" Prints all privileged permissions that are denied for a package.");
3523 pw.println("");
3524 pw.println(" get-oem-permissions TARGET-PACKAGE");
3525 pw.println(" Prints all OEM permissions for a package.");
3526 pw.println("");
3527 pw.println(" set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
3528 pw.println(" get-app-link [--user USER_ID] PACKAGE");
3529 pw.println("");
3530 pw.println(" trim-caches DESIRED_FREE_SPACE [internal|UUID]");
3531 pw.println(" Trim cache files to reach the given free space.");
3532 pw.println("");
Felipe Lemec1ca4412019-09-11 09:23:26 -07003533 pw.println(" list users");
3534 pw.println(" Lists the current users.");
3535 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003536 pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
Bookatz029832a2019-10-04 16:50:22 -07003537 pw.println(" [--guest] [--pre-create-only] [--user-type USER_TYPE] USER_NAME");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003538 pw.println(" Create a new user with the given USER_NAME, printing the new user identifier");
3539 pw.println(" of the user.");
Bookatz029832a2019-10-04 16:50:22 -07003540 // TODO(b/142482943): Consider fetching the list of user types from UMS.
3541 pw.println(" USER_TYPE is the name of a user type, e.g. android.os.usertype.profile.MANAGED.");
3542 pw.println(" If not specified, the default user type is android.os.usertype.full.SECONDARY.");
3543 pw.println(" --managed is shorthand for '--user-type android.os.usertype.profile.MANAGED'.");
3544 pw.println(" --restricted is shorthand for '--user-type android.os.usertype.full.RESTRICTED'.");
3545 pw.println(" --guest is shorthand for '--user-type android.os.usertype.full.GUEST'.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003546 pw.println("");
3547 pw.println(" remove-user USER_ID");
3548 pw.println(" Remove the user with the given USER_IDENTIFIER, deleting all data");
3549 pw.println(" associated with that user");
3550 pw.println("");
3551 pw.println(" set-user-restriction [--user USER_ID] RESTRICTION VALUE");
3552 pw.println("");
3553 pw.println(" get-max-users");
3554 pw.println("");
Alex Chauc12189b2018-01-16 15:01:15 +00003555 pw.println(" get-max-running-users");
3556 pw.println("");
Calin Juravleb6f844d2017-07-17 15:23:21 -07003557 pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
Richard Uhler568a9692016-05-03 16:02:52 -07003558 pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003559 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\". Options are:");
David Brazdil990fb6b2016-03-01 10:02:27 +00003560 pw.println(" -a: compile all packages");
David Brazdil9aa6db02016-03-08 12:57:12 +00003561 pw.println(" -c: clear profile data before compiling");
3562 pw.println(" -f: force compilation even if not needed");
David Brazdil493411a2016-02-01 13:48:46 +00003563 pw.println(" -m: select compilation mode");
Richard Uhler568a9692016-05-03 16:02:52 -07003564 pw.println(" MODE is one of the dex2oat compiler filters:");
Nicolas Geoffrayd1326522017-04-25 12:29:07 +01003565 pw.println(" assume-verified");
3566 pw.println(" extract");
3567 pw.println(" verify");
3568 pw.println(" quicken");
Richard Uhler568a9692016-05-03 16:02:52 -07003569 pw.println(" space-profile");
3570 pw.println(" space");
3571 pw.println(" speed-profile");
3572 pw.println(" speed");
3573 pw.println(" everything");
3574 pw.println(" -r: select compilation reason");
3575 pw.println(" REASON is one of:");
3576 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
3577 pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
3578 }
David Brazdilcf046952016-03-08 16:40:20 +00003579 pw.println(" --reset: restore package to its post-install state");
Richard Uhler568a9692016-05-03 16:02:52 -07003580 pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
Calin Juravlecb5f41e2017-01-25 17:16:08 -08003581 pw.println(" --secondary-dex: compile app secondary dex files");
Calin Juravleb6f844d2017-07-17 15:23:21 -07003582 pw.println(" --split SPLIT: compile only the given split name");
Eric Holka1485f62019-01-07 13:58:25 -08003583 pw.println(" --compile-layouts: compile layout resources for faster inflation");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003584 pw.println("");
3585 pw.println(" force-dex-opt PACKAGE");
3586 pw.println(" Force immediate execution of dex opt for the given PACKAGE.");
3587 pw.println("");
Calin Juravlecb5f41e2017-01-25 17:16:08 -08003588 pw.println(" bg-dexopt-job");
3589 pw.println(" Execute the background optimizations immediately.");
3590 pw.println(" Note that the command only runs the background optimizer logic. It may");
3591 pw.println(" overlap with the actual job but the job scheduler will not be able to");
3592 pw.println(" cancel it. It will also run even if the device is not in the idle");
3593 pw.println(" maintenance mode.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003594 pw.println("");
Calin Juravle1aa5f882017-01-25 01:05:50 -08003595 pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE");
3596 pw.println(" Reconciles the package secondary dex files with the generated oat files.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003597 pw.println("");
David Sehrcae13b02016-06-07 09:11:27 -07003598 pw.println(" dump-profiles TARGET-PACKAGE");
3599 pw.println(" Dumps method/class profile files to");
Calin Juravle21216c62018-05-04 17:35:29 -07003600 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + "TARGET-PACKAGE.txt");
3601 pw.println("");
3602 pw.println(" snapshot-profile TARGET-PACKAGE [--code-path path]");
3603 pw.println(" Take a snapshot of the package profiles to");
3604 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION
3605 + "TARGET-PACKAGE[-code-path].prof");
3606 pw.println(" If TARGET-PACKAGE=android it will take a snapshot of the boot image");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003607 pw.println("");
Makoto Onuki4828a592016-03-15 18:06:57 -07003608 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003609 pw.println(" Set the default home activity (aka launcher).");
Bookatz2b5a6012019-04-16 19:41:28 -07003610 pw.println(" TARGET-COMPONENT can be a package name (com.package.my) or a full");
3611 pw.println(" component (com.package.my/component.name). However, only the package name");
3612 pw.println(" matters: the actual component used will be determined automatically from");
3613 pw.println(" the package.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003614 pw.println("");
3615 pw.println(" set-installer PACKAGE INSTALLER");
3616 pw.println(" Set installer package name");
3617 pw.println("");
3618 pw.println(" get-instantapp-resolver");
3619 pw.println(" Return the name of the component that is the current instant app installer.");
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08003620 pw.println("");
3621 pw.println(" set-harmful-app-warning [--user <USER_ID>] <PACKAGE> [<WARNING>]");
3622 pw.println(" Mark the app as harmful with the given warning message.");
Ben Gruver9ef60092018-01-10 11:32:30 -08003623 pw.println("");
3624 pw.println(" get-harmful-app-warning [--user <USER_ID>] <PACKAGE>");
3625 pw.println(" Return the harmful app warning message for the given app, if present");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08003626 pw.println();
Patrick Baumanna980e142018-02-12 11:45:23 -08003627 pw.println(" uninstall-system-updates");
3628 pw.println(" Remove updates to all system applications and fall back to their /system " +
3629 "version.");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003630 pw.println("");
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +01003631 pw.println(" get-moduleinfo [--all | --installed] [module-name]");
3632 pw.println(" Displays module info. If module-name is specified only that info is shown");
3633 pw.println(" By default, without any argument only installed modules are shown.");
3634 pw.println(" --all: show all module info");
3635 pw.println(" --installed: show only installed modules");
3636 pw.println("");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08003637 Intent.printIntentArgsHelp(pw , "");
Todd Kennedy60459ab2015-10-30 11:32:16 -07003638 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003639
3640 private static class LocalIntentReceiver {
wangmingming155414292018-04-10 09:35:25 +08003641 private final LinkedBlockingQueue<Intent> mResult = new LinkedBlockingQueue<>();
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003642
3643 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
3644 @Override
Dianne Hackborn98305522017-05-05 17:53:53 -07003645 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003646 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
3647 try {
3648 mResult.offer(intent, 5, TimeUnit.SECONDS);
3649 } catch (InterruptedException e) {
3650 throw new RuntimeException(e);
3651 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003652 }
3653 };
3654
3655 public IntentSender getIntentSender() {
3656 return new IntentSender((IIntentSender) mLocalSender);
3657 }
3658
3659 public Intent getResult() {
3660 try {
3661 return mResult.take();
3662 } catch (InterruptedException e) {
3663 throw new RuntimeException(e);
3664 }
3665 }
3666 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07003667}