blob: 8a9f1b3afd023871966096d1876992b79d02c5e0 [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;
Alex Buynytskyy8e9e6a32020-02-08 14:26:45 -080091import android.os.incremental.V4Signature;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070092import android.os.storage.StorageManager;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -070093import android.permission.IPermissionManager;
Calin Juravlebdd94d92018-05-17 01:23:15 -070094import android.system.ErrnoException;
95import android.system.Os;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080096import android.text.TextUtils;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070097import android.text.format.DateUtils;
Fyodor Kupolov51245c72016-12-01 11:34:10 -080098import android.util.ArraySet;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080099import android.util.PrintWriterPrinter;
Songchun Fan38dfe9a2020-02-20 18:12:47 -0800100import android.util.Slog;
Nikita Ioffebf883482019-08-08 22:09:31 +0100101import android.util.SparseArray;
Dario Freni2bef1762018-06-01 14:02:08 +0100102
Shunta Sato4f26cb52016-06-28 09:29:19 +0900103import com.android.internal.content.PackageHelper;
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700104import com.android.internal.util.ArrayUtils;
Nikita Ioffebf883482019-08-08 22:09:31 +0100105import com.android.internal.util.IndentingPrintWriter;
Alex Chauc12189b2018-01-16 15:01:15 +0000106import com.android.server.LocalServices;
Fyodor Kupolov51245c72016-12-01 11:34:10 -0800107import com.android.server.SystemConfig;
Dario Freni2bef1762018-06-01 14:02:08 +0100108
Andreas Gampebdd30d82016-03-20 11:32:11 -0700109import dalvik.system.DexFile;
Dario Freni2bef1762018-06-01 14:02:08 +0100110
111import libcore.io.IoUtils;
112import libcore.io.Streams;
113
Calin Juravle21216c62018-05-04 17:35:29 -0700114import java.io.File;
115import java.io.FileOutputStream;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800116import java.io.IOException;
Calin Juravle21216c62018-05-04 17:35:29 -0700117import java.io.InputStream;
118import java.io.OutputStream;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700119import java.io.PrintWriter;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800120import java.net.URISyntaxException;
Alex Buynytskyyda208152019-11-11 09:34:05 -0800121import java.nio.charset.StandardCharsets;
Calin Juravle21216c62018-05-04 17:35:29 -0700122import java.util.ArrayList;
Alex Buynytskyy17d9da02020-02-12 16:03:30 -0800123import java.util.Base64;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000124import java.util.Collection;
Calin Juravle21216c62018-05-04 17:35:29 -0700125import java.util.Collections;
126import java.util.Comparator;
127import java.util.LinkedList;
128import java.util.List;
129import java.util.Map;
130import java.util.Objects;
131import java.util.WeakHashMap;
Bookatz2b5a6012019-04-16 19:41:28 -0700132import java.util.concurrent.CompletableFuture;
Calin Juravle21216c62018-05-04 17:35:29 -0700133import java.util.concurrent.CountDownLatch;
wangmingming155414292018-04-10 09:35:25 +0800134import java.util.concurrent.LinkedBlockingQueue;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800135import java.util.concurrent.TimeUnit;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700136
137class PackageManagerShellCommand extends ShellCommand {
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700138 /** Path for streaming APK content */
139 private static final String STDIN_PATH = "-";
Calin Juravle21216c62018-05-04 17:35:29 -0700140 /** Path where ART profiles snapshots are dumped for the shell user */
141 private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +0100142 private static final int DEFAULT_WAIT_MS = 60 * 1000;
Songchun Fan38dfe9a2020-02-20 18:12:47 -0800143 private static final String TAG = "PackageManagerShellCommand";
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700144
Todd Kennedy60459ab2015-10-30 11:32:16 -0700145 final IPackageManager mInterface;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700146 final IPermissionManager mPermissionManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700147 final private WeakHashMap<String, Resources> mResourceCache =
148 new WeakHashMap<String, Resources>();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800149 int mTargetUser;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700150 boolean mBrief;
151 boolean mComponents;
Ng Zhi An73971312018-09-11 21:39:14 -0700152 int mQueryFlags;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700153
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700154 PackageManagerShellCommand(
155 PackageManagerService service, IPermissionManager permissionManager) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700156 mInterface = service;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700157 mPermissionManager = permissionManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700158 }
159
160 @Override
161 public int onCommand(String cmd) {
162 if (cmd == null) {
163 return handleDefaultCommands(cmd);
164 }
165
166 final PrintWriter pw = getOutPrintWriter();
167 try {
Alex Buynytskyy476138c2019-12-20 14:41:47 -0800168 switch (cmd) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700169 case "path":
170 return runPath();
171 case "dump":
172 return runDump();
173 case "list":
174 return runList();
175 case "resolve-activity":
176 return runResolveActivity();
177 case "query-activities":
178 return runQueryIntentActivities();
179 case "query-services":
180 return runQueryIntentServices();
181 case "query-receivers":
182 return runQueryIntentReceivers();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800183 case "install":
184 return runInstall();
Alex Buynytskyyda208152019-11-11 09:34:05 -0800185 case "install-streaming":
186 return runStreamingInstall();
Alex Buynytskyy04f73912020-02-10 08:34:18 -0800187 case "install-incremental":
188 return runIncrementalInstall();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800189 case "install-abandon":
190 case "install-destroy":
191 return runInstallAbandon();
192 case "install-commit":
193 return runInstallCommit();
194 case "install-create":
195 return runInstallCreate();
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800196 case "install-remove":
197 return runInstallRemove();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800198 case "install-write":
199 return runInstallWrite();
Todd Kennedybe0b8892017-02-15 14:13:52 -0800200 case "install-existing":
201 return runInstallExisting();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700202 case "set-install-location":
203 return runSetInstallLocation();
204 case "get-install-location":
205 return runGetInstallLocation();
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000206 case "install-add-session":
207 return runInstallAddSession();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700208 case "move-package":
209 return runMovePackage();
210 case "move-primary-storage":
211 return runMovePrimaryStorage();
David Brazdil493411a2016-02-01 13:48:46 +0000212 case "compile":
213 return runCompile();
Calin Juravle1aa5f882017-01-25 01:05:50 -0800214 case "reconcile-secondary-dex-files":
215 return runreconcileSecondaryDexFiles();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700216 case "force-dex-opt":
217 return runForceDexOpt();
Calin Juravlecb5f41e2017-01-25 17:16:08 -0800218 case "bg-dexopt-job":
219 return runDexoptJob();
David Sehra8777082016-05-24 15:25:23 -0700220 case "dump-profiles":
221 return runDumpProfiles();
Calin Juravle21216c62018-05-04 17:35:29 -0700222 case "snapshot-profile":
223 return runSnapshotProfile();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800224 case "uninstall":
225 return runUninstall();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700226 case "clear":
227 return runClear();
228 case "enable":
229 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
230 case "disable":
231 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
232 case "disable-user":
233 return runSetEnabledSetting(
234 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
235 case "disable-until-used":
236 return runSetEnabledSetting(
237 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
238 case "default-state":
239 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
240 case "hide":
241 return runSetHiddenSetting(true);
242 case "unhide":
243 return runSetHiddenSetting(false);
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000244 case "suspend":
245 return runSuspend(true);
246 case "unsuspend":
247 return runSuspend(false);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700248 case "grant":
249 return runGrantRevokePermission(true);
250 case "revoke":
251 return runGrantRevokePermission(false);
252 case "reset-permissions":
253 return runResetPermissions();
254 case "set-permission-enforced":
255 return runSetPermissionEnforced();
Fyodor Kupolov51245c72016-12-01 11:34:10 -0800256 case "get-privapp-permissions":
257 return runGetPrivappPermissions();
Todd Kennedy74629e32017-08-15 14:48:07 -0700258 case "get-privapp-deny-permissions":
259 return runGetPrivappDenyPermissions();
Svet Ganov087dce22017-09-07 15:42:16 -0700260 case "get-oem-permissions":
261 return runGetOemPermissions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700262 case "set-app-link":
263 return runSetAppLink();
264 case "get-app-link":
265 return runGetAppLink();
266 case "trim-caches":
267 return runTrimCaches();
268 case "create-user":
269 return runCreateUser();
270 case "remove-user":
271 return runRemoveUser();
272 case "set-user-restriction":
273 return runSetUserRestriction();
274 case "get-max-users":
275 return runGetMaxUsers();
Alex Chauc12189b2018-01-16 15:01:15 +0000276 case "get-max-running-users":
277 return runGetMaxRunningUsers();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700278 case "set-home-activity":
279 return runSetHomeActivity();
280 case "set-installer":
281 return runSetInstaller();
Todd Kennedy0a3f0812017-05-08 14:43:15 -0700282 case "get-instantapp-resolver":
283 return runGetInstantAppResolver();
Tadashi G. Takaokabe5782f2017-02-14 16:41:49 +0900284 case "has-feature":
285 return runHasFeature();
Ben Gruver1ab3d6e2017-12-07 13:45:08 -0800286 case "set-harmful-app-warning":
287 return runSetHarmfulAppWarning();
Ben Gruver9ef60092018-01-10 11:32:30 -0800288 case "get-harmful-app-warning":
289 return runGetHarmfulAppWarning();
Abhijeet Kaur84b1f5d2019-01-21 17:18:03 +0000290 case "get-stagedsessions":
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100291 return runListStagedSessions();
Patrick Baumanna980e142018-02-12 11:45:23 -0800292 case "uninstall-system-updates":
293 return uninstallSystemUpdates();
Narayan Kamathc5d752e2019-01-23 14:06:35 +0000294 case "rollback-app":
295 return runRollbackApp();
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +0100296 case "get-moduleinfo":
297 return runGetModuleInfo();
Patrick Baumann4b491872020-02-25 11:51:44 -0800298 case "log-visibility":
299 return runLogVisibility();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700300 default: {
301 String nextArg = getNextArg();
302 if (nextArg == null) {
303 if (cmd.equalsIgnoreCase("-l")) {
304 return runListPackages(false);
305 } else if (cmd.equalsIgnoreCase("-lf")) {
306 return runListPackages(true);
307 }
308 } else if (getNextArg() == null) {
309 if (cmd.equalsIgnoreCase("-p")) {
310 return displayPackageFilePath(nextArg, UserHandle.USER_SYSTEM);
311 }
312 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700313 return handleDefaultCommands(cmd);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700314 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700315 }
316 } catch (RemoteException e) {
317 pw.println("Remote exception: " + e);
318 }
319 return -1;
320 }
321
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +0100322 /**
323 * Shows module info
324 *
325 * Usage: get-moduleinfo [--all | --installed] [module-name]
326 * Example: get-moduleinfo, get-moduleinfo --all, get-moduleinfo xyz
327 */
328 private int runGetModuleInfo() {
329 final PrintWriter pw = getOutPrintWriter();
330 int flags = 0;
331
332 String opt;
333 while ((opt = getNextOption()) != null) {
334 switch (opt) {
335 case "--all":
336 flags |= PackageManager.MATCH_ALL;
337 break;
338 case "--installed":
339 break;
340 default:
341 pw.println("Error: Unknown option: " + opt);
342 return -1;
343 }
344 }
345
346 String moduleName = getNextArg();
347 try {
348 if (moduleName != null) {
349 ModuleInfo m = mInterface.getModuleInfo(moduleName, flags);
350 pw.println(m.toString() + " packageName: " + m.getPackageName());
351
352 } else {
353 List<ModuleInfo> modules = mInterface.getInstalledModules(flags);
354 for (ModuleInfo m: modules) {
355 pw.println(m.toString() + " packageName: " + m.getPackageName());
356 }
357 }
358 } catch (RemoteException e) {
359 pw.println("Failure [" + e.getClass().getName() + " - " + e.getMessage() + "]");
360 return -1;
361 }
362 return 1;
363 }
364
Patrick Baumann4b491872020-02-25 11:51:44 -0800365 private int runLogVisibility() {
366 final PrintWriter pw = getOutPrintWriter();
367 boolean enable = true;
368
369 String opt;
370 while ((opt = getNextOption()) != null) {
371 switch (opt) {
372 case "--disable":
373 enable = false;
374 break;
375 case "--enable":
376 enable = true;
377 break;
378 default:
379 pw.println("Error: Unknown option: " + opt);
380 return -1;
381 }
382 }
383
384 String packageName = getNextArg();
385 if (packageName != null) {
386 LocalServices.getService(PackageManagerInternal.class)
387 .setVisibilityLogging(packageName, enable);
388 } else {
389 getErrPrintWriter().println("Error: no package specified");
390 return -1;
391 }
392 return 1;
393 }
394
Patrick Baumanna980e142018-02-12 11:45:23 -0800395 private int uninstallSystemUpdates() {
396 final PrintWriter pw = getOutPrintWriter();
397 List<String> failedUninstalls = new LinkedList<>();
398 try {
399 final ParceledListSlice<ApplicationInfo> packages =
400 mInterface.getInstalledApplications(
401 PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
402 final IPackageInstaller installer = mInterface.getPackageInstaller();
403 List<ApplicationInfo> list = packages.getList();
404 for (ApplicationInfo info : list) {
405 if (info.isUpdatedSystemApp()) {
406 pw.println("Uninstalling updates to " + info.packageName + "...");
407 final LocalIntentReceiver receiver = new LocalIntentReceiver();
408 installer.uninstall(new VersionedPackage(info.packageName,
409 info.versionCode), null /*callerPackageName*/, 0 /* flags */,
410 receiver.getIntentSender(), 0);
411
412 final Intent result = receiver.getResult();
413 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
414 PackageInstaller.STATUS_FAILURE);
415 if (status != PackageInstaller.STATUS_SUCCESS) {
416 failedUninstalls.add(info.packageName);
417 }
418 }
419 }
420 } catch (RemoteException e) {
421 pw.println("Failure ["
422 + e.getClass().getName() + " - "
423 + e.getMessage() + "]");
424 return 0;
425 }
426 if (!failedUninstalls.isEmpty()) {
427 pw.println("Failure [Couldn't uninstall packages: "
428 + TextUtils.join(", ", failedUninstalls)
429 + "]");
430 return 0;
431 }
432 pw.println("Success");
433 return 1;
434 }
435
Narayan Kamathc5d752e2019-01-23 14:06:35 +0000436 private int runRollbackApp() {
437 final PrintWriter pw = getOutPrintWriter();
438
439 final String packageName = getNextArgRequired();
440 if (packageName == null) {
441 pw.println("Error: package name not specified");
442 return 1;
443 }
444
445 final LocalIntentReceiver receiver = new LocalIntentReceiver();
446 try {
447 IRollbackManager rm = IRollbackManager.Stub.asInterface(
448 ServiceManager.getService(Context.ROLLBACK_SERVICE));
449
450 RollbackInfo rollback = null;
451 for (RollbackInfo r : (List<RollbackInfo>) rm.getAvailableRollbacks().getList()) {
452 for (PackageRollbackInfo info : r.getPackages()) {
453 if (packageName.equals(info.getPackageName())) {
454 rollback = r;
455 break;
456 }
457 }
458 }
459
460 if (rollback == null) {
461 pw.println("No available rollbacks for: " + packageName);
462 return 1;
463 }
464
465 rm.commitRollback(rollback.getRollbackId(),
466 ParceledListSlice.<VersionedPackage>emptyList(),
467 "com.android.shell", receiver.getIntentSender());
468 } catch (RemoteException re) {
469 // Cannot happen.
470 }
471
472 final Intent result = receiver.getResult();
473 final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
474 RollbackManager.STATUS_FAILURE);
475 if (status == RollbackManager.STATUS_SUCCESS) {
476 pw.println("Success");
477 return 0;
478 } else {
479 pw.println("Failure ["
480 + result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE) + "]");
481 return 1;
482 }
483 }
484
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000485 private void setParamsSize(InstallParams params, List<String> inPaths) {
486 if (params.sessionParams.sizeBytes != -1 || STDIN_PATH.equals(inPaths.get(0))) {
487 return;
488 }
489
490 long sessionSize = 0;
491
492 for (String inPath : inPaths) {
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700493 final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");
494 if (fd == null) {
495 getErrPrintWriter().println("Error: Can't open file: " + inPath);
496 throw new IllegalArgumentException("Error: Can't open file: " + inPath);
497 }
498 try {
Winson14ff7172019-10-23 10:42:27 -0700499 ApkLite baseApk = ApkLiteParseUtils.parseApkLite(fd.getFileDescriptor(), inPath, 0);
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700500 PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
501 null, null);
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000502 sessionSize += PackageHelper.calculateInstalledSize(pkgLite,
503 params.sessionParams.abiOverride, fd.getFileDescriptor());
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700504 } catch (PackageParserException | IOException e) {
505 getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath);
506 throw new IllegalArgumentException(
507 "Error: Failed to parse APK file: " + inPath, e);
508 } finally {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900509 try {
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700510 fd.close();
511 } catch (IOException e) {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900512 }
513 }
514 }
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -0800515
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000516 params.sessionParams.setSize(sessionSize);
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700517 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700518 /**
519 * Displays the package file for a package.
520 * @param pckg
521 */
522 private int displayPackageFilePath(String pckg, int userId) throws RemoteException {
Bill Lin7fd81af2019-10-04 00:31:21 +0800523 PackageInfo info = mInterface.getPackageInfo(pckg, PackageManager.MATCH_APEX, userId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700524 if (info != null && info.applicationInfo != null) {
525 final PrintWriter pw = getOutPrintWriter();
526 pw.print("package:");
527 pw.println(info.applicationInfo.sourceDir);
528 if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
529 for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
530 pw.print("package:");
531 pw.println(splitSourceDir);
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800532 }
533 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700534 return 0;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800535 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700536 return 1;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800537 }
538
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700539 private int runPath() throws RemoteException {
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000540 int userId = UserHandle.USER_SYSTEM;
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700541 String option = getNextOption();
542 if (option != null && option.equals("--user")) {
543 userId = UserHandle.parseUserArg(getNextArgRequired());
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000544 }
545
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700546 String pkg = getNextArgRequired();
547 if (pkg == null) {
548 getErrPrintWriter().println("Error: no package specified");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000549 return 1;
550 }
Todd Kennedyc3c52172019-11-26 13:20:59 -0800551 final int translatedUserId =
552 translateUserId(userId, UserHandle.USER_NULL, "runPath");
553 return displayPackageFilePath(pkg, translatedUserId);
David Sehra8777082016-05-24 15:25:23 -0700554 }
555
Todd Kennedy60459ab2015-10-30 11:32:16 -0700556 private int runList() throws RemoteException {
557 final PrintWriter pw = getOutPrintWriter();
558 final String type = getNextArg();
559 if (type == null) {
560 pw.println("Error: didn't specify type of data to list");
561 return -1;
562 }
563 switch(type) {
564 case "features":
565 return runListFeatures();
566 case "instrumentation":
567 return runListInstrumentation();
568 case "libraries":
569 return runListLibraries();
570 case "package":
571 case "packages":
572 return runListPackages(false /*showSourceDir*/);
573 case "permission-groups":
574 return runListPermissionGroups();
575 case "permissions":
576 return runListPermissions();
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100577 case "staged-sessions":
578 return runListStagedSessions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700579 case "users":
580 ServiceManager.getService("user").shellCommand(
581 getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
582 new String[] { "list" }, getShellCallback(), adoptResultReceiver());
583 return 0;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700584 }
585 pw.println("Error: unknown list type '" + type + "'");
586 return -1;
587 }
588
589 private int runListFeatures() throws RemoteException {
590 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700591 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700592
593 // sort by name
594 Collections.sort(list, new Comparator<FeatureInfo>() {
595 public int compare(FeatureInfo o1, FeatureInfo o2) {
596 if (o1.name == o2.name) return 0;
597 if (o1.name == null) return -1;
598 if (o2.name == null) return 1;
599 return o1.name.compareTo(o2.name);
600 }
601 });
602
603 final int count = (list != null) ? list.size() : 0;
604 for (int p = 0; p < count; p++) {
605 FeatureInfo fi = list.get(p);
606 pw.print("feature:");
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700607 if (fi.name != null) {
608 pw.print(fi.name);
609 if (fi.version > 0) {
610 pw.print("=");
611 pw.print(fi.version);
612 }
613 pw.println();
614 } else {
615 pw.println("reqGlEsVersion=0x"
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700616 + Integer.toHexString(fi.reqGlEsVersion));
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700617 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700618 }
619 return 0;
620 }
621
622 private int runListInstrumentation() throws RemoteException {
623 final PrintWriter pw = getOutPrintWriter();
624 boolean showSourceDir = false;
625 String targetPackage = null;
626
627 try {
628 String opt;
629 while ((opt = getNextArg()) != null) {
630 switch (opt) {
631 case "-f":
632 showSourceDir = true;
633 break;
634 default:
635 if (opt.charAt(0) != '-') {
636 targetPackage = opt;
637 } else {
638 pw.println("Error: Unknown option: " + opt);
639 return -1;
640 }
641 break;
642 }
643 }
644 } catch (RuntimeException ex) {
645 pw.println("Error: " + ex.toString());
646 return -1;
647 }
648
649 final List<InstrumentationInfo> list =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700650 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700651
652 // sort by target package
653 Collections.sort(list, new Comparator<InstrumentationInfo>() {
654 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
655 return o1.targetPackage.compareTo(o2.targetPackage);
656 }
657 });
658
659 final int count = (list != null) ? list.size() : 0;
660 for (int p = 0; p < count; p++) {
661 final InstrumentationInfo ii = list.get(p);
662 pw.print("instrumentation:");
663 if (showSourceDir) {
664 pw.print(ii.sourceDir);
665 pw.print("=");
666 }
667 final ComponentName cn = new ComponentName(ii.packageName, ii.name);
668 pw.print(cn.flattenToShortString());
669 pw.print(" (target=");
670 pw.print(ii.targetPackage);
671 pw.println(")");
672 }
673 return 0;
674 }
675
676 private int runListLibraries() throws RemoteException {
677 final PrintWriter pw = getOutPrintWriter();
678 final List<String> list = new ArrayList<String>();
679 final String[] rawList = mInterface.getSystemSharedLibraryNames();
680 for (int i = 0; i < rawList.length; i++) {
681 list.add(rawList[i]);
682 }
683
684 // sort by name
685 Collections.sort(list, new Comparator<String>() {
686 public int compare(String o1, String o2) {
687 if (o1 == o2) return 0;
688 if (o1 == null) return -1;
689 if (o2 == null) return 1;
690 return o1.compareTo(o2);
691 }
692 });
693
694 final int count = (list != null) ? list.size() : 0;
695 for (int p = 0; p < count; p++) {
696 String lib = list.get(p);
697 pw.print("library:");
698 pw.println(lib);
699 }
700 return 0;
701 }
702
703 private int runListPackages(boolean showSourceDir) throws RemoteException {
704 final PrintWriter pw = getOutPrintWriter();
705 int getFlags = 0;
706 boolean listDisabled = false, listEnabled = false;
707 boolean listSystem = false, listThirdParty = false;
708 boolean listInstaller = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700709 boolean showUid = false;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800710 boolean showVersionCode = false;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900711 boolean listApexOnly = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700712 int uid = -1;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700713 int userId = UserHandle.USER_SYSTEM;
714 try {
715 String opt;
716 while ((opt = getNextOption()) != null) {
717 switch (opt) {
718 case "-d":
719 listDisabled = true;
720 break;
721 case "-e":
722 listEnabled = true;
723 break;
Andreas Gampe1f110452018-06-04 11:47:48 -0700724 case "-a":
725 getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
726 getFlags |= PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS;
727 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700728 case "-f":
729 showSourceDir = true;
730 break;
731 case "-i":
732 listInstaller = true;
733 break;
734 case "-l":
735 // old compat
736 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700737 case "-s":
738 listSystem = true;
739 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700740 case "-U":
741 showUid = true;
742 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700743 case "-u":
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700744 getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700745 break;
746 case "-3":
747 listThirdParty = true;
748 break;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800749 case "--show-versioncode":
750 showVersionCode = true;
751 break;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900752 case "--apex-only":
753 getFlags |= PackageManager.MATCH_APEX;
754 listApexOnly = true;
755 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700756 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800757 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy60459ab2015-10-30 11:32:16 -0700758 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700759 case "--uid":
760 showUid = true;
761 uid = Integer.parseInt(getNextArgRequired());
762 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700763 default:
764 pw.println("Error: Unknown option: " + opt);
765 return -1;
766 }
767 }
768 } catch (RuntimeException ex) {
769 pw.println("Error: " + ex.toString());
770 return -1;
771 }
772
773 final String filter = getNextArg();
774
Todd Kennedy5385b512019-11-26 15:49:06 -0800775 if (userId == UserHandle.USER_ALL) {
776 getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
777 }
Todd Kennedyc3c52172019-11-26 13:20:59 -0800778 final int translatedUserId =
Todd Kennedy5385b512019-11-26 15:49:06 -0800779 translateUserId(userId, UserHandle.USER_SYSTEM, "runListPackages");
Todd Kennedy60459ab2015-10-30 11:32:16 -0700780 @SuppressWarnings("unchecked")
781 final ParceledListSlice<PackageInfo> slice =
Todd Kennedyc3c52172019-11-26 13:20:59 -0800782 mInterface.getInstalledPackages(getFlags, translatedUserId);
Todd Kennedy60459ab2015-10-30 11:32:16 -0700783 final List<PackageInfo> packages = slice.getList();
784
785 final int count = packages.size();
786 for (int p = 0; p < count; p++) {
787 final PackageInfo info = packages.get(p);
788 if (filter != null && !info.packageName.contains(filter)) {
789 continue;
790 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900791 final boolean isApex = info.isApex;
792 if (uid != -1 && !isApex && info.applicationInfo.uid != uid) {
Felipe Lemeeece9862016-06-29 11:45:03 -0700793 continue;
794 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900795
796 final boolean isSystem = !isApex &&
Todd Kennedy60459ab2015-10-30 11:32:16 -0700797 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900798 final boolean isEnabled = !isApex && info.applicationInfo.enabled;
799 if ((!listDisabled || !isEnabled) &&
800 (!listEnabled || isEnabled) &&
Todd Kennedy60459ab2015-10-30 11:32:16 -0700801 (!listSystem || isSystem) &&
Jiyong Park4f49abe2018-12-11 13:37:17 +0900802 (!listThirdParty || !isSystem) &&
803 (!listApexOnly || isApex)) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700804 pw.print("package:");
JW Wang9a722632019-09-30 10:42:30 +0800805 if (showSourceDir) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700806 pw.print(info.applicationInfo.sourceDir);
807 pw.print("=");
808 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800809 pw.print(info.packageName);
Jiyong Parkf50a2932018-12-17 13:54:40 +0900810 if (showVersionCode) {
Todd Kennedybadc69a2017-01-24 11:05:47 -0800811 pw.print(" versionCode:");
Jiyong Parkf50a2932018-12-17 13:54:40 +0900812 if (info.applicationInfo != null) {
Dario Freni788ecb12019-01-23 18:49:32 +0000813 pw.print(info.applicationInfo.longVersionCode);
Jiyong Parkf50a2932018-12-17 13:54:40 +0900814 } else {
Dario Freni788ecb12019-01-23 18:49:32 +0000815 pw.print(info.getLongVersionCode());
Jiyong Parkf50a2932018-12-17 13:54:40 +0900816 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800817 }
Mohammad Samiul Islam6b7ad942019-05-07 20:28:00 +0100818 if (listInstaller) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700819 pw.print(" installer=");
820 pw.print(mInterface.getInstallerPackageName(info.packageName));
821 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900822 if (showUid && !isApex) {
Felipe Lemeeece9862016-06-29 11:45:03 -0700823 pw.print(" uid:");
824 pw.print(info.applicationInfo.uid);
825 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700826 pw.println();
827 }
828 }
829 return 0;
830 }
831
832 private int runListPermissionGroups() throws RemoteException {
833 final PrintWriter pw = getOutPrintWriter();
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700834 final List<PermissionGroupInfo> pgs =
835 mPermissionManager.getAllPermissionGroups(0).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700836
837 final int count = pgs.size();
838 for (int p = 0; p < count ; p++) {
839 final PermissionGroupInfo pgi = pgs.get(p);
840 pw.print("permission group:");
841 pw.println(pgi.name);
842 }
843 return 0;
844 }
845
846 private int runListPermissions() throws RemoteException {
847 final PrintWriter pw = getOutPrintWriter();
848 boolean labels = false;
849 boolean groups = false;
850 boolean userOnly = false;
851 boolean summary = false;
852 boolean dangerousOnly = false;
853 String opt;
854 while ((opt = getNextOption()) != null) {
855 switch (opt) {
856 case "-d":
857 dangerousOnly = true;
858 break;
859 case "-f":
860 labels = true;
861 break;
862 case "-g":
863 groups = true;
864 break;
865 case "-s":
866 groups = true;
867 labels = true;
868 summary = true;
869 break;
870 case "-u":
871 userOnly = true;
872 break;
873 default:
874 pw.println("Error: Unknown option: " + opt);
875 return 1;
876 }
877 }
878
879 final ArrayList<String> groupList = new ArrayList<String>();
880 if (groups) {
881 final List<PermissionGroupInfo> infos =
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700882 mPermissionManager.getAllPermissionGroups(0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700883 final int count = infos.size();
884 for (int i = 0; i < count; i++) {
885 groupList.add(infos.get(i).name);
886 }
887 groupList.add(null);
888 } else {
889 final String grp = getNextArg();
890 groupList.add(grp);
891 }
892
893 if (dangerousOnly) {
894 pw.println("Dangerous Permissions:");
895 pw.println("");
896 doListPermissions(groupList, groups, labels, summary,
897 PermissionInfo.PROTECTION_DANGEROUS,
898 PermissionInfo.PROTECTION_DANGEROUS);
899 if (userOnly) {
900 pw.println("Normal Permissions:");
901 pw.println("");
902 doListPermissions(groupList, groups, labels, summary,
903 PermissionInfo.PROTECTION_NORMAL,
904 PermissionInfo.PROTECTION_NORMAL);
905 }
906 } else if (userOnly) {
907 pw.println("Dangerous and Normal Permissions:");
908 pw.println("");
909 doListPermissions(groupList, groups, labels, summary,
910 PermissionInfo.PROTECTION_NORMAL,
911 PermissionInfo.PROTECTION_DANGEROUS);
912 } else {
913 pw.println("All Permissions:");
914 pw.println("");
915 doListPermissions(groupList, groups, labels, summary,
916 -10000, 10000);
917 }
918 return 0;
919 }
920
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100921 private static class SessionDump {
922 boolean onlyParent; // Show parent sessions only
923 boolean onlyReady; // Show only staged sessions that are in ready state
924 boolean onlySessionId; // Show sessionId only
925 }
926
927 // Returns true if the provided flag is a session flag and given SessionDump was updated
928 private boolean setSessionFlag(String flag, SessionDump sessionDump) {
929 switch (flag) {
930 case "--only-parent":
931 sessionDump.onlyParent = true;
932 break;
933 case "--only-ready":
934 sessionDump.onlyReady = true;
935 break;
936 case "--only-sessionid":
937 sessionDump.onlySessionId = true;
938 break;
939 default:
940 return false;
941 }
942 return true;
943 }
944
945 private int runListStagedSessions() {
Todd Kennedy5385b512019-11-26 15:49:06 -0800946 try (IndentingPrintWriter pw = new IndentingPrintWriter(
947 getOutPrintWriter(), /* singleIndent */ " ", /* wrapLength */ 120)) {
948 final SessionDump sessionDump = new SessionDump();
949 String opt;
950 while ((opt = getNextOption()) != null) {
951 if (!setSessionFlag(opt, sessionDump)) {
952 pw.println("Error: Unknown option: " + opt);
953 return -1;
954 }
955 }
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100956
Todd Kennedy5385b512019-11-26 15:49:06 -0800957 try {
958 final List<SessionInfo> stagedSessions =
959 mInterface.getPackageInstaller().getStagedSessions().getList();
960 printSessionList(pw, stagedSessions, sessionDump);
961 } catch (RemoteException e) {
962 pw.println("Failure ["
963 + e.getClass().getName() + " - "
964 + e.getMessage() + "]");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100965 return -1;
966 }
Todd Kennedy5385b512019-11-26 15:49:06 -0800967 return 1;
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100968 }
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100969 }
970
971 private void printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions,
972 SessionDump sessionDump) {
973 final SparseArray<SessionInfo> sessionById = new SparseArray<>(stagedSessions.size());
974 for (SessionInfo session : stagedSessions) {
975 sessionById.put(session.getSessionId(), session);
976 }
977 for (SessionInfo session: stagedSessions) {
978 if (sessionDump.onlyReady && !session.isStagedSessionReady()) {
979 continue;
980 }
981 if (session.getParentSessionId() != SessionInfo.INVALID_ID) {
982 continue;
983 }
984 printSession(pw, session, sessionDump);
985 if (session.isMultiPackage() && !sessionDump.onlyParent) {
986 pw.increaseIndent();
987 final int[] childIds = session.getChildSessionIds();
988 for (int i = 0; i < childIds.length; i++) {
989 final SessionInfo childSession = sessionById.get(childIds[i]);
990 if (childSession == null) {
991 if (sessionDump.onlySessionId) {
992 pw.println(childIds[i]);
993 } else {
994 pw.println("sessionId = " + childIds[i] + "; not found");
995 }
996 } else {
997 printSession(pw, childSession, sessionDump);
998 }
999 }
1000 pw.decreaseIndent();
1001 }
1002 }
1003 }
1004
1005 private static void printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump) {
1006 if (sessionDump.onlySessionId) {
1007 pw.println(session.getSessionId());
1008 return;
1009 }
1010 pw.println("sessionId = " + session.getSessionId()
1011 + "; appPackageName = " + session.getAppPackageName()
1012 + "; isStaged = " + session.isStaged()
1013 + "; isReady = " + session.isStagedSessionReady()
1014 + "; isApplied = " + session.isStagedSessionApplied()
1015 + "; isFailed = " + session.isStagedSessionFailed() + ";");
1016 }
1017
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001018 private Intent parseIntentAndUser() throws URISyntaxException {
1019 mTargetUser = UserHandle.USER_CURRENT;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001020 mBrief = false;
1021 mComponents = false;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001022 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
1023 @Override
1024 public boolean handleOption(String opt, ShellCommand cmd) {
1025 if ("--user".equals(opt)) {
1026 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
1027 return true;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001028 } else if ("--brief".equals(opt)) {
1029 mBrief = true;
1030 return true;
1031 } else if ("--components".equals(opt)) {
1032 mComponents = true;
1033 return true;
Ng Zhi An73971312018-09-11 21:39:14 -07001034 } else if ("--query-flags".equals(opt)) {
1035 mQueryFlags = Integer.decode(cmd.getNextArgRequired());
1036 return true;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001037 }
1038 return false;
1039 }
1040 });
1041 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1042 Binder.getCallingUid(), mTargetUser, false, false, null, null);
1043 return intent;
1044 }
1045
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001046 private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri,
1047 boolean brief, boolean components) {
1048 if (brief || components) {
1049 final ComponentName comp;
1050 if (ri.activityInfo != null) {
1051 comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
1052 } else if (ri.serviceInfo != null) {
1053 comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
1054 } else if (ri.providerInfo != null) {
1055 comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name);
1056 } else {
1057 comp = null;
1058 }
1059 if (comp != null) {
1060 if (!components) {
1061 pr.println(prefix + "priority=" + ri.priority
1062 + " preferredOrder=" + ri.preferredOrder
1063 + " match=0x" + Integer.toHexString(ri.match)
1064 + " specificIndex=" + ri.specificIndex
1065 + " isDefault=" + ri.isDefault);
1066 }
1067 pr.println(prefix + comp.flattenToShortString());
1068 return;
1069 }
1070 }
1071 ri.dump(pr, prefix);
1072 }
1073
Dianne Hackborn99878e92015-12-02 16:27:41 -08001074 private int runResolveActivity() {
1075 Intent intent;
1076 try {
1077 intent = parseIntentAndUser();
1078 } catch (URISyntaxException e) {
1079 throw new RuntimeException(e.getMessage(), e);
1080 }
1081 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001082 ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), mQueryFlags,
1083 mTargetUser);
Dianne Hackborn99878e92015-12-02 16:27:41 -08001084 PrintWriter pw = getOutPrintWriter();
1085 if (ri == null) {
1086 pw.println("No activity found");
1087 } else {
1088 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001089 printResolveInfo(pr, "", ri, mBrief, mComponents);
Dianne Hackborn99878e92015-12-02 16:27:41 -08001090 }
1091 } catch (RemoteException e) {
1092 throw new RuntimeException("Failed calling service", e);
1093 }
1094 return 0;
1095 }
1096
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001097 private int runQueryIntentActivities() {
1098 Intent intent;
1099 try {
1100 intent = parseIntentAndUser();
1101 } catch (URISyntaxException e) {
1102 throw new RuntimeException(e.getMessage(), e);
1103 }
1104 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001105 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(),
1106 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001107 PrintWriter pw = getOutPrintWriter();
1108 if (result == null || result.size() <= 0) {
1109 pw.println("No activities found");
1110 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001111 if (!mComponents) {
1112 pw.print(result.size()); pw.println(" activities found:");
1113 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1114 for (int i = 0; i < result.size(); i++) {
1115 pw.print(" Activity #"); pw.print(i); pw.println(":");
1116 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1117 }
1118 } else {
1119 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1120 for (int i = 0; i < result.size(); i++) {
1121 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1122 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001123 }
1124 }
1125 } catch (RemoteException e) {
1126 throw new RuntimeException("Failed calling service", e);
1127 }
1128 return 0;
1129 }
1130
1131 private int runQueryIntentServices() {
1132 Intent intent;
1133 try {
1134 intent = parseIntentAndUser();
1135 } catch (URISyntaxException e) {
1136 throw new RuntimeException(e.getMessage(), e);
1137 }
1138 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001139 List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(),
1140 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001141 PrintWriter pw = getOutPrintWriter();
1142 if (result == null || result.size() <= 0) {
1143 pw.println("No services found");
1144 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001145 if (!mComponents) {
1146 pw.print(result.size()); pw.println(" services found:");
1147 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1148 for (int i = 0; i < result.size(); i++) {
1149 pw.print(" Service #"); pw.print(i); pw.println(":");
1150 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1151 }
1152 } else {
1153 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1154 for (int i = 0; i < result.size(); i++) {
1155 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1156 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001157 }
1158 }
1159 } catch (RemoteException e) {
1160 throw new RuntimeException("Failed calling service", e);
1161 }
1162 return 0;
1163 }
1164
1165 private int runQueryIntentReceivers() {
1166 Intent intent;
1167 try {
1168 intent = parseIntentAndUser();
1169 } catch (URISyntaxException e) {
1170 throw new RuntimeException(e.getMessage(), e);
1171 }
1172 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001173 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(),
1174 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001175 PrintWriter pw = getOutPrintWriter();
1176 if (result == null || result.size() <= 0) {
1177 pw.println("No receivers found");
1178 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001179 if (!mComponents) {
1180 pw.print(result.size()); pw.println(" receivers found:");
1181 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1182 for (int i = 0; i < result.size(); i++) {
1183 pw.print(" Receiver #"); pw.print(i); pw.println(":");
1184 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1185 }
1186 } else {
1187 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1188 for (int i = 0; i < result.size(); i++) {
1189 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1190 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001191 }
1192 }
1193 } catch (RemoteException e) {
1194 throw new RuntimeException("Failed calling service", e);
1195 }
1196 return 0;
1197 }
1198
Alex Buynytskyyda208152019-11-11 09:34:05 -08001199 private int runStreamingInstall() throws RemoteException {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001200 final InstallParams params = makeInstallParams();
Alex Buynytskyy1ecfcec2019-12-17 12:10:41 -08001201 if (params.sessionParams.dataLoaderParams == null) {
Alex Buynytskyy476138c2019-12-20 14:41:47 -08001202 params.sessionParams.setDataLoaderParams(
Alex Buynytskyycd4d3872020-02-08 17:50:50 -08001203 PackageManagerShellCommandDataLoader.getStreamingDataLoaderParams(this));
Alex Buynytskyyda208152019-11-11 09:34:05 -08001204 }
1205 return doRunInstall(params);
1206 }
1207
Alex Buynytskyy04f73912020-02-10 08:34:18 -08001208 private int runIncrementalInstall() throws RemoteException {
1209 final InstallParams params = makeInstallParams();
1210 if (params.sessionParams.dataLoaderParams == null) {
1211 params.sessionParams.setDataLoaderParams(
1212 PackageManagerShellCommandDataLoader.getIncrementalDataLoaderParams(this));
1213 }
1214 return doRunInstall(params);
1215 }
1216
Alex Buynytskyyda208152019-11-11 09:34:05 -08001217 private int runInstall() throws RemoteException {
1218 return doRunInstall(makeInstallParams());
1219 }
1220
1221 private int doRunInstall(final InstallParams params) throws RemoteException {
1222 final PrintWriter pw = getOutPrintWriter();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001223
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001224 final boolean isStreaming = params.sessionParams.dataLoaderParams != null;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001225 final boolean isApex =
1226 (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0;
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001227
1228 ArrayList<String> args = getRemainingArgs();
1229
1230 final boolean fromStdIn = args.isEmpty() || STDIN_PATH.equals(args.get(0));
1231 final boolean hasSplits = args.size() > 1;
1232
1233 if (fromStdIn && params.sessionParams.sizeBytes == -1) {
1234 pw.println("Error: must either specify a package size or an APK file");
1235 return 1;
1236 }
1237
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001238 if (isApex && hasSplits) {
1239 pw.println("Error: can't specify SPLIT(s) for APEX");
1240 return 1;
1241 }
1242
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001243 if (!isStreaming) {
1244 if (fromStdIn && hasSplits) {
1245 pw.println("Error: can't specify SPLIT(s) along with STDIN");
1246 return 1;
1247 }
1248
1249 if (args.isEmpty()) {
1250 args.add(STDIN_PATH);
1251 } else {
1252 setParamsSize(params, args);
1253 }
Alex Buynytskyyda208152019-11-11 09:34:05 -08001254 }
1255
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001256 final int sessionId = doCreateSession(params.sessionParams,
1257 params.installerPackageName, params.userId);
1258 boolean abandonSession = true;
1259 try {
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001260 if (isStreaming) {
1261 if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex)
1262 != PackageInstaller.STATUS_SUCCESS) {
1263 return 1;
1264 }
1265 } else {
1266 if (doWriteSplits(sessionId, args, params.sessionParams.sizeBytes, isApex)
1267 != PackageInstaller.STATUS_SUCCESS) {
1268 return 1;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001269 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001270 }
1271 if (doCommitSession(sessionId, false /*logSuccess*/)
1272 != PackageInstaller.STATUS_SUCCESS) {
1273 return 1;
1274 }
1275 abandonSession = false;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01001276
Nikita Ioffe62d918c2020-01-18 01:20:42 +00001277 if (!params.sessionParams.isStaged || !params.mWaitForStagedSessionReady) {
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01001278 pw.println("Success");
1279 return 0;
1280 }
1281
1282 long timeoutMs = params.timeoutMs <= 0
1283 ? DEFAULT_WAIT_MS
1284 : params.timeoutMs;
1285 PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
1286 .getSessionInfo(sessionId);
1287 long currentTime = System.currentTimeMillis();
1288 long endTime = currentTime + timeoutMs;
1289 // Using a loop instead of BroadcastReceiver since we can receive session update
1290 // broadcast only if packageInstallerName is "android". We can't always force
1291 // "android" as packageIntallerName, e.g, rollback auto implies
1292 // "-i com.android.shell".
1293 while (currentTime < endTime) {
1294 if (si != null
1295 && (si.isStagedSessionReady() || si.isStagedSessionFailed())) {
1296 break;
1297 }
1298 SystemClock.sleep(Math.min(endTime - currentTime, 100));
1299 currentTime = System.currentTimeMillis();
1300 si = mInterface.getPackageInstaller().getSessionInfo(sessionId);
1301 }
1302 if (si == null) {
1303 pw.println("Failure [failed to retrieve SessionInfo]");
1304 return 1;
1305 }
1306 if (!si.isStagedSessionReady() && !si.isStagedSessionFailed()) {
1307 pw.println("Failure [timed out after " + timeoutMs + " ms]");
1308 return 1;
1309 }
1310 if (!si.isStagedSessionReady()) {
1311 pw.println("Error [" + si.getStagedSessionErrorCode() + "] ["
1312 + si.getStagedSessionErrorMessage() + "]");
1313 return 1;
1314 }
Nikita Ioffe62d918c2020-01-18 01:20:42 +00001315 pw.println("Success. Reboot device to apply staged session");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001316 return 0;
1317 } finally {
1318 if (abandonSession) {
1319 try {
1320 doAbandonSession(sessionId, false /*logSuccess*/);
1321 } catch (Exception ignore) {
1322 }
1323 }
1324 }
1325 }
1326
1327 private int runInstallAbandon() throws RemoteException {
1328 final int sessionId = Integer.parseInt(getNextArg());
1329 return doAbandonSession(sessionId, true /*logSuccess*/);
1330 }
1331
1332 private int runInstallCommit() throws RemoteException {
1333 final int sessionId = Integer.parseInt(getNextArg());
1334 return doCommitSession(sessionId, true /*logSuccess*/);
1335 }
1336
1337 private int runInstallCreate() throws RemoteException {
1338 final PrintWriter pw = getOutPrintWriter();
1339 final InstallParams installParams = makeInstallParams();
1340 final int sessionId = doCreateSession(installParams.sessionParams,
1341 installParams.installerPackageName, installParams.userId);
1342
1343 // NOTE: adb depends on parsing this string
1344 pw.println("Success: created install session [" + sessionId + "]");
1345 return 0;
1346 }
1347
1348 private int runInstallWrite() throws RemoteException {
1349 long sizeBytes = -1;
1350
1351 String opt;
1352 while ((opt = getNextOption()) != null) {
1353 if (opt.equals("-S")) {
1354 sizeBytes = Long.parseLong(getNextArg());
1355 } else {
1356 throw new IllegalArgumentException("Unknown option: " + opt);
1357 }
1358 }
1359
1360 final int sessionId = Integer.parseInt(getNextArg());
1361 final String splitName = getNextArg();
1362 final String path = getNextArg();
1363 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
1364 }
1365
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001366 private int runInstallAddSession() throws RemoteException {
1367 final PrintWriter pw = getOutPrintWriter();
1368 final int parentSessionId = Integer.parseInt(getNextArg());
1369
1370 List<Integer> otherSessionIds = new ArrayList<>();
1371 String opt;
1372 while ((opt = getNextArg()) != null) {
1373 otherSessionIds.add(Integer.parseInt(opt));
1374 }
1375 if (otherSessionIds.size() == 0) {
1376 pw.println("Error: At least two sessions are required.");
1377 return 1;
1378 }
1379 return doInstallAddSession(parentSessionId, ArrayUtils.convertToIntArray(otherSessionIds),
1380 true /*logSuccess*/);
1381 }
1382
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001383 private int runInstallRemove() throws RemoteException {
1384 final PrintWriter pw = getOutPrintWriter();
1385
1386 final int sessionId = Integer.parseInt(getNextArg());
1387
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001388 ArrayList<String> splitNames = getRemainingArgs();
1389 if (splitNames.isEmpty()) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001390 pw.println("Error: split name not specified");
1391 return 1;
1392 }
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001393 return doRemoveSplits(sessionId, splitNames, true /*logSuccess*/);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001394 }
1395
1396 private int runInstallExisting() throws RemoteException {
1397 final PrintWriter pw = getOutPrintWriter();
Todd Kennedybef39e02019-09-20 15:14:18 -07001398 int userId = UserHandle.USER_CURRENT;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001399 int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001400 String opt;
Chandan Nathe8e463b2019-01-28 15:23:38 +00001401 boolean waitTillComplete = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001402 while ((opt = getNextOption()) != null) {
1403 switch (opt) {
1404 case "--user":
1405 userId = UserHandle.parseUserArg(getNextArgRequired());
1406 break;
1407 case "--ephemeral":
1408 case "--instant":
1409 installFlags |= PackageManager.INSTALL_INSTANT_APP;
1410 installFlags &= ~PackageManager.INSTALL_FULL_APP;
1411 break;
1412 case "--full":
1413 installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1414 installFlags |= PackageManager.INSTALL_FULL_APP;
1415 break;
Chandan Nathe8e463b2019-01-28 15:23:38 +00001416 case "--wait":
1417 waitTillComplete = true;
1418 break;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001419 case "--restrict-permissions":
1420 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1421 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001422 default:
1423 pw.println("Error: Unknown option: " + opt);
1424 return 1;
1425 }
1426 }
1427
1428 final String packageName = getNextArg();
1429 if (packageName == null) {
1430 pw.println("Error: package name not specified");
1431 return 1;
1432 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08001433 final int translatedUserId =
1434 translateUserId(userId, UserHandle.USER_NULL, "runInstallExisting");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001435
Chandan Nathe8e463b2019-01-28 15:23:38 +00001436 int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001437 try {
Chandan Nathe8e463b2019-01-28 15:23:38 +00001438 if (waitTillComplete) {
1439 final LocalIntentReceiver receiver = new LocalIntentReceiver();
1440 final IPackageInstaller installer = mInterface.getPackageInstaller();
Todd Kennedyc3c52172019-11-26 13:20:59 -08001441 pw.println("Installing package " + packageName + " for user: " + translatedUserId);
Chandan Nathe8e463b2019-01-28 15:23:38 +00001442 installer.installExistingPackage(packageName, installFlags, installReason,
Todd Kennedyc3c52172019-11-26 13:20:59 -08001443 receiver.getIntentSender(), translatedUserId, null);
Chandan Nathe8e463b2019-01-28 15:23:38 +00001444 final Intent result = receiver.getResult();
1445 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1446 PackageInstaller.STATUS_FAILURE);
1447 pw.println("Received intent for package install");
1448 return status == PackageInstaller.STATUS_SUCCESS ? 0 : 1;
1449 }
1450
Todd Kennedyc3c52172019-11-26 13:20:59 -08001451 final int res = mInterface.installExistingPackageAsUser(packageName, translatedUserId,
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001452 installFlags, installReason, null);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001453 if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
1454 throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1455 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08001456 pw.println("Package " + packageName + " installed for user: " + translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001457 return 0;
1458 } catch (RemoteException | NameNotFoundException e) {
1459 pw.println(e.toString());
1460 return 1;
1461 }
1462 }
1463
1464 private int runSetInstallLocation() throws RemoteException {
1465 int loc;
1466
1467 String arg = getNextArg();
1468 if (arg == null) {
1469 getErrPrintWriter().println("Error: no install location specified.");
1470 return 1;
1471 }
1472 try {
1473 loc = Integer.parseInt(arg);
1474 } catch (NumberFormatException e) {
1475 getErrPrintWriter().println("Error: install location has to be a number.");
1476 return 1;
1477 }
1478 if (!mInterface.setInstallLocation(loc)) {
1479 getErrPrintWriter().println("Error: install location has to be a number.");
1480 return 1;
1481 }
1482 return 0;
1483 }
1484
1485 private int runGetInstallLocation() throws RemoteException {
1486 int loc = mInterface.getInstallLocation();
1487 String locStr = "invalid";
1488 if (loc == PackageHelper.APP_INSTALL_AUTO) {
1489 locStr = "auto";
1490 } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
1491 locStr = "internal";
1492 } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
1493 locStr = "external";
1494 }
1495 getOutPrintWriter().println(loc + "[" + locStr + "]");
1496 return 0;
1497 }
1498
1499 public int runMovePackage() throws RemoteException {
1500 final String packageName = getNextArg();
1501 if (packageName == null) {
1502 getErrPrintWriter().println("Error: package name not specified");
1503 return 1;
1504 }
1505 String volumeUuid = getNextArg();
1506 if ("internal".equals(volumeUuid)) {
1507 volumeUuid = null;
1508 }
1509
1510 final int moveId = mInterface.movePackage(packageName, volumeUuid);
1511
1512 int status = mInterface.getMoveStatus(moveId);
1513 while (!PackageManager.isMoveStatusFinished(status)) {
1514 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1515 status = mInterface.getMoveStatus(moveId);
1516 }
1517
1518 if (status == PackageManager.MOVE_SUCCEEDED) {
1519 getOutPrintWriter().println("Success");
1520 return 0;
1521 } else {
1522 getErrPrintWriter().println("Failure [" + status + "]");
1523 return 1;
1524 }
1525 }
1526
1527 public int runMovePrimaryStorage() throws RemoteException {
1528 String volumeUuid = getNextArg();
1529 if ("internal".equals(volumeUuid)) {
1530 volumeUuid = null;
1531 }
1532
1533 final int moveId = mInterface.movePrimaryStorage(volumeUuid);
1534
1535 int status = mInterface.getMoveStatus(moveId);
1536 while (!PackageManager.isMoveStatusFinished(status)) {
1537 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1538 status = mInterface.getMoveStatus(moveId);
1539 }
1540
1541 if (status == PackageManager.MOVE_SUCCEEDED) {
1542 getOutPrintWriter().println("Success");
1543 return 0;
1544 } else {
1545 getErrPrintWriter().println("Failure [" + status + "]");
1546 return 1;
1547 }
1548 }
1549
1550 private int runCompile() throws RemoteException {
1551 final PrintWriter pw = getOutPrintWriter();
1552 boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
1553 boolean forceCompilation = false;
1554 boolean allPackages = false;
1555 boolean clearProfileData = false;
1556 String compilerFilter = null;
1557 String compilationReason = null;
1558 String checkProfilesRaw = null;
1559 boolean secondaryDex = false;
1560 String split = null;
Eric Holka1485f62019-01-07 13:58:25 -08001561 boolean compileLayouts = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001562
1563 String opt;
1564 while ((opt = getNextOption()) != null) {
1565 switch (opt) {
1566 case "-a":
1567 allPackages = true;
1568 break;
1569 case "-c":
1570 clearProfileData = true;
1571 break;
1572 case "-f":
1573 forceCompilation = true;
1574 break;
1575 case "-m":
1576 compilerFilter = getNextArgRequired();
1577 break;
1578 case "-r":
1579 compilationReason = getNextArgRequired();
1580 break;
Eric Holka1485f62019-01-07 13:58:25 -08001581 case "--compile-layouts":
1582 compileLayouts = true;
1583 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001584 case "--check-prof":
1585 checkProfilesRaw = getNextArgRequired();
1586 break;
1587 case "--reset":
1588 forceCompilation = true;
1589 clearProfileData = true;
1590 compilationReason = "install";
1591 break;
1592 case "--secondary-dex":
1593 secondaryDex = true;
1594 break;
1595 case "--split":
1596 split = getNextArgRequired();
1597 break;
1598 default:
1599 pw.println("Error: Unknown option: " + opt);
1600 return 1;
1601 }
1602 }
1603
1604 if (checkProfilesRaw != null) {
1605 if ("true".equals(checkProfilesRaw)) {
1606 checkProfiles = true;
1607 } else if ("false".equals(checkProfilesRaw)) {
1608 checkProfiles = false;
1609 } else {
1610 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
1611 return 1;
1612 }
1613 }
1614
Eric Holka1485f62019-01-07 13:58:25 -08001615 final boolean compilerFilterGiven = compilerFilter != null;
1616 final boolean compilationReasonGiven = compilationReason != null;
1617 // Make sure exactly one of -m, -r, or --compile-layouts is given.
1618 if ((!compilerFilterGiven && !compilationReasonGiven && !compileLayouts)
1619 || (!compilerFilterGiven && compilationReasonGiven && compileLayouts)
1620 || (compilerFilterGiven && !compilationReasonGiven && compileLayouts)
1621 || (compilerFilterGiven && compilationReasonGiven && !compileLayouts)
1622 || (compilerFilterGiven && compilationReasonGiven && compileLayouts)) {
1623 pw.println("Must specify exactly one of compilation filter (\"-m\"), compilation " +
1624 "reason (\"-r\"), or compile layouts (\"--compile-layouts\")");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001625 return 1;
1626 }
1627
1628 if (allPackages && split != null) {
1629 pw.println("-a cannot be specified together with --split");
1630 return 1;
1631 }
1632
1633 if (secondaryDex && split != null) {
1634 pw.println("--secondary-dex cannot be specified together with --split");
1635 return 1;
1636 }
1637
Eric Holka1485f62019-01-07 13:58:25 -08001638 String targetCompilerFilter = null;
1639 if (compilerFilterGiven) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001640 if (!DexFile.isValidCompilerFilter(compilerFilter)) {
1641 pw.println("Error: \"" + compilerFilter +
1642 "\" is not a valid compilation filter.");
1643 return 1;
1644 }
1645 targetCompilerFilter = compilerFilter;
Eric Holka1485f62019-01-07 13:58:25 -08001646 }
1647 if (compilationReasonGiven) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001648 int reason = -1;
1649 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
1650 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
1651 compilationReason)) {
1652 reason = i;
1653 break;
1654 }
1655 }
1656 if (reason == -1) {
1657 pw.println("Error: Unknown compilation reason: " + compilationReason);
1658 return 1;
1659 }
1660 targetCompilerFilter =
1661 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
1662 }
1663
1664
1665 List<String> packageNames = null;
1666 if (allPackages) {
1667 packageNames = mInterface.getAllPackages();
1668 } else {
1669 String packageName = getNextArg();
1670 if (packageName == null) {
1671 pw.println("Error: package name not specified");
1672 return 1;
1673 }
1674 packageNames = Collections.singletonList(packageName);
1675 }
1676
1677 List<String> failedPackages = new ArrayList<>();
Andreas Gampecbd08d42017-11-20 17:03:17 -08001678 int index = 0;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001679 for (String packageName : packageNames) {
1680 if (clearProfileData) {
1681 mInterface.clearApplicationProfileData(packageName);
1682 }
1683
Andreas Gampecbd08d42017-11-20 17:03:17 -08001684 if (allPackages) {
1685 pw.println(++index + "/" + packageNames.size() + ": " + packageName);
1686 pw.flush();
1687 }
1688
Eric Holka1485f62019-01-07 13:58:25 -08001689 boolean result = true;
1690 if (compileLayouts) {
1691 PackageManagerInternal internal = LocalServices.getService(
1692 PackageManagerInternal.class);
1693 result = internal.compileLayouts(packageName);
1694 } else {
1695 result = secondaryDex
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001696 ? mInterface.performDexOptSecondary(packageName,
1697 targetCompilerFilter, forceCompilation)
1698 : mInterface.performDexOptMode(packageName,
1699 checkProfiles, targetCompilerFilter, forceCompilation,
1700 true /* bootComplete */, split);
Eric Holka1485f62019-01-07 13:58:25 -08001701 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001702 if (!result) {
1703 failedPackages.add(packageName);
1704 }
1705 }
1706
1707 if (failedPackages.isEmpty()) {
1708 pw.println("Success");
1709 return 0;
1710 } else if (failedPackages.size() == 1) {
1711 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
1712 return 1;
1713 } else {
1714 pw.print("Failure: the following packages could not be compiled: ");
1715 boolean is_first = true;
1716 for (String packageName : failedPackages) {
1717 if (is_first) {
1718 is_first = false;
1719 } else {
1720 pw.print(", ");
1721 }
1722 pw.print(packageName);
1723 }
1724 pw.println();
1725 return 1;
1726 }
1727 }
1728
1729 private int runreconcileSecondaryDexFiles() throws RemoteException {
1730 String packageName = getNextArg();
1731 mInterface.reconcileSecondaryDexFiles(packageName);
1732 return 0;
1733 }
1734
1735 public int runForceDexOpt() throws RemoteException {
1736 mInterface.forceDexOpt(getNextArgRequired());
1737 return 0;
1738 }
1739
1740 private int runDexoptJob() throws RemoteException {
Arthur Eubanks09dd1ec2017-09-15 09:28:51 -07001741 String arg;
1742 List<String> packageNames = new ArrayList<>();
1743 while ((arg = getNextArg()) != null) {
1744 packageNames.add(arg);
1745 }
1746 boolean result = mInterface.runBackgroundDexoptJob(packageNames.isEmpty() ? null :
1747 packageNames);
Andreas Gampefa8b57d2018-08-31 15:47:01 -07001748 getOutPrintWriter().println(result ? "Success" : "Failure");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001749 return result ? 0 : -1;
1750 }
1751
1752 private int runDumpProfiles() throws RemoteException {
1753 String packageName = getNextArg();
1754 mInterface.dumpProfiles(packageName);
1755 return 0;
1756 }
1757
Calin Juravle21216c62018-05-04 17:35:29 -07001758 private int runSnapshotProfile() throws RemoteException {
1759 PrintWriter pw = getOutPrintWriter();
1760
1761 // Parse the arguments
1762 final String packageName = getNextArg();
1763 final boolean isBootImage = "android".equals(packageName);
1764
1765 String codePath = null;
1766 String opt;
1767 while ((opt = getNextArg()) != null) {
1768 switch (opt) {
1769 case "--code-path":
1770 if (isBootImage) {
1771 pw.write("--code-path cannot be used for the boot image.");
1772 return -1;
1773 }
1774 codePath = getNextArg();
1775 break;
1776 default:
1777 pw.write("Unknown arg: " + opt);
1778 return -1;
1779 }
1780 }
1781
1782 // If no code path was explicitly requested, select the base code path.
1783 String baseCodePath = null;
1784 if (!isBootImage) {
1785 PackageInfo packageInfo = mInterface.getPackageInfo(packageName, /* flags */ 0,
1786 /* userId */0);
1787 if (packageInfo == null) {
1788 pw.write("Package not found " + packageName);
1789 return -1;
1790 }
1791 baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
1792 if (codePath == null) {
1793 codePath = baseCodePath;
1794 }
1795 }
1796
1797 // Create the profile snapshot.
1798 final SnapshotRuntimeProfileCallback callback = new SnapshotRuntimeProfileCallback();
1799 // The calling package is needed to debug permission access.
1800 final String callingPackage = (Binder.getCallingUid() == Process.ROOT_UID)
1801 ? "root" : "com.android.shell";
1802 final int profileType = isBootImage
1803 ? ArtManager.PROFILE_BOOT_IMAGE : ArtManager.PROFILE_APPS;
1804 if (!mInterface.getArtManager().isRuntimeProfilingEnabled(profileType, callingPackage)) {
1805 pw.println("Error: Runtime profiling is not enabled");
1806 return -1;
1807 }
1808 mInterface.getArtManager().snapshotRuntimeProfile(profileType, packageName,
1809 codePath, callback, callingPackage);
1810 if (!callback.waitTillDone()) {
1811 pw.println("Error: callback not called");
1812 return callback.mErrCode;
1813 }
1814
1815 // Copy the snapshot profile to the output profile file.
1816 try (InputStream inStream = new AutoCloseInputStream(callback.mProfileReadFd)) {
1817 final String outputFileSuffix = isBootImage || Objects.equals(baseCodePath, codePath)
1818 ? "" : ("-" + new File(codePath).getName());
1819 final String outputProfilePath =
1820 ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + packageName + outputFileSuffix + ".prof";
1821 try (OutputStream outStream = new FileOutputStream(outputProfilePath)) {
1822 Streams.copy(inStream, outStream);
1823 }
Calin Juravlebdd94d92018-05-17 01:23:15 -07001824 // Give read permissions to the other group.
1825 Os.chmod(outputProfilePath, /*mode*/ 0644 );
1826 } catch (IOException | ErrnoException e) {
Calin Juravle21216c62018-05-04 17:35:29 -07001827 pw.println("Error when reading the profile fd: " + e.getMessage());
1828 e.printStackTrace(pw);
1829 return -1;
1830 }
1831 return 0;
1832 }
1833
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001834 private ArrayList<String> getRemainingArgs() {
1835 ArrayList<String> args = new ArrayList<>();
1836 String arg;
1837 while ((arg = getNextArg()) != null) {
1838 args.add(arg);
1839 }
1840 return args;
1841 }
1842
Calin Juravle21216c62018-05-04 17:35:29 -07001843 private static class SnapshotRuntimeProfileCallback
1844 extends ISnapshotRuntimeProfileCallback.Stub {
1845 private boolean mSuccess = false;
1846 private int mErrCode = -1;
1847 private ParcelFileDescriptor mProfileReadFd = null;
1848 private CountDownLatch mDoneSignal = new CountDownLatch(1);
1849
1850 @Override
1851 public void onSuccess(ParcelFileDescriptor profileReadFd) {
1852 mSuccess = true;
1853 try {
1854 // We need to dup the descriptor. We are in the same process as system server
1855 // and we will be receiving the same object (which will be closed on the
1856 // server side).
1857 mProfileReadFd = profileReadFd.dup();
1858 } catch (IOException e) {
1859 e.printStackTrace();
1860 }
1861 mDoneSignal.countDown();
1862 }
1863
1864 @Override
1865 public void onError(int errCode) {
1866 mSuccess = false;
1867 mErrCode = errCode;
1868 mDoneSignal.countDown();
1869 }
1870
1871 boolean waitTillDone() {
1872 boolean done = false;
1873 try {
1874 // The time-out is an arbitrary large value. Since this is a local call the result
1875 // will come very fast.
1876 done = mDoneSignal.await(10000000, TimeUnit.MILLISECONDS);
1877 } catch (InterruptedException ignored) {
1878 }
1879 return done && mSuccess;
1880 }
1881 }
1882
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001883 private int runUninstall() throws RemoteException {
1884 final PrintWriter pw = getOutPrintWriter();
1885 int flags = 0;
1886 int userId = UserHandle.USER_ALL;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001887 long versionCode = PackageManager.VERSION_CODE_HIGHEST;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001888
1889 String opt;
1890 while ((opt = getNextOption()) != null) {
1891 switch (opt) {
1892 case "-k":
1893 flags |= PackageManager.DELETE_KEEP_DATA;
1894 break;
1895 case "--user":
1896 userId = UserHandle.parseUserArg(getNextArgRequired());
1897 break;
1898 case "--versionCode":
Dianne Hackborn3accca02013-09-20 09:32:11 -07001899 versionCode = Long.parseLong(getNextArgRequired());
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001900 break;
1901 default:
1902 pw.println("Error: Unknown option: " + opt);
1903 return 1;
1904 }
1905 }
1906
1907 final String packageName = getNextArg();
1908 if (packageName == null) {
1909 pw.println("Error: package name not specified");
1910 return 1;
1911 }
1912
1913 // if a split is specified, just remove it and not the whole package
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001914 ArrayList<String> splitNames = getRemainingArgs();
1915 if (!splitNames.isEmpty()) {
1916 return runRemoveSplits(packageName, splitNames);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001917 }
1918
Todd Kennedyc3c52172019-11-26 13:20:59 -08001919 if (userId == UserHandle.USER_ALL) {
1920 flags |= PackageManager.DELETE_ALL_USERS;
1921 }
1922 final int translatedUserId =
1923 translateUserId(userId, UserHandle.USER_SYSTEM, "runUninstall");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001924 final LocalIntentReceiver receiver = new LocalIntentReceiver();
Todd Kennedyc3c52172019-11-26 13:20:59 -08001925 final PackageManagerInternal internal =
1926 LocalServices.getService(PackageManagerInternal.class);
Nikita Ioffef012a222019-03-05 22:37:55 +00001927
1928 if (internal.isApexPackage(packageName)) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08001929 internal.uninstallApex(
Gavin Corkery4fd10882019-11-28 15:37:51 +00001930 packageName, versionCode, translatedUserId, receiver.getIntentSender(), flags);
Todd Kennedy2678a992019-11-27 10:21:23 -08001931 } else {
1932 if ((flags & PackageManager.DELETE_ALL_USERS) == 0) {
1933 final PackageInfo info = mInterface.getPackageInfo(packageName,
1934 PackageManager.MATCH_STATIC_SHARED_LIBRARIES, translatedUserId);
1935 if (info == null) {
1936 pw.println("Failure [not installed for " + translatedUserId + "]");
1937 return 1;
1938 }
1939 final boolean isSystem =
1940 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
1941 // If we are being asked to delete a system app for just one
1942 // user set flag so it disables rather than reverting to system
1943 // version of the app.
1944 if (isSystem) {
1945 flags |= PackageManager.DELETE_SYSTEM_APP;
1946 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08001947 }
Nikita Ioffef012a222019-03-05 22:37:55 +00001948 mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
1949 versionCode), null /*callerPackageName*/, flags,
Todd Kennedyc3c52172019-11-26 13:20:59 -08001950 receiver.getIntentSender(), translatedUserId);
Nikita Ioffef012a222019-03-05 22:37:55 +00001951 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001952
1953 final Intent result = receiver.getResult();
1954 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1955 PackageInstaller.STATUS_FAILURE);
1956 if (status == PackageInstaller.STATUS_SUCCESS) {
1957 pw.println("Success");
1958 return 0;
1959 } else {
1960 pw.println("Failure ["
1961 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
1962 return 1;
1963 }
1964 }
1965
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001966 private int runRemoveSplits(String packageName, Collection<String> splitNames)
1967 throws RemoteException {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001968 final PrintWriter pw = getOutPrintWriter();
1969 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
1970 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1971 sessionParams.appPackageName = packageName;
1972 final int sessionId =
1973 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
1974 boolean abandonSession = true;
1975 try {
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001976 if (doRemoveSplits(sessionId, splitNames, false /*logSuccess*/)
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001977 != PackageInstaller.STATUS_SUCCESS) {
1978 return 1;
1979 }
1980 if (doCommitSession(sessionId, false /*logSuccess*/)
1981 != PackageInstaller.STATUS_SUCCESS) {
1982 return 1;
1983 }
1984 abandonSession = false;
1985 pw.println("Success");
1986 return 0;
1987 } finally {
1988 if (abandonSession) {
1989 try {
1990 doAbandonSession(sessionId, false /*logSuccess*/);
1991 } catch (Exception ignore) {
1992 }
1993 }
1994 }
1995 }
1996
1997 static class ClearDataObserver extends IPackageDataObserver.Stub {
1998 boolean finished;
1999 boolean result;
2000
2001 @Override
2002 public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
2003 synchronized (this) {
2004 finished = true;
2005 result = succeeded;
2006 notifyAll();
2007 }
2008 }
2009 }
2010
2011 private int runClear() throws RemoteException {
2012 int userId = UserHandle.USER_SYSTEM;
2013 String option = getNextOption();
2014 if (option != null && option.equals("--user")) {
2015 userId = UserHandle.parseUserArg(getNextArgRequired());
2016 }
2017
2018 String pkg = getNextArg();
2019 if (pkg == null) {
2020 getErrPrintWriter().println("Error: no package specified");
2021 return 1;
2022 }
2023
Todd Kennedy5385b512019-11-26 15:49:06 -08002024 final int translatedUserId =
2025 translateUserId(userId, UserHandle.USER_NULL, "runClear");
2026 final ClearDataObserver obs = new ClearDataObserver();
2027 ActivityManager.getService().clearApplicationUserData(pkg, false, obs, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002028 synchronized (obs) {
2029 while (!obs.finished) {
2030 try {
2031 obs.wait();
2032 } catch (InterruptedException e) {
2033 }
2034 }
2035 }
2036
2037 if (obs.result) {
2038 getOutPrintWriter().println("Success");
2039 return 0;
2040 } else {
2041 getErrPrintWriter().println("Failed");
2042 return 1;
2043 }
2044 }
2045
2046 private static String enabledSettingToString(int state) {
2047 switch (state) {
2048 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
2049 return "default";
2050 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
2051 return "enabled";
2052 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
2053 return "disabled";
2054 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
2055 return "disabled-user";
2056 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
2057 return "disabled-until-used";
2058 }
2059 return "unknown";
2060 }
2061
2062 private int runSetEnabledSetting(int state) throws RemoteException {
2063 int userId = UserHandle.USER_SYSTEM;
2064 String option = getNextOption();
2065 if (option != null && option.equals("--user")) {
2066 userId = UserHandle.parseUserArg(getNextArgRequired());
2067 }
2068
Todd Kennedyc3c52172019-11-26 13:20:59 -08002069 final String pkg = getNextArg();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002070 if (pkg == null) {
2071 getErrPrintWriter().println("Error: no package or component specified");
2072 return 1;
2073 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002074 final int translatedUserId =
2075 translateUserId(userId, UserHandle.USER_NULL, "runSetEnabledSetting");
2076 final ComponentName cn = ComponentName.unflattenFromString(pkg);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002077 if (cn == null) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002078 mInterface.setApplicationEnabledSetting(pkg, state, 0, translatedUserId,
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002079 "shell:" + android.os.Process.myUid());
2080 getOutPrintWriter().println("Package " + pkg + " new state: "
2081 + enabledSettingToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002082 mInterface.getApplicationEnabledSetting(pkg, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002083 return 0;
2084 } else {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002085 mInterface.setComponentEnabledSetting(cn, state, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002086 getOutPrintWriter().println("Component " + cn.toShortString() + " new state: "
2087 + enabledSettingToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002088 mInterface.getComponentEnabledSetting(cn, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002089 return 0;
2090 }
2091 }
2092
2093 private int runSetHiddenSetting(boolean state) throws RemoteException {
2094 int userId = UserHandle.USER_SYSTEM;
2095 String option = getNextOption();
2096 if (option != null && option.equals("--user")) {
2097 userId = UserHandle.parseUserArg(getNextArgRequired());
2098 }
2099
2100 String pkg = getNextArg();
2101 if (pkg == null) {
2102 getErrPrintWriter().println("Error: no package or component specified");
2103 return 1;
2104 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002105 final int translatedUserId =
2106 translateUserId(userId, UserHandle.USER_NULL, "runSetHiddenSetting");
2107 mInterface.setApplicationHiddenSettingAsUser(pkg, state, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002108 getOutPrintWriter().println("Package " + pkg + " new hidden state: "
Todd Kennedyc3c52172019-11-26 13:20:59 -08002109 + mInterface.getApplicationHiddenSettingAsUser(pkg, translatedUserId));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002110 return 0;
2111 }
2112
2113 private int runSuspend(boolean suspendedState) {
2114 final PrintWriter pw = getOutPrintWriter();
2115 int userId = UserHandle.USER_SYSTEM;
Suprabh Shukla3c3af142018-03-30 00:28:37 -07002116 String dialogMessage = null;
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002117 final PersistableBundle appExtras = new PersistableBundle();
2118 final PersistableBundle launcherExtras = new PersistableBundle();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002119 String opt;
2120 while ((opt = getNextOption()) != null) {
2121 switch (opt) {
2122 case "--user":
2123 userId = UserHandle.parseUserArg(getNextArgRequired());
2124 break;
Suprabh Shukla3c3af142018-03-30 00:28:37 -07002125 case "--dialogMessage":
2126 dialogMessage = getNextArgRequired();
2127 break;
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002128 case "--ael":
2129 case "--aes":
2130 case "--aed":
2131 case "--lel":
2132 case "--les":
2133 case "--led":
2134 final String key = getNextArgRequired();
2135 final String val = getNextArgRequired();
2136 if (!suspendedState) {
2137 break;
2138 }
2139 final PersistableBundle bundleToInsert =
2140 opt.startsWith("--a") ? appExtras : launcherExtras;
2141 switch (opt.charAt(4)) {
2142 case 'l':
2143 bundleToInsert.putLong(key, Long.valueOf(val));
2144 break;
2145 case 'd':
2146 bundleToInsert.putDouble(key, Double.valueOf(val));
2147 break;
2148 case 's':
2149 bundleToInsert.putString(key, val);
2150 break;
2151 }
2152 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002153 default:
2154 pw.println("Error: Unknown option: " + opt);
2155 return 1;
2156 }
2157 }
2158
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002159 final String packageName = getNextArg();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002160 if (packageName == null) {
2161 pw.println("Error: package name not specified");
2162 return 1;
2163 }
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002164 final String callingPackage =
2165 (Binder.getCallingUid() == Process.ROOT_UID) ? "root" : "com.android.shell";
Suprabh Shukla389cb6f2018-10-01 18:20:39 -07002166
2167 final SuspendDialogInfo info;
2168 if (!TextUtils.isEmpty(dialogMessage)) {
2169 info = new SuspendDialogInfo.Builder()
2170 .setMessage(dialogMessage)
2171 .build();
2172 } else {
2173 info = null;
2174 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002175 try {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002176 final int translatedUserId =
2177 translateUserId(userId, UserHandle.USER_NULL, "runSuspend");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002178 mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
Suprabh Shuklad3278442019-08-27 15:58:03 -07002179 ((appExtras.size() > 0) ? appExtras : null),
2180 ((launcherExtras.size() > 0) ? launcherExtras : null),
Todd Kennedyc3c52172019-11-26 13:20:59 -08002181 info, callingPackage, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002182 pw.println("Package " + packageName + " new suspended state: "
Todd Kennedyc3c52172019-11-26 13:20:59 -08002183 + mInterface.isPackageSuspendedForUser(packageName, translatedUserId));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002184 return 0;
2185 } catch (RemoteException | IllegalArgumentException e) {
2186 pw.println(e.toString());
2187 return 1;
2188 }
2189 }
2190
2191 private int runGrantRevokePermission(boolean grant) throws RemoteException {
2192 int userId = UserHandle.USER_SYSTEM;
2193
2194 String opt = null;
2195 while ((opt = getNextOption()) != null) {
2196 if (opt.equals("--user")) {
2197 userId = UserHandle.parseUserArg(getNextArgRequired());
2198 }
2199 }
2200
2201 String pkg = getNextArg();
2202 if (pkg == null) {
2203 getErrPrintWriter().println("Error: no package specified");
2204 return 1;
2205 }
2206 String perm = getNextArg();
2207 if (perm == null) {
2208 getErrPrintWriter().println("Error: no permission specified");
2209 return 1;
2210 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002211 final int translatedUserId =
2212 translateUserId(userId, UserHandle.USER_NULL, "runGrantRevokePermission");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002213 if (grant) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002214 mPermissionManager.grantRuntimePermission(pkg, perm, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002215 } else {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002216 mPermissionManager.revokeRuntimePermission(pkg, perm, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002217 }
2218 return 0;
2219 }
2220
2221 private int runResetPermissions() throws RemoteException {
Todd Kennedyc971a452019-07-08 16:04:52 -07002222 mPermissionManager.resetRuntimePermissions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002223 return 0;
2224 }
2225
2226 private int runSetPermissionEnforced() throws RemoteException {
2227 final String permission = getNextArg();
2228 if (permission == null) {
2229 getErrPrintWriter().println("Error: no permission specified");
2230 return 1;
2231 }
2232 final String enforcedRaw = getNextArg();
2233 if (enforcedRaw == null) {
2234 getErrPrintWriter().println("Error: no enforcement specified");
2235 return 1;
2236 }
Todd Kennedyc5b0e862019-07-16 09:47:58 -07002237 mPermissionManager.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002238 return 0;
2239 }
2240
Jiyong Park002fdbd2017-02-13 20:50:31 +09002241 private boolean isVendorApp(String pkg) {
2242 try {
2243 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
2244 return info != null && info.applicationInfo.isVendor();
2245 } catch (RemoteException e) {
2246 return false;
2247 }
2248 }
2249
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002250 private boolean isProductApp(String pkg) {
2251 try {
2252 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
2253 return info != null && info.applicationInfo.isProduct();
2254 } catch (RemoteException e) {
2255 return false;
2256 }
2257 }
2258
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002259 private boolean isSystemExtApp(String pkg) {
Dario Freni2bef1762018-06-01 14:02:08 +01002260 try {
2261 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002262 return info != null && info.applicationInfo.isSystemExt();
Dario Freni2bef1762018-06-01 14:02:08 +01002263 } catch (RemoteException e) {
2264 return false;
2265 }
2266 }
2267
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002268 private int runGetPrivappPermissions() {
2269 final String pkg = getNextArg();
2270 if (pkg == null) {
2271 getErrPrintWriter().println("Error: no package specified.");
2272 return 1;
2273 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002274
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002275 ArraySet<String> privAppPermissions = null;
2276 if (isVendorApp(pkg)) {
2277 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
2278 } else if (isProductApp(pkg)) {
2279 privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002280 } else if (isSystemExtApp(pkg)) {
Dario Freni2bef1762018-06-01 14:02:08 +01002281 privAppPermissions = SystemConfig.getInstance()
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002282 .getSystemExtPrivAppPermissions(pkg);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002283 } else {
2284 privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
2285 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002286
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002287 getOutPrintWriter().println(privAppPermissions == null
2288 ? "{}" : privAppPermissions.toString());
2289 return 0;
2290 }
2291
2292 private int runGetPrivappDenyPermissions() {
2293 final String pkg = getNextArg();
2294 if (pkg == null) {
2295 getErrPrintWriter().println("Error: no package specified.");
2296 return 1;
2297 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002298
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002299 ArraySet<String> privAppPermissions = null;
2300 if (isVendorApp(pkg)) {
2301 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
2302 } else if (isProductApp(pkg)) {
2303 privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002304 } else if (isSystemExtApp(pkg)) {
Dario Freni2bef1762018-06-01 14:02:08 +01002305 privAppPermissions = SystemConfig.getInstance()
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002306 .getSystemExtPrivAppDenyPermissions(pkg);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002307 } else {
2308 privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
2309 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002310
2311 getOutPrintWriter().println(privAppPermissions == null
2312 ? "{}" : privAppPermissions.toString());
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002313 return 0;
2314 }
2315
2316 private int runGetOemPermissions() {
2317 final String pkg = getNextArg();
2318 if (pkg == null) {
2319 getErrPrintWriter().println("Error: no package specified.");
2320 return 1;
2321 }
2322 final Map<String, Boolean> oemPermissions = SystemConfig.getInstance()
2323 .getOemPermissions(pkg);
2324 if (oemPermissions == null || oemPermissions.isEmpty()) {
2325 getOutPrintWriter().println("{}");
2326 } else {
2327 oemPermissions.forEach((permission, granted) ->
2328 getOutPrintWriter().println(permission + " granted:" + granted)
2329 );
2330 }
2331 return 0;
2332 }
2333
2334 private String linkStateToString(int state) {
2335 switch (state) {
2336 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
2337 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
2338 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
2339 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
2340 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
2341 }
2342 return "Unknown link state: " + state;
2343 }
2344
2345 // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
2346 private int runSetAppLink() throws RemoteException {
2347 int userId = UserHandle.USER_SYSTEM;
2348
2349 String opt;
2350 while ((opt = getNextOption()) != null) {
2351 if (opt.equals("--user")) {
2352 userId = UserHandle.parseUserArg(getNextArgRequired());
2353 } else {
2354 getErrPrintWriter().println("Error: unknown option: " + opt);
2355 return 1;
2356 }
2357 }
2358
2359 // Package name to act on; required
2360 final String pkg = getNextArg();
2361 if (pkg == null) {
2362 getErrPrintWriter().println("Error: no package specified.");
2363 return 1;
2364 }
2365
2366 // State to apply; {always|ask|never|undefined}, required
2367 final String modeString = getNextArg();
2368 if (modeString == null) {
2369 getErrPrintWriter().println("Error: no app link state specified.");
2370 return 1;
2371 }
2372
2373 final int newMode;
2374 switch (modeString.toLowerCase()) {
2375 case "undefined":
2376 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
2377 break;
2378
2379 case "always":
2380 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
2381 break;
2382
2383 case "ask":
2384 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
2385 break;
2386
2387 case "always-ask":
2388 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
2389 break;
2390
2391 case "never":
2392 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
2393 break;
2394
2395 default:
2396 getErrPrintWriter().println("Error: unknown app link state '" + modeString + "'");
2397 return 1;
2398 }
2399
Todd Kennedyc3c52172019-11-26 13:20:59 -08002400 final int translatedUserId =
2401 translateUserId(userId, UserHandle.USER_NULL, "runSetAppLink");
2402 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002403 if (info == null) {
2404 getErrPrintWriter().println("Error: package " + pkg + " not found.");
2405 return 1;
2406 }
2407
2408 if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2409 getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2410 return 1;
2411 }
2412
Todd Kennedyc3c52172019-11-26 13:20:59 -08002413 if (!mInterface.updateIntentVerificationStatus(pkg, newMode, translatedUserId)) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002414 getErrPrintWriter().println("Error: unable to update app link status for " + pkg);
2415 return 1;
2416 }
2417
2418 return 0;
2419 }
2420
2421 // pm get-app-link [--user USER_ID] PACKAGE
2422 private int runGetAppLink() throws RemoteException {
2423 int userId = UserHandle.USER_SYSTEM;
2424
2425 String opt;
2426 while ((opt = getNextOption()) != null) {
2427 if (opt.equals("--user")) {
2428 userId = UserHandle.parseUserArg(getNextArgRequired());
2429 } else {
2430 getErrPrintWriter().println("Error: unknown option: " + opt);
2431 return 1;
2432 }
2433 }
2434
2435 // Package name to act on; required
2436 final String pkg = getNextArg();
2437 if (pkg == null) {
2438 getErrPrintWriter().println("Error: no package specified.");
2439 return 1;
2440 }
2441
Todd Kennedyc3c52172019-11-26 13:20:59 -08002442 final int translatedUserId =
2443 translateUserId(userId, UserHandle.USER_NULL, "runGetAppLink");
2444 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002445 if (info == null) {
2446 getErrPrintWriter().println("Error: package " + pkg + " not found.");
2447 return 1;
2448 }
2449
2450 if ((info.applicationInfo.privateFlags
2451 & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2452 getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2453 return 1;
2454 }
2455
2456 getOutPrintWriter().println(linkStateToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002457 mInterface.getIntentVerificationStatus(pkg, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002458
2459 return 0;
2460 }
2461
2462 private int runTrimCaches() throws RemoteException {
2463 String size = getNextArg();
2464 if (size == null) {
2465 getErrPrintWriter().println("Error: no size specified");
2466 return 1;
2467 }
2468 long multiplier = 1;
2469 int len = size.length();
2470 char c = size.charAt(len - 1);
2471 if (c < '0' || c > '9') {
2472 if (c == 'K' || c == 'k') {
2473 multiplier = 1024L;
2474 } else if (c == 'M' || c == 'm') {
2475 multiplier = 1024L*1024L;
2476 } else if (c == 'G' || c == 'g') {
2477 multiplier = 1024L*1024L*1024L;
2478 } else {
2479 getErrPrintWriter().println("Invalid suffix: " + c);
2480 return 1;
2481 }
2482 size = size.substring(0, len-1);
2483 }
2484 long sizeVal;
2485 try {
2486 sizeVal = Long.parseLong(size) * multiplier;
2487 } catch (NumberFormatException e) {
2488 getErrPrintWriter().println("Error: expected number at: " + size);
2489 return 1;
2490 }
2491 String volumeUuid = getNextArg();
2492 if ("internal".equals(volumeUuid)) {
2493 volumeUuid = null;
2494 }
2495 ClearDataObserver obs = new ClearDataObserver();
2496 mInterface.freeStorageAndNotify(volumeUuid, sizeVal,
2497 StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs);
2498 synchronized (obs) {
2499 while (!obs.finished) {
2500 try {
2501 obs.wait();
2502 } catch (InterruptedException e) {
2503 }
2504 }
2505 }
2506 return 0;
2507 }
2508
2509 private static boolean isNumber(String s) {
2510 try {
2511 Integer.parseInt(s);
2512 } catch (NumberFormatException nfe) {
2513 return false;
2514 }
2515 return true;
2516 }
2517
2518 public int runCreateUser() throws RemoteException {
2519 String name;
2520 int userId = -1;
2521 int flags = 0;
Bookatz029832a2019-10-04 16:50:22 -07002522 String userType = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002523 String opt;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002524 boolean preCreateOnly = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002525 while ((opt = getNextOption()) != null) {
Bookatz029832a2019-10-04 16:50:22 -07002526 String newUserType = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002527 if ("--profileOf".equals(opt)) {
2528 userId = UserHandle.parseUserArg(getNextArgRequired());
2529 } else if ("--managed".equals(opt)) {
Bookatz029832a2019-10-04 16:50:22 -07002530 newUserType = UserManager.USER_TYPE_PROFILE_MANAGED;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002531 } else if ("--restricted".equals(opt)) {
Bookatz029832a2019-10-04 16:50:22 -07002532 newUserType = UserManager.USER_TYPE_FULL_RESTRICTED;
2533 } else if ("--guest".equals(opt)) {
2534 newUserType = UserManager.USER_TYPE_FULL_GUEST;
2535 } else if ("--demo".equals(opt)) {
2536 newUserType = UserManager.USER_TYPE_FULL_DEMO;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002537 } else if ("--ephemeral".equals(opt)) {
2538 flags |= UserInfo.FLAG_EPHEMERAL;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002539 } else if ("--pre-create-only".equals(opt)) {
2540 preCreateOnly = true;
Bookatz029832a2019-10-04 16:50:22 -07002541 } else if ("--user-type".equals(opt)) {
2542 newUserType = getNextArgRequired();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002543 } else {
2544 getErrPrintWriter().println("Error: unknown option " + opt);
2545 return 1;
2546 }
Bookatz029832a2019-10-04 16:50:22 -07002547 // Ensure only one user-type was specified.
2548 if (newUserType != null) {
2549 if (userType != null && !userType.equals(newUserType)) {
2550 getErrPrintWriter().println("Error: more than one user type was specified ("
2551 + userType + " and " + newUserType + ")");
2552 return 1;
2553 }
2554 userType = newUserType;
2555 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002556 }
2557 String arg = getNextArg();
Felipe Lemee35f5b02019-10-14 15:37:44 -07002558 if (arg == null && !preCreateOnly) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002559 getErrPrintWriter().println("Error: no user name specified.");
2560 return 1;
2561 }
Felipe Lemee35f5b02019-10-14 15:37:44 -07002562 if (arg != null && preCreateOnly) {
2563 getErrPrintWriter().println("Warning: name is ignored for pre-created users");
2564 }
2565
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002566 name = arg;
Valentin Iftime89df4c82019-08-23 13:02:50 +02002567 UserInfo info = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002568 IUserManager um = IUserManager.Stub.asInterface(
2569 ServiceManager.getService(Context.USER_SERVICE));
2570 IAccountManager accm = IAccountManager.Stub.asInterface(
2571 ServiceManager.getService(Context.ACCOUNT_SERVICE));
Bookatz029832a2019-10-04 16:50:22 -07002572 if (userType == null) {
2573 userType = UserInfo.getDefaultUserType(flags);
2574 }
Valentin Iftime89df4c82019-08-23 13:02:50 +02002575 try {
2576 if (UserManager.isUserTypeRestricted(userType)) {
2577 // In non-split user mode, userId can only be SYSTEM
2578 int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
2579 info = um.createRestrictedProfileWithThrow(name, parentUserId);
2580 accm.addSharedAccountsFromParentUser(parentUserId, userId,
2581 (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
2582 } else if (userId < 0) {
2583 info = preCreateOnly ?
2584 um.preCreateUserWithThrow(userType) :
2585 um.createUserWithThrow(name, userType, flags);
2586 } else {
2587 info = um.createProfileForUserWithThrow(name, userType, flags, userId, null);
2588 }
2589 } catch (ServiceSpecificException e) {
2590 getErrPrintWriter().println("Error: " + e);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002591 }
2592
2593 if (info != null) {
2594 getOutPrintWriter().println("Success: created user id " + info.id);
2595 return 0;
2596 } else {
2597 getErrPrintWriter().println("Error: couldn't create User.");
2598 return 1;
2599 }
2600 }
2601
2602 public int runRemoveUser() throws RemoteException {
2603 int userId;
2604 String arg = getNextArg();
2605 if (arg == null) {
2606 getErrPrintWriter().println("Error: no user id specified.");
2607 return 1;
2608 }
2609 userId = UserHandle.parseUserArg(arg);
2610 IUserManager um = IUserManager.Stub.asInterface(
2611 ServiceManager.getService(Context.USER_SERVICE));
2612 if (um.removeUser(userId)) {
2613 getOutPrintWriter().println("Success: removed user");
2614 return 0;
2615 } else {
2616 getErrPrintWriter().println("Error: couldn't remove user id " + userId);
2617 return 1;
2618 }
2619 }
2620
2621 public int runSetUserRestriction() throws RemoteException {
2622 int userId = UserHandle.USER_SYSTEM;
2623 String opt = getNextOption();
2624 if (opt != null && "--user".equals(opt)) {
2625 userId = UserHandle.parseUserArg(getNextArgRequired());
2626 }
2627
2628 String restriction = getNextArg();
2629 String arg = getNextArg();
2630 boolean value;
2631 if ("1".equals(arg)) {
2632 value = true;
2633 } else if ("0".equals(arg)) {
2634 value = false;
2635 } else {
2636 getErrPrintWriter().println("Error: valid value not specified");
2637 return 1;
2638 }
Todd Kennedy5385b512019-11-26 15:49:06 -08002639 final int translatedUserId =
2640 translateUserId(userId, UserHandle.USER_NULL, "runSetUserRestriction");
2641 final IUserManager um = IUserManager.Stub.asInterface(
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002642 ServiceManager.getService(Context.USER_SERVICE));
Todd Kennedy5385b512019-11-26 15:49:06 -08002643 um.setUserRestriction(restriction, value, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002644 return 0;
2645 }
2646
2647 public int runGetMaxUsers() {
2648 getOutPrintWriter().println("Maximum supported users: "
2649 + UserManager.getMaxSupportedUsers());
2650 return 0;
2651 }
2652
Alex Chauc12189b2018-01-16 15:01:15 +00002653 public int runGetMaxRunningUsers() {
2654 ActivityManagerInternal activityManagerInternal =
2655 LocalServices.getService(ActivityManagerInternal.class);
2656 getOutPrintWriter().println("Maximum supported running users: "
2657 + activityManagerInternal.getMaxRunningUsers());
2658 return 0;
2659 }
2660
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002661 private static class InstallParams {
2662 SessionParams sessionParams;
2663 String installerPackageName;
2664 int userId = UserHandle.USER_ALL;
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002665 boolean mWaitForStagedSessionReady = true;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002666 long timeoutMs = DEFAULT_WAIT_MS;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002667 }
2668
2669 private InstallParams makeInstallParams() {
2670 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2671 final InstallParams params = new InstallParams();
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07002672
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002673 params.sessionParams = sessionParams;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07002674 // Whitelist all permissions by default
2675 sessionParams.installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
2676
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002677 String opt;
Patrick Baumanna9333492017-11-28 15:23:49 -08002678 boolean replaceExisting = true;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002679 while ((opt = getNextOption()) != null) {
2680 switch (opt) {
Patrick Baumanna9333492017-11-28 15:23:49 -08002681 case "-r": // ignore
2682 break;
2683 case "-R":
2684 replaceExisting = false;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002685 break;
2686 case "-i":
2687 params.installerPackageName = getNextArg();
2688 if (params.installerPackageName == null) {
2689 throw new IllegalArgumentException("Missing installer package");
2690 }
2691 break;
2692 case "-t":
2693 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
2694 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002695 case "-f":
2696 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
2697 break;
2698 case "-d":
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00002699 sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002700 break;
2701 case "-g":
2702 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
Svet Ganov83a3a4a2019-05-03 18:50:43 -07002703 break;
2704 case "--restrict-permissions":
2705 sessionParams.installFlags &=
2706 ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002707 break;
Todd Kennedyb1072712016-04-26 15:41:20 -07002708 case "--dont-kill":
2709 sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
2710 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002711 case "--originating-uri":
2712 sessionParams.originatingUri = Uri.parse(getNextArg());
2713 break;
2714 case "--referrer":
2715 sessionParams.referrerUri = Uri.parse(getNextArg());
2716 break;
2717 case "-p":
2718 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
2719 sessionParams.appPackageName = getNextArg();
2720 if (sessionParams.appPackageName == null) {
2721 throw new IllegalArgumentException("Missing inherit package name");
2722 }
2723 break;
Dianne Hackbornca3872c2017-10-30 14:19:32 -07002724 case "--pkg":
2725 sessionParams.appPackageName = getNextArg();
2726 if (sessionParams.appPackageName == null) {
2727 throw new IllegalArgumentException("Missing package name");
2728 }
2729 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002730 case "-S":
Todd Kennedy9caf94e2016-10-12 15:26:08 -07002731 final long sizeBytes = Long.parseLong(getNextArg());
2732 if (sizeBytes <= 0) {
2733 throw new IllegalArgumentException("Size must be positive");
2734 }
2735 sessionParams.setSize(sizeBytes);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002736 break;
2737 case "--abi":
2738 sessionParams.abiOverride = checkAbiArgument(getNextArg());
2739 break;
Todd Kennedy2699f062015-11-20 13:07:17 -08002740 case "--ephemeral":
Dianne Hackbornca3872c2017-10-30 14:19:32 -07002741 case "--instant":
Todd Kennedybe0b8892017-02-15 14:13:52 -08002742 case "--instantapp":
Todd Kennedyb7717682016-11-30 15:41:21 -08002743 sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
Todd Kennedy2699f062015-11-20 13:07:17 -08002744 break;
Todd Kennedybe0b8892017-02-15 14:13:52 -08002745 case "--full":
2746 sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
2747 break;
Todd Kennedy78a72502017-07-19 12:49:30 -07002748 case "--preload":
2749 sessionParams.setInstallAsVirtualPreload();
2750 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002751 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08002752 params.userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002753 break;
2754 case "--install-location":
2755 sessionParams.installLocation = Integer.parseInt(getNextArg());
2756 break;
Sunny Goyalabd4d442018-09-19 15:49:50 -07002757 case "--install-reason":
2758 sessionParams.installReason = Integer.parseInt(getNextArg());
2759 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002760 case "--force-uuid":
2761 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
2762 sessionParams.volumeUuid = getNextArg();
2763 if ("internal".equals(sessionParams.volumeUuid)) {
2764 sessionParams.volumeUuid = null;
2765 }
2766 break;
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002767 case "--force-sdk": // ignore
Todd Kennedyb1072712016-04-26 15:41:20 -07002768 break;
Dario Frenid8bf22e2018-08-31 14:18:04 +01002769 case "--apex":
Dario Freni3fa46d82019-01-23 19:31:47 +00002770 sessionParams.setInstallAsApex();
Dario Freni505b8152019-01-08 12:30:43 +00002771 sessionParams.setStaged();
Dario Frenid8bf22e2018-08-31 14:18:04 +01002772 break;
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002773 case "--multi-package":
2774 sessionParams.setMultiPackage();
2775 break;
Dario Freniaac4ba42018-12-06 15:47:16 +00002776 case "--staged":
2777 sessionParams.setStaged();
2778 break;
Patrick Baumann5ff0f9e2019-11-27 11:40:07 -08002779 case "--force-queryable":
2780 sessionParams.setForceQueryable();
2781 break;
Richard Uhlerb29f1452018-09-12 16:38:15 +01002782 case "--enable-rollback":
Richard Uhler88184a62019-04-16 11:30:25 +01002783 if (params.installerPackageName == null) {
2784 // com.android.shell has the TEST_MANAGE_ROLLBACKS
2785 // permission needed to enable rollback for non-module
2786 // packages, which is likely what the user wants when
2787 // enabling rollback through the shell command. Set
2788 // the installer to com.android.shell if no installer
2789 // has been provided so that the user doesn't have to
2790 // remember to set it themselves.
2791 params.installerPackageName = "com.android.shell";
2792 }
Richard Uhlerb29f1452018-09-12 16:38:15 +01002793 sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
2794 break;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002795 case "--wait":
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002796 params.mWaitForStagedSessionReady = true;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002797 try {
2798 params.timeoutMs = Long.parseLong(peekNextArg());
2799 getNextArg();
2800 } catch (NumberFormatException ignore) {
2801 }
2802 break;
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002803 case "--no-wait":
2804 params.mWaitForStagedSessionReady = false;
2805 break;
Chester Hsieh750b5ed2020-01-08 09:32:17 -08002806 case "--skip-verification":
2807 sessionParams.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;
2808 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002809 default:
2810 throw new IllegalArgumentException("Unknown option " + opt);
2811 }
Patrick Baumanndcf19162019-05-29 09:18:58 -07002812 }
2813 if (replaceExisting) {
2814 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002815 }
2816 return params;
2817 }
2818
Makoto Onuki4828a592016-03-15 18:06:57 -07002819 private int runSetHomeActivity() {
2820 final PrintWriter pw = getOutPrintWriter();
2821 int userId = UserHandle.USER_SYSTEM;
2822 String opt;
2823 while ((opt = getNextOption()) != null) {
2824 switch (opt) {
2825 case "--user":
2826 userId = UserHandle.parseUserArg(getNextArgRequired());
2827 break;
2828 default:
2829 pw.println("Error: Unknown option: " + opt);
2830 return 1;
2831 }
2832 }
2833
Bookatz2b5a6012019-04-16 19:41:28 -07002834 String pkgName;
Makoto Onuki4828a592016-03-15 18:06:57 -07002835 String component = getNextArg();
Bookatz2b5a6012019-04-16 19:41:28 -07002836 if (component.indexOf('/') < 0) {
2837 // No component specified, so assume it's just a package name.
2838 pkgName = component;
2839 } else {
2840 ComponentName componentName =
2841 component != null ? ComponentName.unflattenFromString(component) : null;
2842 if (componentName == null) {
2843 pw.println("Error: invalid component name");
2844 return 1;
2845 }
2846 pkgName = componentName.getPackageName();
Makoto Onuki4828a592016-03-15 18:06:57 -07002847 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002848 final int translatedUserId =
2849 translateUserId(userId, UserHandle.USER_NULL, "runSetHomeActivity");
Bookatz2b5a6012019-04-16 19:41:28 -07002850 final CompletableFuture<Boolean> future = new CompletableFuture<>();
2851 final RemoteCallback callback = new RemoteCallback(res -> future.complete(res != null));
Makoto Onuki4828a592016-03-15 18:06:57 -07002852 try {
Bookatz2b5a6012019-04-16 19:41:28 -07002853 IRoleManager roleManager = android.app.role.IRoleManager.Stub.asInterface(
2854 ServiceManager.getServiceOrThrow(Context.ROLE_SERVICE));
2855 roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName,
Todd Kennedyc3c52172019-11-26 13:20:59 -08002856 0, translatedUserId, callback);
Bookatz2b5a6012019-04-16 19:41:28 -07002857 boolean success = future.get();
2858 if (success) {
2859 pw.println("Success");
2860 return 0;
2861 } else {
2862 pw.println("Error: Failed to set default home.");
2863 return 1;
2864 }
Makoto Onuki3bdbf982016-06-23 16:56:35 -07002865 } catch (Exception e) {
Makoto Onuki4828a592016-03-15 18:06:57 -07002866 pw.println(e.toString());
2867 return 1;
2868 }
2869 }
2870
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002871 private int runSetInstaller() throws RemoteException {
2872 final String targetPackage = getNextArg();
2873 final String installerPackageName = getNextArg();
Fyodor Kupolov51245c72016-12-01 11:34:10 -08002874
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002875 if (targetPackage == null || installerPackageName == null) {
2876 getErrPrintWriter().println("Must provide both target and installer package names");
Todd Kennedy74629e32017-08-15 14:48:07 -07002877 return 1;
2878 }
Todd Kennedy74629e32017-08-15 14:48:07 -07002879
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002880 mInterface.setInstallerPackageName(targetPackage, installerPackageName);
2881 getOutPrintWriter().println("Success");
Svet Ganov087dce22017-09-07 15:42:16 -07002882 return 0;
2883 }
2884
Todd Kennedy0a3f0812017-05-08 14:43:15 -07002885 private int runGetInstantAppResolver() {
2886 final PrintWriter pw = getOutPrintWriter();
2887 try {
2888 final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent();
2889 if (instantAppsResolver == null) {
2890 return 1;
2891 }
2892 pw.println(instantAppsResolver.flattenToString());
2893 return 0;
2894 } catch (Exception e) {
2895 pw.println(e.toString());
2896 return 1;
2897 }
2898 }
2899
Tadashi G. Takaokabe5782f2017-02-14 16:41:49 +09002900 private int runHasFeature() {
2901 final PrintWriter err = getErrPrintWriter();
2902 final String featureName = getNextArg();
2903 if (featureName == null) {
2904 err.println("Error: expected FEATURE name");
2905 return 1;
2906 }
2907 final String versionString = getNextArg();
2908 try {
2909 final int version = (versionString == null) ? 0 : Integer.parseInt(versionString);
2910 final boolean hasFeature = mInterface.hasSystemFeature(featureName, version);
2911 getOutPrintWriter().println(hasFeature);
2912 return hasFeature ? 0 : 1;
2913 } catch (NumberFormatException e) {
2914 err.println("Error: illegal version number " + versionString);
2915 return 1;
2916 } catch (RemoteException e) {
2917 err.println(e.toString());
2918 return 1;
2919 }
2920 }
2921
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002922 private int runDump() {
2923 String pkg = getNextArg();
2924 if (pkg == null) {
2925 getErrPrintWriter().println("Error: no package specified");
2926 return 1;
2927 }
2928 ActivityManager.dumpPackageStateStatic(getOutFileDescriptor(), pkg);
2929 return 0;
2930 }
2931
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002932 private int runSetHarmfulAppWarning() throws RemoteException {
2933 int userId = UserHandle.USER_CURRENT;
2934
2935 String opt;
2936 while ((opt = getNextOption()) != null) {
2937 if (opt.equals("--user")) {
2938 userId = UserHandle.parseUserArg(getNextArgRequired());
2939 } else {
2940 getErrPrintWriter().println("Error: Unknown option: " + opt);
2941 return -1;
2942 }
2943 }
2944
Todd Kennedyc3c52172019-11-26 13:20:59 -08002945 final int translatedUserId =
2946 translateUserId(userId, UserHandle.USER_NULL, "runSetHarmfulAppWarning");
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002947 final String packageName = getNextArgRequired();
2948 final String warning = getNextArg();
2949
Todd Kennedyc3c52172019-11-26 13:20:59 -08002950 mInterface.setHarmfulAppWarning(packageName, warning, translatedUserId);
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002951
2952 return 0;
2953 }
2954
Ben Gruver9ef60092018-01-10 11:32:30 -08002955 private int runGetHarmfulAppWarning() throws RemoteException {
2956 int userId = UserHandle.USER_CURRENT;
2957
2958 String opt;
2959 while ((opt = getNextOption()) != null) {
2960 if (opt.equals("--user")) {
2961 userId = UserHandle.parseUserArg(getNextArgRequired());
2962 } else {
2963 getErrPrintWriter().println("Error: Unknown option: " + opt);
2964 return -1;
2965 }
2966 }
2967
Todd Kennedyc3c52172019-11-26 13:20:59 -08002968 final int translatedUserId =
2969 translateUserId(userId, UserHandle.USER_NULL, "runGetHarmfulAppWarning");
Ben Gruver9ef60092018-01-10 11:32:30 -08002970 final String packageName = getNextArgRequired();
Todd Kennedyc3c52172019-11-26 13:20:59 -08002971 final CharSequence warning = mInterface.getHarmfulAppWarning(packageName, translatedUserId);
Ben Gruver9ef60092018-01-10 11:32:30 -08002972 if (!TextUtils.isEmpty(warning)) {
2973 getOutPrintWriter().println(warning);
2974 return 0;
2975 } else {
2976 return 1;
2977 }
2978 }
2979
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002980 private static String checkAbiArgument(String abi) {
2981 if (TextUtils.isEmpty(abi)) {
2982 throw new IllegalArgumentException("Missing ABI argument");
2983 }
2984
2985 if ("-".equals(abi)) {
2986 return abi;
2987 }
2988
2989 final String[] supportedAbis = Build.SUPPORTED_ABIS;
2990 for (String supportedAbi : supportedAbis) {
2991 if (supportedAbi.equals(abi)) {
2992 return abi;
2993 }
2994 }
2995
2996 throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
2997 }
2998
Todd Kennedyc3c52172019-11-26 13:20:59 -08002999 private int translateUserId(int userId, int allUserId, String logContext) {
3000 final boolean allowAll = (allUserId != UserHandle.USER_NULL);
3001 final int translatedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
3002 Binder.getCallingUid(), userId, allowAll, true, logContext, "pm command");
3003 return translatedUserId == UserHandle.USER_ALL ? allUserId : translatedUserId;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003004 }
3005
3006 private int doCreateSession(SessionParams params, String installerPackageName, int userId)
3007 throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003008 if (userId == UserHandle.USER_ALL) {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003009 params.installFlags |= PackageManager.INSTALL_ALL_USERS;
3010 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08003011 final int translatedUserId =
3012 translateUserId(userId, UserHandle.USER_SYSTEM, "doCreateSession");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003013 final int sessionId = mInterface.getPackageInstaller()
Todd Kennedyc3c52172019-11-26 13:20:59 -08003014 .createSession(params, installerPackageName, translatedUserId);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003015 return sessionId;
3016 }
3017
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003018 private int doAddFiles(int sessionId, ArrayList<String> args, long sessionSizeBytes,
3019 boolean isApex) throws RemoteException {
Alex Buynytskyyc282de92020-03-10 10:27:42 -07003020 PackageInstaller.Session session = null;
Alex Buynytskyyda208152019-11-11 09:34:05 -08003021 try {
Alex Buynytskyyc282de92020-03-10 10:27:42 -07003022 session = new PackageInstaller.Session(
3023 mInterface.getPackageInstaller().openSession(sessionId));
3024
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003025 // 1. Single file from stdin.
3026 if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) {
Alex Buynytskyy17d9da02020-02-12 16:03:30 -08003027 final String name = "base." + (isApex ? "apex" : "apk");
3028 final String metadata = "-" + name;
3029 session.addFile(LOCATION_DATA_APP, name, sessionSizeBytes,
3030 metadata.getBytes(StandardCharsets.UTF_8), null);
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003031 return 0;
Alex Buynytskyyda208152019-11-11 09:34:05 -08003032 }
3033
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003034 for (String arg : args) {
3035 final int delimLocation = arg.indexOf(':');
3036
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003037 if (delimLocation != -1) {
Songchun Fan5f911c82020-02-19 16:23:08 -08003038 // 2. File with specified size read from stdin.
3039 if (processArgForStdin(arg, session) != 0) {
Alex Buynytskyy17d9da02020-02-12 16:03:30 -08003040 return 1;
3041 }
Songchun Fan5f911c82020-02-19 16:23:08 -08003042 } else {
3043 // 3. Local file.
3044 processArgForLocalFile(arg, session);
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003045 }
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003046 }
Alex Buynytskyyda208152019-11-11 09:34:05 -08003047 return 0;
Alex Buynytskyyc282de92020-03-10 10:27:42 -07003048 } catch (IllegalArgumentException e) {
3049 getErrPrintWriter().println("Failed to add file(s), reason: " + e);
3050 getOutPrintWriter().println("Failure [failed to add file(s)]");
3051 return 1;
Alex Buynytskyyda208152019-11-11 09:34:05 -08003052 } finally {
3053 IoUtils.closeQuietly(session);
3054 }
3055 }
3056
Songchun Fan5f911c82020-02-19 16:23:08 -08003057 private int processArgForStdin(String arg, PackageInstaller.Session session) {
3058 final String[] fileDesc = arg.split(":");
3059 String name, metadata;
3060 long sizeBytes;
3061 byte[] signature = null;
3062
3063 try {
3064 if (fileDesc.length < 2) {
3065 getErrPrintWriter().println("Must specify file name and size");
3066 return 1;
3067 }
3068 name = fileDesc[0];
3069 sizeBytes = Long.parseUnsignedLong(fileDesc[1]);
3070 metadata = name;
3071
3072 if (fileDesc.length > 2 && !TextUtils.isEmpty(fileDesc[2])) {
3073 metadata = fileDesc[2];
3074 }
3075 if (fileDesc.length > 3) {
3076 signature = Base64.getDecoder().decode(fileDesc[3]);
3077 }
3078 } catch (IllegalArgumentException e) {
3079 getErrPrintWriter().println(
3080 "Unable to parse file parameters: " + arg + ", reason: " + e);
3081 return 1;
3082 }
3083
3084 if (TextUtils.isEmpty(name)) {
3085 getErrPrintWriter().println("Empty file name in: " + arg);
3086 return 1;
3087 }
3088
3089 if (signature != null) {
3090 // Streaming/adb mode.
3091 metadata = "+" + metadata;
3092 try {
3093 if (V4Signature.readFrom(signature) == null) {
3094 getErrPrintWriter().println("V4 signature is invalid in: " + arg);
3095 return 1;
3096 }
3097 } catch (Exception e) {
3098 getErrPrintWriter().println(
3099 "V4 signature is invalid: " + e + " in " + arg);
3100 return 1;
3101 }
3102 } else {
3103 // Single-shot read from stdin.
3104 metadata = "-" + metadata;
3105 }
3106
3107 session.addFile(LOCATION_DATA_APP, name, sizeBytes,
3108 metadata.getBytes(StandardCharsets.UTF_8), signature);
3109 return 0;
3110 }
3111
3112 private void processArgForLocalFile(String arg, PackageInstaller.Session session) {
3113 final String inPath = arg;
3114
3115 final File file = new File(inPath);
3116 final String name = file.getName();
3117 final long size = file.length();
3118 final byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8);
3119
Songchun Fan38dfe9a2020-02-20 18:12:47 -08003120 byte[] v4signatureBytes = null;
3121 // Try to load the v4 signature file for the APK; it might not exist.
3122 final String v4SignaturePath = inPath + V4Signature.EXT;
3123 final ParcelFileDescriptor pfd = openFileForSystem(v4SignaturePath, "r");
3124 if (pfd != null) {
3125 try {
3126 final V4Signature v4signature = V4Signature.readFrom(pfd);
3127 v4signatureBytes = v4signature.toByteArray();
3128 } catch (IOException ex) {
3129 Slog.e(TAG, "V4 signature file exists but failed to be parsed.", ex);
3130 } finally {
3131 IoUtils.closeQuietly(pfd);
3132 }
3133 }
Songchun Fan5f911c82020-02-19 16:23:08 -08003134
3135 session.addFile(LOCATION_DATA_APP, name, size, metadata, v4signatureBytes);
3136 }
3137
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003138 private int doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes,
3139 boolean isApex) throws RemoteException {
3140 final boolean multipleSplits = splitPaths.size() > 1;
3141 for (String splitPath : splitPaths) {
3142 String splitName = multipleSplits ? new File(splitPath).getName()
3143 : "base." + (isApex ? "apex" : "apk");
3144
3145 if (doWriteSplit(sessionId, splitPath, sessionSizeBytes, splitName,
3146 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
3147 return 1;
3148 }
3149 }
3150 return 0;
3151 }
3152
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003153 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003154 boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003155 PackageInstaller.Session session = null;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003156 try {
Alex Buynytskyyda208152019-11-11 09:34:05 -08003157 session = new PackageInstaller.Session(
3158 mInterface.getPackageInstaller().openSession(sessionId));
3159
Jeff Sharkeya651b782018-07-23 13:45:28 -06003160 final PrintWriter pw = getOutPrintWriter();
Alex Buynytskyyda208152019-11-11 09:34:05 -08003161
Jeff Sharkeya651b782018-07-23 13:45:28 -06003162 final ParcelFileDescriptor fd;
3163 if (STDIN_PATH.equals(inPath)) {
3164 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
3165 } else if (inPath != null) {
3166 fd = openFileForSystem(inPath, "r");
3167 if (fd == null) {
3168 return -1;
3169 }
3170 sizeBytes = fd.getStatSize();
3171 if (sizeBytes < 0) {
3172 getErrPrintWriter().println("Unable to get size of: " + inPath);
3173 return -1;
3174 }
3175 } else {
3176 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
3177 }
3178 if (sizeBytes <= 0) {
3179 getErrPrintWriter().println("Error: must specify a APK size");
3180 return 1;
3181 }
3182
Jeff Sharkey0451de62018-02-02 11:27:21 -07003183 session.write(splitName, 0, sizeBytes, fd);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003184
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003185 if (logSuccess) {
Jeff Sharkey0451de62018-02-02 11:27:21 -07003186 pw.println("Success: streamed " + sizeBytes + " bytes");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003187 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003188 return 0;
3189 } catch (IOException e) {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07003190 getErrPrintWriter().println("Error: failed to write; " + e.getMessage());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003191 return 1;
3192 } finally {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003193 IoUtils.closeQuietly(session);
3194 }
3195 }
3196
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003197 private int doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)
3198 throws RemoteException {
3199 final PrintWriter pw = getOutPrintWriter();
3200 PackageInstaller.Session session = null;
3201 try {
3202 session = new PackageInstaller.Session(
3203 mInterface.getPackageInstaller().openSession(parentId));
3204 if (!session.isMultiPackage()) {
3205 getErrPrintWriter().println(
3206 "Error: parent session ID is not a multi-package session");
3207 return 1;
3208 }
3209 for (int i = 0; i < sessionIds.length; i++) {
3210 session.addChildSessionId(sessionIds[i]);
3211 }
3212 if (logSuccess) {
3213 pw.println("Success");
3214 }
3215 return 0;
3216 } finally {
3217 IoUtils.closeQuietly(session);
3218 }
3219 }
3220
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003221 private int doRemoveSplits(int sessionId, Collection<String> splitNames, boolean logSuccess)
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003222 throws RemoteException {
3223 final PrintWriter pw = getOutPrintWriter();
3224 PackageInstaller.Session session = null;
3225 try {
3226 session = new PackageInstaller.Session(
3227 mInterface.getPackageInstaller().openSession(sessionId));
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003228 for (String splitName : splitNames) {
3229 session.removeSplit(splitName);
3230 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003231
3232 if (logSuccess) {
3233 pw.println("Success");
3234 }
3235 return 0;
3236 } catch (IOException e) {
3237 pw.println("Error: failed to remove split; " + e.getMessage());
3238 return 1;
3239 } finally {
3240 IoUtils.closeQuietly(session);
3241 }
3242 }
3243
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003244 private int doCommitSession(int sessionId, boolean logSuccess)
3245 throws RemoteException {
3246
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003247 final PrintWriter pw = getOutPrintWriter();
3248 PackageInstaller.Session session = null;
3249 try {
3250 session = new PackageInstaller.Session(
3251 mInterface.getPackageInstaller().openSession(sessionId));
Dario Frenia8f4b132018-12-30 00:36:49 +00003252 if (!session.isMultiPackage() && !session.isStaged()) {
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003253 // Sanity check that all .dm files match an apk.
3254 // (The installer does not support standalone .dm files and will not process them.)
3255 try {
3256 DexMetadataHelper.validateDexPaths(session.getNames());
3257 } catch (IllegalStateException | IOException e) {
3258 pw.println(
3259 "Warning [Could not validate the dex paths: " + e.getMessage() + "]");
3260 }
Calin Juravle3fc56c32017-12-11 18:26:13 -08003261 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003262 final LocalIntentReceiver receiver = new LocalIntentReceiver();
3263 session.commit(receiver.getIntentSender());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003264 final Intent result = receiver.getResult();
3265 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
3266 PackageInstaller.STATUS_FAILURE);
3267 if (status == PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003268 if (logSuccess) {
Todd Kennedyb6e96e52016-07-20 16:27:39 -07003269 pw.println("Success");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003270 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003271 } else {
3272 pw.println("Failure ["
3273 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003274 }
3275 return status;
3276 } finally {
3277 IoUtils.closeQuietly(session);
3278 }
3279 }
3280
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003281 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003282 final PrintWriter pw = getOutPrintWriter();
3283 PackageInstaller.Session session = null;
3284 try {
3285 session = new PackageInstaller.Session(
3286 mInterface.getPackageInstaller().openSession(sessionId));
3287 session.abandon();
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003288 if (logSuccess) {
3289 pw.println("Success");
3290 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003291 return 0;
3292 } finally {
3293 IoUtils.closeQuietly(session);
3294 }
3295 }
3296
Todd Kennedy60459ab2015-10-30 11:32:16 -07003297 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
3298 boolean summary, int startProtectionLevel, int endProtectionLevel)
3299 throws RemoteException {
3300 final PrintWriter pw = getOutPrintWriter();
3301 final int groupCount = groupList.size();
3302 for (int i = 0; i < groupCount; i++) {
3303 String groupName = groupList.get(i);
3304 String prefix = "";
3305 if (groups) {
3306 if (i > 0) {
3307 pw.println("");
3308 }
3309 if (groupName != null) {
3310 PermissionGroupInfo pgi =
3311 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
3312 if (summary) {
3313 Resources res = getResources(pgi);
3314 if (res != null) {
3315 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
3316 } else {
3317 pw.print(pgi.name + ": ");
3318
3319 }
3320 } else {
3321 pw.println((labels ? "+ " : "") + "group:" + pgi.name);
3322 if (labels) {
3323 pw.println(" package:" + pgi.packageName);
3324 Resources res = getResources(pgi);
3325 if (res != null) {
3326 pw.println(" label:"
3327 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
3328 pw.println(" description:"
3329 + loadText(pgi, pgi.descriptionRes,
3330 pgi.nonLocalizedDescription));
3331 }
3332 }
3333 }
3334 } else {
3335 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
3336 }
3337 prefix = " ";
3338 }
Todd Kennedy1d29b4a2019-07-02 14:49:28 -07003339 List<PermissionInfo> ps = mPermissionManager
3340 .queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -07003341 final int count = ps.size();
3342 boolean first = true;
3343 for (int p = 0 ; p < count ; p++) {
3344 PermissionInfo pi = ps.get(p);
3345 if (groups && groupName == null && pi.group != null) {
3346 continue;
3347 }
3348 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
3349 if (base < startProtectionLevel
3350 || base > endProtectionLevel) {
3351 continue;
3352 }
3353 if (summary) {
3354 if (first) {
3355 first = false;
3356 } else {
3357 pw.print(", ");
3358 }
3359 Resources res = getResources(pi);
3360 if (res != null) {
3361 pw.print(loadText(pi, pi.labelRes,
3362 pi.nonLocalizedLabel));
3363 } else {
3364 pw.print(pi.name);
3365 }
3366 } else {
3367 pw.println(prefix + (labels ? "+ " : "")
3368 + "permission:" + pi.name);
3369 if (labels) {
3370 pw.println(prefix + " package:" + pi.packageName);
3371 Resources res = getResources(pi);
3372 if (res != null) {
3373 pw.println(prefix + " label:"
3374 + loadText(pi, pi.labelRes,
3375 pi.nonLocalizedLabel));
3376 pw.println(prefix + " description:"
3377 + loadText(pi, pi.descriptionRes,
3378 pi.nonLocalizedDescription));
3379 }
3380 pw.println(prefix + " protectionLevel:"
3381 + PermissionInfo.protectionToString(pi.protectionLevel));
3382 }
3383 }
3384 }
3385
3386 if (summary) {
3387 pw.println("");
3388 }
3389 }
3390 }
3391
3392 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
3393 throws RemoteException {
3394 if (nonLocalized != null) {
3395 return nonLocalized.toString();
3396 }
3397 if (res != 0) {
3398 Resources r = getResources(pii);
3399 if (r != null) {
3400 try {
3401 return r.getString(res);
3402 } catch (Resources.NotFoundException e) {
3403 }
3404 }
3405 }
3406 return null;
3407 }
3408
3409 private Resources getResources(PackageItemInfo pii) throws RemoteException {
3410 Resources res = mResourceCache.get(pii.packageName);
3411 if (res != null) return res;
3412
Patrick Baumannbc883f62019-05-21 11:20:11 -07003413 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName,
3414 PackageManager.MATCH_DISABLED_COMPONENTS
3415 | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
3416 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, 0);
Todd Kennedy60459ab2015-10-30 11:32:16 -07003417 AssetManager am = new AssetManager();
3418 am.addAssetPath(ai.publicSourceDir);
3419 res = new Resources(am, null, null);
3420 mResourceCache.put(pii.packageName, res);
3421 return res;
3422 }
3423
3424 @Override
3425 public void onHelp() {
3426 final PrintWriter pw = getOutPrintWriter();
3427 pw.println("Package manager (package) commands:");
3428 pw.println(" help");
3429 pw.println(" Print this help text.");
3430 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003431 pw.println(" path [--user USER_ID] PACKAGE");
3432 pw.println(" Print the path to the .apk of the given PACKAGE.");
3433 pw.println("");
3434 pw.println(" dump PACKAGE");
3435 pw.println(" Print various system state associated with the given PACKAGE.");
3436 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003437 pw.println(" has-feature FEATURE_NAME [version]");
3438 pw.println(" Prints true and returns exit status 0 when system has a FEATURE_NAME,");
3439 pw.println(" otherwise prints false and returns exit status 1");
3440 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003441 pw.println(" list features");
3442 pw.println(" Prints all features of the system.");
3443 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003444 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
3445 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE");
3446 pw.println(" Options:");
3447 pw.println(" -f: dump the name of the .apk file containing the test package");
3448 pw.println("");
3449 pw.println(" list libraries");
3450 pw.println(" Prints all system libraries.");
3451 pw.println("");
3452 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
Jiyong Parkf50a2932018-12-17 13:54:40 +09003453 pw.println(" [--show-versioncode] [--apex-only] [--uid UID] [--user USER_ID] [FILTER]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003454 pw.println(" Prints all packages; optionally only those whose name contains");
3455 pw.println(" the text in FILTER. Options are:");
3456 pw.println(" -f: see their associated file");
Jiyong Park4f49abe2018-12-11 13:37:17 +09003457 pw.println(" -a: all known packages (but excluding APEXes)");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003458 pw.println(" -d: filter to only show disabled packages");
3459 pw.println(" -e: filter to only show enabled packages");
3460 pw.println(" -s: filter to only show system packages");
3461 pw.println(" -3: filter to only show third party packages");
3462 pw.println(" -i: see the installer for the packages");
3463 pw.println(" -l: ignored (used for compatibility with older releases)");
3464 pw.println(" -U: also show the package UID");
3465 pw.println(" -u: also include uninstalled packages");
Jiyong Parkf50a2932018-12-17 13:54:40 +09003466 pw.println(" --show-versioncode: also show the version code");
Jiyong Park4f49abe2018-12-11 13:37:17 +09003467 pw.println(" --apex-only: only show APEX packages");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003468 pw.println(" --uid UID: filter to only show packages with the given UID");
3469 pw.println(" --user USER_ID: only list packages belonging to the given user");
3470 pw.println("");
3471 pw.println(" list permission-groups");
3472 pw.println(" Prints all known permission groups.");
3473 pw.println("");
3474 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
3475 pw.println(" Prints all known permissions; optionally only those in GROUP. Options are:");
3476 pw.println(" -g: organize by group");
3477 pw.println(" -f: print all information");
3478 pw.println(" -s: short summary");
3479 pw.println(" -d: only list dangerous permissions");
3480 pw.println(" -u: list only the permissions users will see");
3481 pw.println("");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003482 pw.println(" list staged-sessions [--only-ready] [--only-sessionid] [--only-parent]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003483 pw.println(" Prints all staged sessions.");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003484 pw.println(" --only-ready: show only staged sessions that are ready");
3485 pw.println(" --only-sessionid: show only sessionId of each session");
3486 pw.println(" --only-parent: hide all children sessions");
3487 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003488 pw.println(" list users");
3489 pw.println(" Prints all users.");
3490 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003491 pw.println(" resolve-activity [--brief] [--components] [--query-flags FLAGS]");
3492 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003493 pw.println(" Prints the activity that resolves to the given INTENT.");
3494 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003495 pw.println(" query-activities [--brief] [--components] [--query-flags FLAGS]");
3496 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003497 pw.println(" Prints all activities that can handle the given INTENT.");
3498 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003499 pw.println(" query-services [--brief] [--components] [--query-flags FLAGS]");
3500 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003501 pw.println(" Prints all services that can handle the given INTENT.");
3502 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003503 pw.println(" query-receivers [--brief] [--components] [--query-flags FLAGS]");
3504 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003505 pw.println(" Prints all broadcast receivers that can handle the given INTENT.");
3506 pw.println("");
Mark De Ruyterbfcd3392019-11-21 12:08:58 -08003507 pw.println(" install [-rtfdgw] [-i PACKAGE] [--user USER_ID|all|current]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003508 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003509 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
3510 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003511 pw.println(" [--preload] [--instant] [--full] [--dont-kill]");
Richard Uhlerb29f1452018-09-12 16:38:15 +01003512 pw.println(" [--enable-rollback]");
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01003513 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
3514 pw.println(" [--apex] [--wait TIMEOUT]");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003515 pw.println(" [PATH [SPLIT...]|-]");
3516 pw.println(" Install an application. Must provide the apk data to install, either as");
3517 pw.println(" file path(s) or '-' to read from stdin. Options are:");
Patrick Baumanna9333492017-11-28 15:23:49 -08003518 pw.println(" -R: disallow replacement of existing application");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003519 pw.println(" -t: allow test packages");
3520 pw.println(" -i: specify package name of installer owning the app");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003521 pw.println(" -f: install application on internal flash");
3522 pw.println(" -d: allow version code downgrade (debuggable packages only)");
3523 pw.println(" -p: partial application install (new split on top of existing pkg)");
3524 pw.println(" -g: grant all runtime permissions");
3525 pw.println(" -S: size in bytes of package, required for stdin");
3526 pw.println(" --user: install under the given user.");
3527 pw.println(" --dont-kill: installing a new feature split, don't kill running app");
Svet Ganov83a3a4a2019-05-03 18:50:43 -07003528 pw.println(" --restrict-permissions: don't whitelist restricted permissions at install");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003529 pw.println(" --originating-uri: set URI where app was downloaded from");
3530 pw.println(" --referrer: set URI that instigated the install of the app");
3531 pw.println(" --pkg: specify expected package name of app being installed");
3532 pw.println(" --abi: override the default ABI of the platform");
Todd Kennedybef39e02019-09-20 15:14:18 -07003533 pw.println(" --instant: cause the app to be installed as an ephemeral install app");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003534 pw.println(" --full: cause the app to be installed as a non-ephemeral full app");
3535 pw.println(" --install-location: force the install location:");
3536 pw.println(" 0=auto, 1=internal only, 2=prefer external");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003537 pw.println(" --install-reason: indicates why the app is being installed:");
3538 pw.println(" 0=unknown, 1=admin policy, 2=device restore,");
3539 pw.println(" 3=device setup, 4=user request");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003540 pw.println(" --force-uuid: force install on to disk volume with given UUID");
MÃ¥rten Kongstad2a5989342018-11-16 15:04:44 +01003541 pw.println(" --apex: install an .apex file, not an .apk");
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01003542 pw.println(" --wait: when performing staged install, wait TIMEOUT milliseconds");
3543 pw.println(" for pre-reboot verification to complete. If TIMEOUT is not");
3544 pw.println(" specified it will wait for " + DEFAULT_WAIT_MS + " milliseconds.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003545 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003546 pw.println(" install-existing [--user USER_ID|all|current]");
3547 pw.println(" [--instant] [--full] [--wait] [--restrict-permissions] PACKAGE");
3548 pw.println(" Installs an existing application for a new user. Options are:");
3549 pw.println(" --user: install for the given user.");
3550 pw.println(" --instant: install as an instant app");
3551 pw.println(" --full: install as a full app");
3552 pw.println(" --wait: wait until the package is installed");
3553 pw.println(" --restrict-permissions: don't whitelist restricted permissions");
3554 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003555 pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
3556 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003557 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
3558 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003559 pw.println(" [--preload] [--instant] [--full] [--dont-kill]");
MÃ¥rten Kongstad2a5989342018-11-16 15:04:44 +01003560 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [--apex] [-S BYTES]");
Dario Freniaac4ba42018-12-06 15:47:16 +00003561 pw.println(" [--multi-package] [--staged]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003562 pw.println(" Like \"install\", but starts an install session. Use \"install-write\"");
3563 pw.println(" to push data into the session, and \"install-commit\" to finish.");
3564 pw.println("");
3565 pw.println(" install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]");
3566 pw.println(" Write an apk into the given install session. If the path is '-', data");
3567 pw.println(" will be read from stdin. Options are:");
3568 pw.println(" -S: size in bytes of package, required for stdin");
3569 pw.println("");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003570 pw.println(" install-remove SESSION_ID SPLIT...");
3571 pw.println(" Mark SPLIT(s) as removed in the given install session.");
3572 pw.println("");
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003573 pw.println(" install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs");
3574 pw.println(" Add one or more session IDs to a multi-package session.");
3575 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003576 pw.println(" install-commit SESSION_ID");
3577 pw.println(" Commit the given active install session, installing the app.");
3578 pw.println("");
3579 pw.println(" install-abandon SESSION_ID");
3580 pw.println(" Delete the given active install session.");
3581 pw.println("");
3582 pw.println(" set-install-location LOCATION");
3583 pw.println(" Changes the default install location. NOTE this is only intended for debugging;");
3584 pw.println(" using this can cause applications to break and other undersireable behavior.");
3585 pw.println(" LOCATION is one of:");
3586 pw.println(" 0 [auto]: Let system decide the best location");
3587 pw.println(" 1 [internal]: Install on internal device storage");
3588 pw.println(" 2 [external]: Install on external media");
3589 pw.println("");
3590 pw.println(" get-install-location");
3591 pw.println(" Returns the current install location: 0, 1 or 2 as per set-install-location.");
3592 pw.println("");
3593 pw.println(" move-package PACKAGE [internal|UUID]");
3594 pw.println("");
3595 pw.println(" move-primary-storage [internal|UUID]");
3596 pw.println("");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003597 pw.println(" uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE]");
3598 pw.println(" PACKAGE [SPLIT...]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003599 pw.println(" Remove the given package name from the system. May remove an entire app");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003600 pw.println(" if no SPLIT names specified, otherwise will remove only the splits of the");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003601 pw.println(" given app. Options are:");
3602 pw.println(" -k: keep the data and cache directories around after package removal.");
3603 pw.println(" --user: remove the app from the given user.");
3604 pw.println(" --versionCode: only uninstall if the app has the given version code.");
3605 pw.println("");
3606 pw.println(" clear [--user USER_ID] PACKAGE");
3607 pw.println(" Deletes all data associated with a package.");
3608 pw.println("");
3609 pw.println(" enable [--user USER_ID] PACKAGE_OR_COMPONENT");
3610 pw.println(" disable [--user USER_ID] PACKAGE_OR_COMPONENT");
3611 pw.println(" disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
3612 pw.println(" disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
3613 pw.println(" default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
3614 pw.println(" These commands change the enabled state of a given package or");
3615 pw.println(" component (written as \"package/class\").");
3616 pw.println("");
3617 pw.println(" hide [--user USER_ID] PACKAGE_OR_COMPONENT");
3618 pw.println(" unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
3619 pw.println("");
3620 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE");
3621 pw.println(" Suspends the specified package (as user).");
3622 pw.println("");
3623 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE");
3624 pw.println(" Unsuspends the specified package (as user).");
3625 pw.println("");
3626 pw.println(" grant [--user USER_ID] PACKAGE PERMISSION");
3627 pw.println(" revoke [--user USER_ID] PACKAGE PERMISSION");
3628 pw.println(" These commands either grant or revoke permissions to apps. The permissions");
3629 pw.println(" must be declared as used in the app's manifest, be runtime permissions");
3630 pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
3631 pw.println("");
3632 pw.println(" reset-permissions");
3633 pw.println(" Revert all runtime permissions to their default state.");
3634 pw.println("");
3635 pw.println(" set-permission-enforced PERMISSION [true|false]");
3636 pw.println("");
3637 pw.println(" get-privapp-permissions TARGET-PACKAGE");
3638 pw.println(" Prints all privileged permissions for a package.");
3639 pw.println("");
3640 pw.println(" get-privapp-deny-permissions TARGET-PACKAGE");
3641 pw.println(" Prints all privileged permissions that are denied for a package.");
3642 pw.println("");
3643 pw.println(" get-oem-permissions TARGET-PACKAGE");
3644 pw.println(" Prints all OEM permissions for a package.");
3645 pw.println("");
3646 pw.println(" set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
3647 pw.println(" get-app-link [--user USER_ID] PACKAGE");
3648 pw.println("");
3649 pw.println(" trim-caches DESIRED_FREE_SPACE [internal|UUID]");
3650 pw.println(" Trim cache files to reach the given free space.");
3651 pw.println("");
Felipe Lemec1ca4412019-09-11 09:23:26 -07003652 pw.println(" list users");
3653 pw.println(" Lists the current users.");
3654 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003655 pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
Bookatz029832a2019-10-04 16:50:22 -07003656 pw.println(" [--guest] [--pre-create-only] [--user-type USER_TYPE] USER_NAME");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003657 pw.println(" Create a new user with the given USER_NAME, printing the new user identifier");
3658 pw.println(" of the user.");
Bookatz029832a2019-10-04 16:50:22 -07003659 // TODO(b/142482943): Consider fetching the list of user types from UMS.
3660 pw.println(" USER_TYPE is the name of a user type, e.g. android.os.usertype.profile.MANAGED.");
3661 pw.println(" If not specified, the default user type is android.os.usertype.full.SECONDARY.");
3662 pw.println(" --managed is shorthand for '--user-type android.os.usertype.profile.MANAGED'.");
3663 pw.println(" --restricted is shorthand for '--user-type android.os.usertype.full.RESTRICTED'.");
3664 pw.println(" --guest is shorthand for '--user-type android.os.usertype.full.GUEST'.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003665 pw.println("");
3666 pw.println(" remove-user USER_ID");
3667 pw.println(" Remove the user with the given USER_IDENTIFIER, deleting all data");
3668 pw.println(" associated with that user");
3669 pw.println("");
3670 pw.println(" set-user-restriction [--user USER_ID] RESTRICTION VALUE");
3671 pw.println("");
3672 pw.println(" get-max-users");
3673 pw.println("");
Alex Chauc12189b2018-01-16 15:01:15 +00003674 pw.println(" get-max-running-users");
3675 pw.println("");
Calin Juravleb6f844d2017-07-17 15:23:21 -07003676 pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
Richard Uhler568a9692016-05-03 16:02:52 -07003677 pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003678 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\". Options are:");
David Brazdil990fb6b2016-03-01 10:02:27 +00003679 pw.println(" -a: compile all packages");
David Brazdil9aa6db02016-03-08 12:57:12 +00003680 pw.println(" -c: clear profile data before compiling");
3681 pw.println(" -f: force compilation even if not needed");
David Brazdil493411a2016-02-01 13:48:46 +00003682 pw.println(" -m: select compilation mode");
Richard Uhler568a9692016-05-03 16:02:52 -07003683 pw.println(" MODE is one of the dex2oat compiler filters:");
Nicolas Geoffrayd1326522017-04-25 12:29:07 +01003684 pw.println(" assume-verified");
3685 pw.println(" extract");
3686 pw.println(" verify");
3687 pw.println(" quicken");
Richard Uhler568a9692016-05-03 16:02:52 -07003688 pw.println(" space-profile");
3689 pw.println(" space");
3690 pw.println(" speed-profile");
3691 pw.println(" speed");
3692 pw.println(" everything");
3693 pw.println(" -r: select compilation reason");
3694 pw.println(" REASON is one of:");
3695 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
3696 pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
3697 }
David Brazdilcf046952016-03-08 16:40:20 +00003698 pw.println(" --reset: restore package to its post-install state");
Richard Uhler568a9692016-05-03 16:02:52 -07003699 pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
Calin Juravlecb5f41e2017-01-25 17:16:08 -08003700 pw.println(" --secondary-dex: compile app secondary dex files");
Calin Juravleb6f844d2017-07-17 15:23:21 -07003701 pw.println(" --split SPLIT: compile only the given split name");
Eric Holka1485f62019-01-07 13:58:25 -08003702 pw.println(" --compile-layouts: compile layout resources for faster inflation");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003703 pw.println("");
3704 pw.println(" force-dex-opt PACKAGE");
3705 pw.println(" Force immediate execution of dex opt for the given PACKAGE.");
3706 pw.println("");
Calin Juravlecb5f41e2017-01-25 17:16:08 -08003707 pw.println(" bg-dexopt-job");
3708 pw.println(" Execute the background optimizations immediately.");
3709 pw.println(" Note that the command only runs the background optimizer logic. It may");
3710 pw.println(" overlap with the actual job but the job scheduler will not be able to");
3711 pw.println(" cancel it. It will also run even if the device is not in the idle");
3712 pw.println(" maintenance mode.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003713 pw.println("");
Calin Juravle1aa5f882017-01-25 01:05:50 -08003714 pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE");
3715 pw.println(" Reconciles the package secondary dex files with the generated oat files.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003716 pw.println("");
David Sehrcae13b02016-06-07 09:11:27 -07003717 pw.println(" dump-profiles TARGET-PACKAGE");
3718 pw.println(" Dumps method/class profile files to");
Calin Juravle21216c62018-05-04 17:35:29 -07003719 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + "TARGET-PACKAGE.txt");
3720 pw.println("");
3721 pw.println(" snapshot-profile TARGET-PACKAGE [--code-path path]");
3722 pw.println(" Take a snapshot of the package profiles to");
3723 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION
3724 + "TARGET-PACKAGE[-code-path].prof");
3725 pw.println(" If TARGET-PACKAGE=android it will take a snapshot of the boot image");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003726 pw.println("");
Makoto Onuki4828a592016-03-15 18:06:57 -07003727 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003728 pw.println(" Set the default home activity (aka launcher).");
Bookatz2b5a6012019-04-16 19:41:28 -07003729 pw.println(" TARGET-COMPONENT can be a package name (com.package.my) or a full");
3730 pw.println(" component (com.package.my/component.name). However, only the package name");
3731 pw.println(" matters: the actual component used will be determined automatically from");
3732 pw.println(" the package.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003733 pw.println("");
3734 pw.println(" set-installer PACKAGE INSTALLER");
3735 pw.println(" Set installer package name");
3736 pw.println("");
3737 pw.println(" get-instantapp-resolver");
3738 pw.println(" Return the name of the component that is the current instant app installer.");
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08003739 pw.println("");
3740 pw.println(" set-harmful-app-warning [--user <USER_ID>] <PACKAGE> [<WARNING>]");
3741 pw.println(" Mark the app as harmful with the given warning message.");
Ben Gruver9ef60092018-01-10 11:32:30 -08003742 pw.println("");
3743 pw.println(" get-harmful-app-warning [--user <USER_ID>] <PACKAGE>");
3744 pw.println(" Return the harmful app warning message for the given app, if present");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08003745 pw.println();
Patrick Baumanna980e142018-02-12 11:45:23 -08003746 pw.println(" uninstall-system-updates");
3747 pw.println(" Remove updates to all system applications and fall back to their /system " +
3748 "version.");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003749 pw.println("");
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +01003750 pw.println(" get-moduleinfo [--all | --installed] [module-name]");
3751 pw.println(" Displays module info. If module-name is specified only that info is shown");
3752 pw.println(" By default, without any argument only installed modules are shown.");
3753 pw.println(" --all: show all module info");
3754 pw.println(" --installed: show only installed modules");
3755 pw.println("");
Patrick Baumann4b491872020-02-25 11:51:44 -08003756 pw.println(" log-visibility [--enable|--disable] <PACKAGE>");
3757 pw.println(" Turns on debug logging when visibility is blocked for the given package.");
3758 pw.println(" --enable: turn on debug logging (default)");
3759 pw.println(" --disable: turn off debug logging");
3760 pw.println("");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08003761 Intent.printIntentArgsHelp(pw , "");
Todd Kennedy60459ab2015-10-30 11:32:16 -07003762 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003763
3764 private static class LocalIntentReceiver {
wangmingming155414292018-04-10 09:35:25 +08003765 private final LinkedBlockingQueue<Intent> mResult = new LinkedBlockingQueue<>();
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003766
3767 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
3768 @Override
Dianne Hackborn98305522017-05-05 17:53:53 -07003769 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003770 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
3771 try {
3772 mResult.offer(intent, 5, TimeUnit.SECONDS);
3773 } catch (InterruptedException e) {
3774 throw new RuntimeException(e);
3775 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003776 }
3777 };
3778
3779 public IntentSender getIntentSender() {
3780 return new IntentSender((IIntentSender) mLocalSender);
3781 }
3782
3783 public Intent getResult() {
3784 try {
3785 return mResult.take();
3786 } catch (InterruptedException e) {
3787 throw new RuntimeException(e);
3788 }
3789 }
3790 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07003791}