blob: 0dc4d131640cb03a32200030588ef3161aa8a88d [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;
Todd Kennedy60459ab2015-10-30 11:32:16 -070054import android.content.pm.ParceledListSlice;
55import android.content.pm.PermissionGroupInfo;
56import android.content.pm.PermissionInfo;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080057import android.content.pm.ResolveInfo;
Suprabh Shukla389cb6f2018-10-01 18:20:39 -070058import android.content.pm.SuspendDialogInfo;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070059import android.content.pm.UserInfo;
Svet Ganov67882122016-12-11 16:36:34 -080060import android.content.pm.VersionedPackage;
Calin Juravle21216c62018-05-04 17:35:29 -070061import android.content.pm.dex.ArtManager;
Calin Juravle3fc56c32017-12-11 18:26:13 -080062import android.content.pm.dex.DexMetadataHelper;
Calin Juravle21216c62018-05-04 17:35:29 -070063import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
Winson14ff7172019-10-23 10:42:27 -070064import android.content.pm.parsing.ApkLiteParseUtils;
Winson3cb56102020-04-17 16:24:57 -070065import android.content.pm.parsing.result.ParseResult;
66import android.content.pm.parsing.result.ParseTypeImpl;
Todd Kennedy60459ab2015-10-30 11:32:16 -070067import android.content.res.AssetManager;
68import android.content.res.Resources;
Narayan Kamathc5d752e2019-01-23 14:06:35 +000069import android.content.rollback.IRollbackManager;
70import android.content.rollback.PackageRollbackInfo;
71import android.content.rollback.RollbackInfo;
72import android.content.rollback.RollbackManager;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080073import android.net.Uri;
74import android.os.Binder;
75import android.os.Build;
76import android.os.Bundle;
Dianne Hackborn98305522017-05-05 17:53:53 -070077import android.os.IBinder;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070078import android.os.IUserManager;
Dianne Hackbornca3872c2017-10-30 14:19:32 -070079import android.os.ParcelFileDescriptor;
Calin Juravle21216c62018-05-04 17:35:29 -070080import android.os.ParcelFileDescriptor.AutoCloseInputStream;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080081import android.os.PersistableBundle;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070082import android.os.Process;
Bookatz2b5a6012019-04-16 19:41:28 -070083import android.os.RemoteCallback;
Todd Kennedy60459ab2015-10-30 11:32:16 -070084import android.os.RemoteException;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070085import android.os.ServiceManager;
Valentin Iftime89df4c82019-08-23 13:02:50 +020086import android.os.ServiceSpecificException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070087import android.os.ShellCommand;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070088import android.os.SystemClock;
Calin Juravle8bc758b2016-03-28 12:31:52 +010089import android.os.SystemProperties;
Todd Kennedy60459ab2015-10-30 11:32:16 -070090import android.os.UserHandle;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070091import android.os.UserManager;
Alex Buynytskyy8e9e6a32020-02-08 14:26:45 -080092import android.os.incremental.V4Signature;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070093import android.os.storage.StorageManager;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -070094import android.permission.IPermissionManager;
Calin Juravlebdd94d92018-05-17 01:23:15 -070095import android.system.ErrnoException;
96import android.system.Os;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080097import android.text.TextUtils;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070098import android.text.format.DateUtils;
Fyodor Kupolov51245c72016-12-01 11:34:10 -080099import android.util.ArraySet;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800100import android.util.PrintWriterPrinter;
Songchun Fan38dfe9a2020-02-20 18:12:47 -0800101import android.util.Slog;
Nikita Ioffebf883482019-08-08 22:09:31 +0100102import android.util.SparseArray;
Dario Freni2bef1762018-06-01 14:02:08 +0100103
Shunta Sato4f26cb52016-06-28 09:29:19 +0900104import com.android.internal.content.PackageHelper;
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700105import com.android.internal.util.ArrayUtils;
Nikita Ioffebf883482019-08-08 22:09:31 +0100106import com.android.internal.util.IndentingPrintWriter;
Alex Chauc12189b2018-01-16 15:01:15 +0000107import com.android.server.LocalServices;
Fyodor Kupolov51245c72016-12-01 11:34:10 -0800108import com.android.server.SystemConfig;
Alex Buynytskyy06970b92020-03-25 12:50:10 -0700109import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata;
Dario Freni2bef1762018-06-01 14:02:08 +0100110
Andreas Gampebdd30d82016-03-20 11:32:11 -0700111import dalvik.system.DexFile;
Dario Freni2bef1762018-06-01 14:02:08 +0100112
113import libcore.io.IoUtils;
114import libcore.io.Streams;
115
Calin Juravle21216c62018-05-04 17:35:29 -0700116import java.io.File;
117import java.io.FileOutputStream;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800118import java.io.IOException;
Calin Juravle21216c62018-05-04 17:35:29 -0700119import java.io.InputStream;
120import java.io.OutputStream;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700121import java.io.PrintWriter;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800122import java.net.URISyntaxException;
Calin Juravle21216c62018-05-04 17:35:29 -0700123import java.util.ArrayList;
Alex Buynytskyy17d9da02020-02-12 16:03:30 -0800124import java.util.Base64;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000125import java.util.Collection;
Calin Juravle21216c62018-05-04 17:35:29 -0700126import java.util.Collections;
127import java.util.Comparator;
128import java.util.LinkedList;
129import java.util.List;
130import java.util.Map;
131import java.util.Objects;
132import java.util.WeakHashMap;
Bookatz2b5a6012019-04-16 19:41:28 -0700133import java.util.concurrent.CompletableFuture;
Calin Juravle21216c62018-05-04 17:35:29 -0700134import java.util.concurrent.CountDownLatch;
wangmingming155414292018-04-10 09:35:25 +0800135import java.util.concurrent.LinkedBlockingQueue;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800136import java.util.concurrent.TimeUnit;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700137
138class PackageManagerShellCommand extends ShellCommand {
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700139 /** Path for streaming APK content */
140 private static final String STDIN_PATH = "-";
Calin Juravle21216c62018-05-04 17:35:29 -0700141 /** Path where ART profiles snapshots are dumped for the shell user */
142 private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +0100143 private static final int DEFAULT_WAIT_MS = 60 * 1000;
Songchun Fan38dfe9a2020-02-20 18:12:47 -0800144 private static final String TAG = "PackageManagerShellCommand";
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700145
Todd Kennedy60459ab2015-10-30 11:32:16 -0700146 final IPackageManager mInterface;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700147 final IPermissionManager mPermissionManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700148 final private WeakHashMap<String, Resources> mResourceCache =
149 new WeakHashMap<String, Resources>();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800150 int mTargetUser;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700151 boolean mBrief;
152 boolean mComponents;
Ng Zhi An73971312018-09-11 21:39:14 -0700153 int mQueryFlags;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700154
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700155 PackageManagerShellCommand(
156 PackageManagerService service, IPermissionManager permissionManager) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700157 mInterface = service;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700158 mPermissionManager = permissionManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700159 }
160
161 @Override
162 public int onCommand(String cmd) {
163 if (cmd == null) {
164 return handleDefaultCommands(cmd);
165 }
166
167 final PrintWriter pw = getOutPrintWriter();
168 try {
Alex Buynytskyy476138c2019-12-20 14:41:47 -0800169 switch (cmd) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700170 case "path":
171 return runPath();
172 case "dump":
173 return runDump();
174 case "list":
175 return runList();
176 case "resolve-activity":
177 return runResolveActivity();
178 case "query-activities":
179 return runQueryIntentActivities();
180 case "query-services":
181 return runQueryIntentServices();
182 case "query-receivers":
183 return runQueryIntentReceivers();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800184 case "install":
185 return runInstall();
Alex Buynytskyyda208152019-11-11 09:34:05 -0800186 case "install-streaming":
187 return runStreamingInstall();
Alex Buynytskyy04f73912020-02-10 08:34:18 -0800188 case "install-incremental":
189 return runIncrementalInstall();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800190 case "install-abandon":
191 case "install-destroy":
192 return runInstallAbandon();
193 case "install-commit":
194 return runInstallCommit();
195 case "install-create":
196 return runInstallCreate();
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800197 case "install-remove":
198 return runInstallRemove();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800199 case "install-write":
200 return runInstallWrite();
Todd Kennedybe0b8892017-02-15 14:13:52 -0800201 case "install-existing":
202 return runInstallExisting();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700203 case "set-install-location":
204 return runSetInstallLocation();
205 case "get-install-location":
206 return runGetInstallLocation();
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000207 case "install-add-session":
208 return runInstallAddSession();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700209 case "move-package":
210 return runMovePackage();
211 case "move-primary-storage":
212 return runMovePrimaryStorage();
David Brazdil493411a2016-02-01 13:48:46 +0000213 case "compile":
214 return runCompile();
Calin Juravle1aa5f882017-01-25 01:05:50 -0800215 case "reconcile-secondary-dex-files":
216 return runreconcileSecondaryDexFiles();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700217 case "force-dex-opt":
218 return runForceDexOpt();
Calin Juravlecb5f41e2017-01-25 17:16:08 -0800219 case "bg-dexopt-job":
220 return runDexoptJob();
David Sehra8777082016-05-24 15:25:23 -0700221 case "dump-profiles":
222 return runDumpProfiles();
Calin Juravle21216c62018-05-04 17:35:29 -0700223 case "snapshot-profile":
224 return runSnapshotProfile();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800225 case "uninstall":
226 return runUninstall();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700227 case "clear":
228 return runClear();
229 case "enable":
230 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
231 case "disable":
232 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
233 case "disable-user":
234 return runSetEnabledSetting(
235 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
236 case "disable-until-used":
237 return runSetEnabledSetting(
238 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
239 case "default-state":
240 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
241 case "hide":
242 return runSetHiddenSetting(true);
243 case "unhide":
244 return runSetHiddenSetting(false);
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000245 case "suspend":
246 return runSuspend(true);
247 case "unsuspend":
248 return runSuspend(false);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700249 case "grant":
250 return runGrantRevokePermission(true);
251 case "revoke":
252 return runGrantRevokePermission(false);
253 case "reset-permissions":
254 return runResetPermissions();
255 case "set-permission-enforced":
256 return runSetPermissionEnforced();
Fyodor Kupolov51245c72016-12-01 11:34:10 -0800257 case "get-privapp-permissions":
258 return runGetPrivappPermissions();
Todd Kennedy74629e32017-08-15 14:48:07 -0700259 case "get-privapp-deny-permissions":
260 return runGetPrivappDenyPermissions();
Svet Ganov087dce22017-09-07 15:42:16 -0700261 case "get-oem-permissions":
262 return runGetOemPermissions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700263 case "set-app-link":
264 return runSetAppLink();
265 case "get-app-link":
266 return runGetAppLink();
267 case "trim-caches":
268 return runTrimCaches();
269 case "create-user":
270 return runCreateUser();
271 case "remove-user":
272 return runRemoveUser();
273 case "set-user-restriction":
274 return runSetUserRestriction();
275 case "get-max-users":
276 return runGetMaxUsers();
Alex Chauc12189b2018-01-16 15:01:15 +0000277 case "get-max-running-users":
278 return runGetMaxRunningUsers();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700279 case "set-home-activity":
280 return runSetHomeActivity();
281 case "set-installer":
282 return runSetInstaller();
Todd Kennedy0a3f0812017-05-08 14:43:15 -0700283 case "get-instantapp-resolver":
284 return runGetInstantAppResolver();
Tadashi G. Takaokabe5782f2017-02-14 16:41:49 +0900285 case "has-feature":
286 return runHasFeature();
Ben Gruver1ab3d6e2017-12-07 13:45:08 -0800287 case "set-harmful-app-warning":
288 return runSetHarmfulAppWarning();
Ben Gruver9ef60092018-01-10 11:32:30 -0800289 case "get-harmful-app-warning":
290 return runGetHarmfulAppWarning();
Abhijeet Kaur84b1f5d2019-01-21 17:18:03 +0000291 case "get-stagedsessions":
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100292 return runListStagedSessions();
Patrick Baumanna980e142018-02-12 11:45:23 -0800293 case "uninstall-system-updates":
294 return uninstallSystemUpdates();
Narayan Kamathc5d752e2019-01-23 14:06:35 +0000295 case "rollback-app":
296 return runRollbackApp();
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +0100297 case "get-moduleinfo":
298 return runGetModuleInfo();
Patrick Baumann4b491872020-02-25 11:51:44 -0800299 case "log-visibility":
300 return runLogVisibility();
Jerry Chang30a1f132020-03-19 21:38:01 +0800301 case "bypass-staged-installer-check":
302 return runBypassStagedInstallerCheck();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700303 default: {
304 String nextArg = getNextArg();
305 if (nextArg == null) {
306 if (cmd.equalsIgnoreCase("-l")) {
307 return runListPackages(false);
308 } else if (cmd.equalsIgnoreCase("-lf")) {
309 return runListPackages(true);
310 }
311 } else if (getNextArg() == null) {
312 if (cmd.equalsIgnoreCase("-p")) {
313 return displayPackageFilePath(nextArg, UserHandle.USER_SYSTEM);
314 }
315 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700316 return handleDefaultCommands(cmd);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700317 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700318 }
319 } catch (RemoteException e) {
320 pw.println("Remote exception: " + e);
321 }
322 return -1;
323 }
324
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +0100325 /**
326 * Shows module info
327 *
328 * Usage: get-moduleinfo [--all | --installed] [module-name]
329 * Example: get-moduleinfo, get-moduleinfo --all, get-moduleinfo xyz
330 */
331 private int runGetModuleInfo() {
332 final PrintWriter pw = getOutPrintWriter();
333 int flags = 0;
334
335 String opt;
336 while ((opt = getNextOption()) != null) {
337 switch (opt) {
338 case "--all":
339 flags |= PackageManager.MATCH_ALL;
340 break;
341 case "--installed":
342 break;
343 default:
344 pw.println("Error: Unknown option: " + opt);
345 return -1;
346 }
347 }
348
349 String moduleName = getNextArg();
350 try {
351 if (moduleName != null) {
352 ModuleInfo m = mInterface.getModuleInfo(moduleName, flags);
353 pw.println(m.toString() + " packageName: " + m.getPackageName());
354
355 } else {
356 List<ModuleInfo> modules = mInterface.getInstalledModules(flags);
357 for (ModuleInfo m: modules) {
358 pw.println(m.toString() + " packageName: " + m.getPackageName());
359 }
360 }
361 } catch (RemoteException e) {
362 pw.println("Failure [" + e.getClass().getName() + " - " + e.getMessage() + "]");
363 return -1;
364 }
365 return 1;
366 }
367
Patrick Baumann4b491872020-02-25 11:51:44 -0800368 private int runLogVisibility() {
369 final PrintWriter pw = getOutPrintWriter();
370 boolean enable = true;
371
372 String opt;
373 while ((opt = getNextOption()) != null) {
374 switch (opt) {
375 case "--disable":
376 enable = false;
377 break;
378 case "--enable":
379 enable = true;
380 break;
381 default:
382 pw.println("Error: Unknown option: " + opt);
383 return -1;
384 }
385 }
386
387 String packageName = getNextArg();
388 if (packageName != null) {
389 LocalServices.getService(PackageManagerInternal.class)
390 .setVisibilityLogging(packageName, enable);
391 } else {
392 getErrPrintWriter().println("Error: no package specified");
393 return -1;
394 }
395 return 1;
396 }
397
Jerry Chang30a1f132020-03-19 21:38:01 +0800398 private int runBypassStagedInstallerCheck() {
399 final PrintWriter pw = getOutPrintWriter();
400 try {
401 mInterface.getPackageInstaller()
402 .bypassNextStagedInstallerCheck(Boolean.parseBoolean(getNextArg()));
403 return 0;
404 } catch (RemoteException e) {
405 pw.println("Failure ["
406 + e.getClass().getName() + " - "
407 + e.getMessage() + "]");
408 return -1;
409 }
410 }
411
Patrick Baumanna980e142018-02-12 11:45:23 -0800412 private int uninstallSystemUpdates() {
413 final PrintWriter pw = getOutPrintWriter();
414 List<String> failedUninstalls = new LinkedList<>();
415 try {
416 final ParceledListSlice<ApplicationInfo> packages =
417 mInterface.getInstalledApplications(
418 PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
419 final IPackageInstaller installer = mInterface.getPackageInstaller();
420 List<ApplicationInfo> list = packages.getList();
421 for (ApplicationInfo info : list) {
422 if (info.isUpdatedSystemApp()) {
423 pw.println("Uninstalling updates to " + info.packageName + "...");
424 final LocalIntentReceiver receiver = new LocalIntentReceiver();
425 installer.uninstall(new VersionedPackage(info.packageName,
426 info.versionCode), null /*callerPackageName*/, 0 /* flags */,
427 receiver.getIntentSender(), 0);
428
429 final Intent result = receiver.getResult();
430 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
431 PackageInstaller.STATUS_FAILURE);
432 if (status != PackageInstaller.STATUS_SUCCESS) {
433 failedUninstalls.add(info.packageName);
434 }
435 }
436 }
437 } catch (RemoteException e) {
438 pw.println("Failure ["
439 + e.getClass().getName() + " - "
440 + e.getMessage() + "]");
441 return 0;
442 }
443 if (!failedUninstalls.isEmpty()) {
444 pw.println("Failure [Couldn't uninstall packages: "
445 + TextUtils.join(", ", failedUninstalls)
446 + "]");
447 return 0;
448 }
449 pw.println("Success");
450 return 1;
451 }
452
Narayan Kamathc5d752e2019-01-23 14:06:35 +0000453 private int runRollbackApp() {
454 final PrintWriter pw = getOutPrintWriter();
455
456 final String packageName = getNextArgRequired();
457 if (packageName == null) {
458 pw.println("Error: package name not specified");
459 return 1;
460 }
461
462 final LocalIntentReceiver receiver = new LocalIntentReceiver();
463 try {
464 IRollbackManager rm = IRollbackManager.Stub.asInterface(
465 ServiceManager.getService(Context.ROLLBACK_SERVICE));
466
467 RollbackInfo rollback = null;
468 for (RollbackInfo r : (List<RollbackInfo>) rm.getAvailableRollbacks().getList()) {
469 for (PackageRollbackInfo info : r.getPackages()) {
470 if (packageName.equals(info.getPackageName())) {
471 rollback = r;
472 break;
473 }
474 }
475 }
476
477 if (rollback == null) {
478 pw.println("No available rollbacks for: " + packageName);
479 return 1;
480 }
481
482 rm.commitRollback(rollback.getRollbackId(),
483 ParceledListSlice.<VersionedPackage>emptyList(),
484 "com.android.shell", receiver.getIntentSender());
485 } catch (RemoteException re) {
486 // Cannot happen.
487 }
488
489 final Intent result = receiver.getResult();
490 final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
491 RollbackManager.STATUS_FAILURE);
492 if (status == RollbackManager.STATUS_SUCCESS) {
493 pw.println("Success");
494 return 0;
495 } else {
496 pw.println("Failure ["
497 + result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE) + "]");
498 return 1;
499 }
500 }
501
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000502 private void setParamsSize(InstallParams params, List<String> inPaths) {
503 if (params.sessionParams.sizeBytes != -1 || STDIN_PATH.equals(inPaths.get(0))) {
504 return;
505 }
506
507 long sessionSize = 0;
508
Winson3cb56102020-04-17 16:24:57 -0700509 ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000510 for (String inPath : inPaths) {
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700511 final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");
512 if (fd == null) {
513 getErrPrintWriter().println("Error: Can't open file: " + inPath);
514 throw new IllegalArgumentException("Error: Can't open file: " + inPath);
515 }
516 try {
Winson3cb56102020-04-17 16:24:57 -0700517 ParseResult<ApkLite> apkLiteResult = ApkLiteParseUtils.parseApkLite(
518 input.reset(), fd.getFileDescriptor(), inPath, 0);
519 if (apkLiteResult.isError()) {
520 throw new IllegalArgumentException(
521 "Error: Failed to parse APK file: " + inPath + ": "
522 + apkLiteResult.getErrorMessage(),
523 apkLiteResult.getException());
524 }
525 PackageLite pkgLite = new PackageLite(null, apkLiteResult.getResult(), null, null,
526 null, null, null, null);
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000527 sessionSize += PackageHelper.calculateInstalledSize(pkgLite,
528 params.sessionParams.abiOverride, fd.getFileDescriptor());
Winson3cb56102020-04-17 16:24:57 -0700529 } catch (IOException e) {
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700530 getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath);
531 throw new IllegalArgumentException(
532 "Error: Failed to parse APK file: " + inPath, e);
533 } finally {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900534 try {
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700535 fd.close();
536 } catch (IOException e) {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900537 }
538 }
539 }
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -0800540
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000541 params.sessionParams.setSize(sessionSize);
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700542 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700543 /**
544 * Displays the package file for a package.
545 * @param pckg
546 */
547 private int displayPackageFilePath(String pckg, int userId) throws RemoteException {
Bill Lin7fd81af2019-10-04 00:31:21 +0800548 PackageInfo info = mInterface.getPackageInfo(pckg, PackageManager.MATCH_APEX, userId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700549 if (info != null && info.applicationInfo != null) {
550 final PrintWriter pw = getOutPrintWriter();
551 pw.print("package:");
552 pw.println(info.applicationInfo.sourceDir);
553 if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
554 for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
555 pw.print("package:");
556 pw.println(splitSourceDir);
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800557 }
558 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700559 return 0;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800560 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700561 return 1;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800562 }
563
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700564 private int runPath() throws RemoteException {
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000565 int userId = UserHandle.USER_SYSTEM;
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700566 String option = getNextOption();
567 if (option != null && option.equals("--user")) {
568 userId = UserHandle.parseUserArg(getNextArgRequired());
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000569 }
570
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700571 String pkg = getNextArgRequired();
572 if (pkg == null) {
573 getErrPrintWriter().println("Error: no package specified");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000574 return 1;
575 }
Todd Kennedyc3c52172019-11-26 13:20:59 -0800576 final int translatedUserId =
577 translateUserId(userId, UserHandle.USER_NULL, "runPath");
578 return displayPackageFilePath(pkg, translatedUserId);
David Sehra8777082016-05-24 15:25:23 -0700579 }
580
Todd Kennedy60459ab2015-10-30 11:32:16 -0700581 private int runList() throws RemoteException {
582 final PrintWriter pw = getOutPrintWriter();
583 final String type = getNextArg();
584 if (type == null) {
585 pw.println("Error: didn't specify type of data to list");
586 return -1;
587 }
588 switch(type) {
589 case "features":
590 return runListFeatures();
591 case "instrumentation":
592 return runListInstrumentation();
593 case "libraries":
594 return runListLibraries();
595 case "package":
596 case "packages":
597 return runListPackages(false /*showSourceDir*/);
598 case "permission-groups":
599 return runListPermissionGroups();
600 case "permissions":
601 return runListPermissions();
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100602 case "staged-sessions":
603 return runListStagedSessions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700604 case "users":
605 ServiceManager.getService("user").shellCommand(
606 getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
607 new String[] { "list" }, getShellCallback(), adoptResultReceiver());
608 return 0;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700609 }
610 pw.println("Error: unknown list type '" + type + "'");
611 return -1;
612 }
613
614 private int runListFeatures() throws RemoteException {
615 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700616 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700617
618 // sort by name
619 Collections.sort(list, new Comparator<FeatureInfo>() {
620 public int compare(FeatureInfo o1, FeatureInfo o2) {
621 if (o1.name == o2.name) return 0;
622 if (o1.name == null) return -1;
623 if (o2.name == null) return 1;
624 return o1.name.compareTo(o2.name);
625 }
626 });
627
628 final int count = (list != null) ? list.size() : 0;
629 for (int p = 0; p < count; p++) {
630 FeatureInfo fi = list.get(p);
631 pw.print("feature:");
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700632 if (fi.name != null) {
633 pw.print(fi.name);
634 if (fi.version > 0) {
635 pw.print("=");
636 pw.print(fi.version);
637 }
638 pw.println();
639 } else {
640 pw.println("reqGlEsVersion=0x"
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700641 + Integer.toHexString(fi.reqGlEsVersion));
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700642 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700643 }
644 return 0;
645 }
646
647 private int runListInstrumentation() throws RemoteException {
648 final PrintWriter pw = getOutPrintWriter();
649 boolean showSourceDir = false;
650 String targetPackage = null;
651
652 try {
653 String opt;
654 while ((opt = getNextArg()) != null) {
655 switch (opt) {
656 case "-f":
657 showSourceDir = true;
658 break;
659 default:
660 if (opt.charAt(0) != '-') {
661 targetPackage = opt;
662 } else {
663 pw.println("Error: Unknown option: " + opt);
664 return -1;
665 }
666 break;
667 }
668 }
669 } catch (RuntimeException ex) {
670 pw.println("Error: " + ex.toString());
671 return -1;
672 }
673
674 final List<InstrumentationInfo> list =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700675 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700676
677 // sort by target package
678 Collections.sort(list, new Comparator<InstrumentationInfo>() {
679 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
680 return o1.targetPackage.compareTo(o2.targetPackage);
681 }
682 });
683
684 final int count = (list != null) ? list.size() : 0;
685 for (int p = 0; p < count; p++) {
686 final InstrumentationInfo ii = list.get(p);
687 pw.print("instrumentation:");
688 if (showSourceDir) {
689 pw.print(ii.sourceDir);
690 pw.print("=");
691 }
692 final ComponentName cn = new ComponentName(ii.packageName, ii.name);
693 pw.print(cn.flattenToShortString());
694 pw.print(" (target=");
695 pw.print(ii.targetPackage);
696 pw.println(")");
697 }
698 return 0;
699 }
700
701 private int runListLibraries() throws RemoteException {
702 final PrintWriter pw = getOutPrintWriter();
703 final List<String> list = new ArrayList<String>();
704 final String[] rawList = mInterface.getSystemSharedLibraryNames();
705 for (int i = 0; i < rawList.length; i++) {
706 list.add(rawList[i]);
707 }
708
709 // sort by name
710 Collections.sort(list, new Comparator<String>() {
711 public int compare(String o1, String o2) {
712 if (o1 == o2) return 0;
713 if (o1 == null) return -1;
714 if (o2 == null) return 1;
715 return o1.compareTo(o2);
716 }
717 });
718
719 final int count = (list != null) ? list.size() : 0;
720 for (int p = 0; p < count; p++) {
721 String lib = list.get(p);
722 pw.print("library:");
723 pw.println(lib);
724 }
725 return 0;
726 }
727
728 private int runListPackages(boolean showSourceDir) throws RemoteException {
729 final PrintWriter pw = getOutPrintWriter();
730 int getFlags = 0;
731 boolean listDisabled = false, listEnabled = false;
732 boolean listSystem = false, listThirdParty = false;
733 boolean listInstaller = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700734 boolean showUid = false;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800735 boolean showVersionCode = false;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900736 boolean listApexOnly = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700737 int uid = -1;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700738 int userId = UserHandle.USER_SYSTEM;
739 try {
740 String opt;
741 while ((opt = getNextOption()) != null) {
742 switch (opt) {
743 case "-d":
744 listDisabled = true;
745 break;
746 case "-e":
747 listEnabled = true;
748 break;
Andreas Gampe1f110452018-06-04 11:47:48 -0700749 case "-a":
750 getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
751 getFlags |= PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS;
752 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700753 case "-f":
754 showSourceDir = true;
755 break;
756 case "-i":
757 listInstaller = true;
758 break;
759 case "-l":
760 // old compat
761 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700762 case "-s":
763 listSystem = true;
764 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700765 case "-U":
766 showUid = true;
767 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700768 case "-u":
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700769 getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700770 break;
771 case "-3":
772 listThirdParty = true;
773 break;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800774 case "--show-versioncode":
775 showVersionCode = true;
776 break;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900777 case "--apex-only":
778 getFlags |= PackageManager.MATCH_APEX;
779 listApexOnly = true;
780 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700781 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800782 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy60459ab2015-10-30 11:32:16 -0700783 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700784 case "--uid":
785 showUid = true;
786 uid = Integer.parseInt(getNextArgRequired());
787 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700788 default:
789 pw.println("Error: Unknown option: " + opt);
790 return -1;
791 }
792 }
793 } catch (RuntimeException ex) {
794 pw.println("Error: " + ex.toString());
795 return -1;
796 }
797
798 final String filter = getNextArg();
799
Todd Kennedy5385b512019-11-26 15:49:06 -0800800 if (userId == UserHandle.USER_ALL) {
801 getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
802 }
Todd Kennedyc3c52172019-11-26 13:20:59 -0800803 final int translatedUserId =
Todd Kennedy5385b512019-11-26 15:49:06 -0800804 translateUserId(userId, UserHandle.USER_SYSTEM, "runListPackages");
Todd Kennedy60459ab2015-10-30 11:32:16 -0700805 @SuppressWarnings("unchecked")
806 final ParceledListSlice<PackageInfo> slice =
Todd Kennedyc3c52172019-11-26 13:20:59 -0800807 mInterface.getInstalledPackages(getFlags, translatedUserId);
Todd Kennedy60459ab2015-10-30 11:32:16 -0700808 final List<PackageInfo> packages = slice.getList();
809
810 final int count = packages.size();
811 for (int p = 0; p < count; p++) {
812 final PackageInfo info = packages.get(p);
813 if (filter != null && !info.packageName.contains(filter)) {
814 continue;
815 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900816 final boolean isApex = info.isApex;
817 if (uid != -1 && !isApex && info.applicationInfo.uid != uid) {
Felipe Lemeeece9862016-06-29 11:45:03 -0700818 continue;
819 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900820
821 final boolean isSystem = !isApex &&
Todd Kennedy60459ab2015-10-30 11:32:16 -0700822 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900823 final boolean isEnabled = !isApex && info.applicationInfo.enabled;
824 if ((!listDisabled || !isEnabled) &&
825 (!listEnabled || isEnabled) &&
Todd Kennedy60459ab2015-10-30 11:32:16 -0700826 (!listSystem || isSystem) &&
Jiyong Park4f49abe2018-12-11 13:37:17 +0900827 (!listThirdParty || !isSystem) &&
828 (!listApexOnly || isApex)) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700829 pw.print("package:");
JW Wang9a722632019-09-30 10:42:30 +0800830 if (showSourceDir) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700831 pw.print(info.applicationInfo.sourceDir);
832 pw.print("=");
833 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800834 pw.print(info.packageName);
Jiyong Parkf50a2932018-12-17 13:54:40 +0900835 if (showVersionCode) {
Todd Kennedybadc69a2017-01-24 11:05:47 -0800836 pw.print(" versionCode:");
Jiyong Parkf50a2932018-12-17 13:54:40 +0900837 if (info.applicationInfo != null) {
Dario Freni788ecb12019-01-23 18:49:32 +0000838 pw.print(info.applicationInfo.longVersionCode);
Jiyong Parkf50a2932018-12-17 13:54:40 +0900839 } else {
Dario Freni788ecb12019-01-23 18:49:32 +0000840 pw.print(info.getLongVersionCode());
Jiyong Parkf50a2932018-12-17 13:54:40 +0900841 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800842 }
Mohammad Samiul Islam6b7ad942019-05-07 20:28:00 +0100843 if (listInstaller) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700844 pw.print(" installer=");
845 pw.print(mInterface.getInstallerPackageName(info.packageName));
846 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900847 if (showUid && !isApex) {
Felipe Lemeeece9862016-06-29 11:45:03 -0700848 pw.print(" uid:");
849 pw.print(info.applicationInfo.uid);
850 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700851 pw.println();
852 }
853 }
854 return 0;
855 }
856
857 private int runListPermissionGroups() throws RemoteException {
858 final PrintWriter pw = getOutPrintWriter();
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700859 final List<PermissionGroupInfo> pgs =
860 mPermissionManager.getAllPermissionGroups(0).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700861
862 final int count = pgs.size();
863 for (int p = 0; p < count ; p++) {
864 final PermissionGroupInfo pgi = pgs.get(p);
865 pw.print("permission group:");
866 pw.println(pgi.name);
867 }
868 return 0;
869 }
870
871 private int runListPermissions() throws RemoteException {
872 final PrintWriter pw = getOutPrintWriter();
873 boolean labels = false;
874 boolean groups = false;
875 boolean userOnly = false;
876 boolean summary = false;
877 boolean dangerousOnly = false;
878 String opt;
879 while ((opt = getNextOption()) != null) {
880 switch (opt) {
881 case "-d":
882 dangerousOnly = true;
883 break;
884 case "-f":
885 labels = true;
886 break;
887 case "-g":
888 groups = true;
889 break;
890 case "-s":
891 groups = true;
892 labels = true;
893 summary = true;
894 break;
895 case "-u":
896 userOnly = true;
897 break;
898 default:
899 pw.println("Error: Unknown option: " + opt);
900 return 1;
901 }
902 }
903
904 final ArrayList<String> groupList = new ArrayList<String>();
905 if (groups) {
906 final List<PermissionGroupInfo> infos =
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700907 mPermissionManager.getAllPermissionGroups(0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700908 final int count = infos.size();
909 for (int i = 0; i < count; i++) {
910 groupList.add(infos.get(i).name);
911 }
912 groupList.add(null);
913 } else {
914 final String grp = getNextArg();
915 groupList.add(grp);
916 }
917
918 if (dangerousOnly) {
919 pw.println("Dangerous Permissions:");
920 pw.println("");
921 doListPermissions(groupList, groups, labels, summary,
922 PermissionInfo.PROTECTION_DANGEROUS,
923 PermissionInfo.PROTECTION_DANGEROUS);
924 if (userOnly) {
925 pw.println("Normal Permissions:");
926 pw.println("");
927 doListPermissions(groupList, groups, labels, summary,
928 PermissionInfo.PROTECTION_NORMAL,
929 PermissionInfo.PROTECTION_NORMAL);
930 }
931 } else if (userOnly) {
932 pw.println("Dangerous and Normal Permissions:");
933 pw.println("");
934 doListPermissions(groupList, groups, labels, summary,
935 PermissionInfo.PROTECTION_NORMAL,
936 PermissionInfo.PROTECTION_DANGEROUS);
937 } else {
938 pw.println("All Permissions:");
939 pw.println("");
940 doListPermissions(groupList, groups, labels, summary,
941 -10000, 10000);
942 }
943 return 0;
944 }
945
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100946 private static class SessionDump {
947 boolean onlyParent; // Show parent sessions only
948 boolean onlyReady; // Show only staged sessions that are in ready state
949 boolean onlySessionId; // Show sessionId only
950 }
951
952 // Returns true if the provided flag is a session flag and given SessionDump was updated
953 private boolean setSessionFlag(String flag, SessionDump sessionDump) {
954 switch (flag) {
955 case "--only-parent":
956 sessionDump.onlyParent = true;
957 break;
958 case "--only-ready":
959 sessionDump.onlyReady = true;
960 break;
961 case "--only-sessionid":
962 sessionDump.onlySessionId = true;
963 break;
964 default:
965 return false;
966 }
967 return true;
968 }
969
970 private int runListStagedSessions() {
Todd Kennedy5385b512019-11-26 15:49:06 -0800971 try (IndentingPrintWriter pw = new IndentingPrintWriter(
972 getOutPrintWriter(), /* singleIndent */ " ", /* wrapLength */ 120)) {
973 final SessionDump sessionDump = new SessionDump();
974 String opt;
975 while ((opt = getNextOption()) != null) {
976 if (!setSessionFlag(opt, sessionDump)) {
977 pw.println("Error: Unknown option: " + opt);
978 return -1;
979 }
980 }
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100981
Todd Kennedy5385b512019-11-26 15:49:06 -0800982 try {
983 final List<SessionInfo> stagedSessions =
984 mInterface.getPackageInstaller().getStagedSessions().getList();
985 printSessionList(pw, stagedSessions, sessionDump);
986 } catch (RemoteException e) {
987 pw.println("Failure ["
988 + e.getClass().getName() + " - "
989 + e.getMessage() + "]");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100990 return -1;
991 }
Todd Kennedy5385b512019-11-26 15:49:06 -0800992 return 1;
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100993 }
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100994 }
995
996 private void printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions,
997 SessionDump sessionDump) {
998 final SparseArray<SessionInfo> sessionById = new SparseArray<>(stagedSessions.size());
999 for (SessionInfo session : stagedSessions) {
1000 sessionById.put(session.getSessionId(), session);
1001 }
1002 for (SessionInfo session: stagedSessions) {
1003 if (sessionDump.onlyReady && !session.isStagedSessionReady()) {
1004 continue;
1005 }
1006 if (session.getParentSessionId() != SessionInfo.INVALID_ID) {
1007 continue;
1008 }
1009 printSession(pw, session, sessionDump);
1010 if (session.isMultiPackage() && !sessionDump.onlyParent) {
1011 pw.increaseIndent();
1012 final int[] childIds = session.getChildSessionIds();
1013 for (int i = 0; i < childIds.length; i++) {
1014 final SessionInfo childSession = sessionById.get(childIds[i]);
1015 if (childSession == null) {
1016 if (sessionDump.onlySessionId) {
1017 pw.println(childIds[i]);
1018 } else {
1019 pw.println("sessionId = " + childIds[i] + "; not found");
1020 }
1021 } else {
1022 printSession(pw, childSession, sessionDump);
1023 }
1024 }
1025 pw.decreaseIndent();
1026 }
1027 }
1028 }
1029
1030 private static void printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump) {
1031 if (sessionDump.onlySessionId) {
1032 pw.println(session.getSessionId());
1033 return;
1034 }
1035 pw.println("sessionId = " + session.getSessionId()
1036 + "; appPackageName = " + session.getAppPackageName()
1037 + "; isStaged = " + session.isStaged()
1038 + "; isReady = " + session.isStagedSessionReady()
1039 + "; isApplied = " + session.isStagedSessionApplied()
1040 + "; isFailed = " + session.isStagedSessionFailed() + ";");
1041 }
1042
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001043 private Intent parseIntentAndUser() throws URISyntaxException {
1044 mTargetUser = UserHandle.USER_CURRENT;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001045 mBrief = false;
1046 mComponents = false;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001047 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
1048 @Override
1049 public boolean handleOption(String opt, ShellCommand cmd) {
1050 if ("--user".equals(opt)) {
1051 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
1052 return true;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001053 } else if ("--brief".equals(opt)) {
1054 mBrief = true;
1055 return true;
1056 } else if ("--components".equals(opt)) {
1057 mComponents = true;
1058 return true;
Ng Zhi An73971312018-09-11 21:39:14 -07001059 } else if ("--query-flags".equals(opt)) {
1060 mQueryFlags = Integer.decode(cmd.getNextArgRequired());
1061 return true;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001062 }
1063 return false;
1064 }
1065 });
1066 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1067 Binder.getCallingUid(), mTargetUser, false, false, null, null);
1068 return intent;
1069 }
1070
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001071 private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri,
1072 boolean brief, boolean components) {
1073 if (brief || components) {
1074 final ComponentName comp;
1075 if (ri.activityInfo != null) {
1076 comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
1077 } else if (ri.serviceInfo != null) {
1078 comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
1079 } else if (ri.providerInfo != null) {
1080 comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name);
1081 } else {
1082 comp = null;
1083 }
1084 if (comp != null) {
1085 if (!components) {
1086 pr.println(prefix + "priority=" + ri.priority
1087 + " preferredOrder=" + ri.preferredOrder
1088 + " match=0x" + Integer.toHexString(ri.match)
1089 + " specificIndex=" + ri.specificIndex
1090 + " isDefault=" + ri.isDefault);
1091 }
1092 pr.println(prefix + comp.flattenToShortString());
1093 return;
1094 }
1095 }
1096 ri.dump(pr, prefix);
1097 }
1098
Dianne Hackborn99878e92015-12-02 16:27:41 -08001099 private int runResolveActivity() {
1100 Intent intent;
1101 try {
1102 intent = parseIntentAndUser();
1103 } catch (URISyntaxException e) {
1104 throw new RuntimeException(e.getMessage(), e);
1105 }
1106 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001107 ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), mQueryFlags,
1108 mTargetUser);
Dianne Hackborn99878e92015-12-02 16:27:41 -08001109 PrintWriter pw = getOutPrintWriter();
1110 if (ri == null) {
1111 pw.println("No activity found");
1112 } else {
1113 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001114 printResolveInfo(pr, "", ri, mBrief, mComponents);
Dianne Hackborn99878e92015-12-02 16:27:41 -08001115 }
1116 } catch (RemoteException e) {
1117 throw new RuntimeException("Failed calling service", e);
1118 }
1119 return 0;
1120 }
1121
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001122 private int runQueryIntentActivities() {
1123 Intent intent;
1124 try {
1125 intent = parseIntentAndUser();
1126 } catch (URISyntaxException e) {
1127 throw new RuntimeException(e.getMessage(), e);
1128 }
1129 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001130 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(),
1131 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001132 PrintWriter pw = getOutPrintWriter();
1133 if (result == null || result.size() <= 0) {
1134 pw.println("No activities found");
1135 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001136 if (!mComponents) {
1137 pw.print(result.size()); pw.println(" activities found:");
1138 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1139 for (int i = 0; i < result.size(); i++) {
1140 pw.print(" Activity #"); pw.print(i); pw.println(":");
1141 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1142 }
1143 } else {
1144 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1145 for (int i = 0; i < result.size(); i++) {
1146 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1147 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001148 }
1149 }
1150 } catch (RemoteException e) {
1151 throw new RuntimeException("Failed calling service", e);
1152 }
1153 return 0;
1154 }
1155
1156 private int runQueryIntentServices() {
1157 Intent intent;
1158 try {
1159 intent = parseIntentAndUser();
1160 } catch (URISyntaxException e) {
1161 throw new RuntimeException(e.getMessage(), e);
1162 }
1163 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001164 List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(),
1165 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001166 PrintWriter pw = getOutPrintWriter();
1167 if (result == null || result.size() <= 0) {
1168 pw.println("No services found");
1169 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001170 if (!mComponents) {
1171 pw.print(result.size()); pw.println(" services found:");
1172 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1173 for (int i = 0; i < result.size(); i++) {
1174 pw.print(" Service #"); pw.print(i); pw.println(":");
1175 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1176 }
1177 } else {
1178 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1179 for (int i = 0; i < result.size(); i++) {
1180 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1181 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001182 }
1183 }
1184 } catch (RemoteException e) {
1185 throw new RuntimeException("Failed calling service", e);
1186 }
1187 return 0;
1188 }
1189
1190 private int runQueryIntentReceivers() {
1191 Intent intent;
1192 try {
1193 intent = parseIntentAndUser();
1194 } catch (URISyntaxException e) {
1195 throw new RuntimeException(e.getMessage(), e);
1196 }
1197 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001198 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(),
1199 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001200 PrintWriter pw = getOutPrintWriter();
1201 if (result == null || result.size() <= 0) {
1202 pw.println("No receivers found");
1203 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001204 if (!mComponents) {
1205 pw.print(result.size()); pw.println(" receivers found:");
1206 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1207 for (int i = 0; i < result.size(); i++) {
1208 pw.print(" Receiver #"); pw.print(i); pw.println(":");
1209 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1210 }
1211 } else {
1212 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1213 for (int i = 0; i < result.size(); i++) {
1214 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1215 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001216 }
1217 }
1218 } catch (RemoteException e) {
1219 throw new RuntimeException("Failed calling service", e);
1220 }
1221 return 0;
1222 }
1223
Alex Buynytskyyda208152019-11-11 09:34:05 -08001224 private int runStreamingInstall() throws RemoteException {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001225 final InstallParams params = makeInstallParams();
Alex Buynytskyy1ecfcec2019-12-17 12:10:41 -08001226 if (params.sessionParams.dataLoaderParams == null) {
Alex Buynytskyy476138c2019-12-20 14:41:47 -08001227 params.sessionParams.setDataLoaderParams(
Alex Buynytskyycd4d3872020-02-08 17:50:50 -08001228 PackageManagerShellCommandDataLoader.getStreamingDataLoaderParams(this));
Alex Buynytskyyda208152019-11-11 09:34:05 -08001229 }
1230 return doRunInstall(params);
1231 }
1232
Alex Buynytskyy04f73912020-02-10 08:34:18 -08001233 private int runIncrementalInstall() throws RemoteException {
1234 final InstallParams params = makeInstallParams();
1235 if (params.sessionParams.dataLoaderParams == null) {
1236 params.sessionParams.setDataLoaderParams(
1237 PackageManagerShellCommandDataLoader.getIncrementalDataLoaderParams(this));
1238 }
1239 return doRunInstall(params);
1240 }
1241
Alex Buynytskyyda208152019-11-11 09:34:05 -08001242 private int runInstall() throws RemoteException {
1243 return doRunInstall(makeInstallParams());
1244 }
1245
1246 private int doRunInstall(final InstallParams params) throws RemoteException {
1247 final PrintWriter pw = getOutPrintWriter();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001248
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001249 final boolean isStreaming = params.sessionParams.dataLoaderParams != null;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001250 final boolean isApex =
1251 (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0;
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001252
1253 ArrayList<String> args = getRemainingArgs();
1254
1255 final boolean fromStdIn = args.isEmpty() || STDIN_PATH.equals(args.get(0));
1256 final boolean hasSplits = args.size() > 1;
1257
1258 if (fromStdIn && params.sessionParams.sizeBytes == -1) {
1259 pw.println("Error: must either specify a package size or an APK file");
1260 return 1;
1261 }
1262
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001263 if (isApex && hasSplits) {
1264 pw.println("Error: can't specify SPLIT(s) for APEX");
1265 return 1;
1266 }
1267
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001268 if (!isStreaming) {
1269 if (fromStdIn && hasSplits) {
1270 pw.println("Error: can't specify SPLIT(s) along with STDIN");
1271 return 1;
1272 }
1273
1274 if (args.isEmpty()) {
1275 args.add(STDIN_PATH);
1276 } else {
1277 setParamsSize(params, args);
1278 }
Alex Buynytskyyda208152019-11-11 09:34:05 -08001279 }
1280
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001281 final int sessionId = doCreateSession(params.sessionParams,
1282 params.installerPackageName, params.userId);
1283 boolean abandonSession = true;
1284 try {
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001285 if (isStreaming) {
1286 if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex)
1287 != PackageInstaller.STATUS_SUCCESS) {
1288 return 1;
1289 }
1290 } else {
1291 if (doWriteSplits(sessionId, args, params.sessionParams.sizeBytes, isApex)
1292 != PackageInstaller.STATUS_SUCCESS) {
1293 return 1;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001294 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001295 }
1296 if (doCommitSession(sessionId, false /*logSuccess*/)
1297 != PackageInstaller.STATUS_SUCCESS) {
1298 return 1;
1299 }
1300 abandonSession = false;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01001301
Nikita Ioffe62d918c2020-01-18 01:20:42 +00001302 if (!params.sessionParams.isStaged || !params.mWaitForStagedSessionReady) {
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01001303 pw.println("Success");
1304 return 0;
1305 }
Nikita Ioffe13973e12020-03-27 12:48:16 +00001306 return doWaitForStagedSessionRead(sessionId, params.timeoutMs, pw);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001307 } finally {
1308 if (abandonSession) {
1309 try {
1310 doAbandonSession(sessionId, false /*logSuccess*/);
1311 } catch (Exception ignore) {
1312 }
1313 }
1314 }
1315 }
1316
Nikita Ioffe13973e12020-03-27 12:48:16 +00001317 private int doWaitForStagedSessionRead(int sessionId, long timeoutMs, PrintWriter pw)
1318 throws RemoteException {
1319 if (timeoutMs <= 0) {
1320 timeoutMs = DEFAULT_WAIT_MS;
1321 }
1322 PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
1323 .getSessionInfo(sessionId);
1324 if (si == null) {
1325 pw.println("Failure [Unknown session " + sessionId + "]");
1326 return 1;
1327 }
1328 if (!si.isStaged()) {
1329 pw.println("Failure [Session " + sessionId + " is not a staged session]");
1330 return 1;
1331 }
1332 long currentTime = System.currentTimeMillis();
1333 long endTime = currentTime + timeoutMs;
1334 // Using a loop instead of BroadcastReceiver since we can receive session update
1335 // broadcast only if packageInstallerName is "android". We can't always force
1336 // "android" as packageIntallerName, e.g, rollback auto implies
1337 // "-i com.android.shell".
1338 while (currentTime < endTime) {
1339 if (si != null && (si.isStagedSessionReady() || si.isStagedSessionFailed())) {
1340 break;
1341 }
1342 SystemClock.sleep(Math.min(endTime - currentTime, 100));
1343 currentTime = System.currentTimeMillis();
1344 si = mInterface.getPackageInstaller().getSessionInfo(sessionId);
1345 }
1346 if (si == null) {
1347 pw.println("Failure [failed to retrieve SessionInfo]");
1348 return 1;
1349 }
1350 if (!si.isStagedSessionReady() && !si.isStagedSessionFailed()) {
1351 pw.println("Failure [timed out after " + timeoutMs + " ms]");
1352 return 1;
1353 }
1354 if (!si.isStagedSessionReady()) {
1355 pw.println("Error [" + si.getStagedSessionErrorCode() + "] ["
1356 + si.getStagedSessionErrorMessage() + "]");
1357 return 1;
1358 }
1359 pw.println("Success. Reboot device to apply staged session");
1360 return 0;
1361 }
1362
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001363 private int runInstallAbandon() throws RemoteException {
1364 final int sessionId = Integer.parseInt(getNextArg());
1365 return doAbandonSession(sessionId, true /*logSuccess*/);
1366 }
1367
1368 private int runInstallCommit() throws RemoteException {
Nikita Ioffe13973e12020-03-27 12:48:16 +00001369 final PrintWriter pw = getOutPrintWriter();
1370 String opt;
1371 boolean waitForStagedSessionReady = true;
1372 long timeoutMs = -1;
1373 while ((opt = getNextOption()) != null) {
1374 switch (opt) {
1375 case "--wait":
1376 waitForStagedSessionReady = true;
1377 // If there is only one remaining argument, then it represents the sessionId, we
1378 // shouldn't try to parse it as timeoutMs.
1379 if (getRemainingArgsCount() > 1) {
1380 try {
1381 timeoutMs = Long.parseLong(peekNextArg());
1382 getNextArg();
1383 } catch (NumberFormatException ignore) {
1384 }
1385 }
1386 break;
1387 case "--no-wait":
1388 waitForStagedSessionReady = false;
1389 break;
1390 }
1391 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001392 final int sessionId = Integer.parseInt(getNextArg());
Nikita Ioffe13973e12020-03-27 12:48:16 +00001393 if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
1394 return 1;
1395 }
1396 final PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
1397 .getSessionInfo(sessionId);
1398 if (si == null || !si.isStaged() || !waitForStagedSessionReady) {
1399 pw.println("Success");
1400 return 0;
1401 }
1402 return doWaitForStagedSessionRead(sessionId, timeoutMs, pw);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001403 }
1404
1405 private int runInstallCreate() throws RemoteException {
1406 final PrintWriter pw = getOutPrintWriter();
1407 final InstallParams installParams = makeInstallParams();
1408 final int sessionId = doCreateSession(installParams.sessionParams,
1409 installParams.installerPackageName, installParams.userId);
1410
1411 // NOTE: adb depends on parsing this string
1412 pw.println("Success: created install session [" + sessionId + "]");
1413 return 0;
1414 }
1415
1416 private int runInstallWrite() throws RemoteException {
1417 long sizeBytes = -1;
1418
1419 String opt;
1420 while ((opt = getNextOption()) != null) {
1421 if (opt.equals("-S")) {
1422 sizeBytes = Long.parseLong(getNextArg());
1423 } else {
1424 throw new IllegalArgumentException("Unknown option: " + opt);
1425 }
1426 }
1427
1428 final int sessionId = Integer.parseInt(getNextArg());
1429 final String splitName = getNextArg();
1430 final String path = getNextArg();
1431 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
1432 }
1433
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001434 private int runInstallAddSession() throws RemoteException {
1435 final PrintWriter pw = getOutPrintWriter();
1436 final int parentSessionId = Integer.parseInt(getNextArg());
1437
1438 List<Integer> otherSessionIds = new ArrayList<>();
1439 String opt;
1440 while ((opt = getNextArg()) != null) {
1441 otherSessionIds.add(Integer.parseInt(opt));
1442 }
1443 if (otherSessionIds.size() == 0) {
1444 pw.println("Error: At least two sessions are required.");
1445 return 1;
1446 }
1447 return doInstallAddSession(parentSessionId, ArrayUtils.convertToIntArray(otherSessionIds),
1448 true /*logSuccess*/);
1449 }
1450
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001451 private int runInstallRemove() throws RemoteException {
1452 final PrintWriter pw = getOutPrintWriter();
1453
1454 final int sessionId = Integer.parseInt(getNextArg());
1455
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001456 ArrayList<String> splitNames = getRemainingArgs();
1457 if (splitNames.isEmpty()) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001458 pw.println("Error: split name not specified");
1459 return 1;
1460 }
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001461 return doRemoveSplits(sessionId, splitNames, true /*logSuccess*/);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001462 }
1463
1464 private int runInstallExisting() throws RemoteException {
1465 final PrintWriter pw = getOutPrintWriter();
Todd Kennedybef39e02019-09-20 15:14:18 -07001466 int userId = UserHandle.USER_CURRENT;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001467 int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001468 String opt;
Chandan Nathe8e463b2019-01-28 15:23:38 +00001469 boolean waitTillComplete = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001470 while ((opt = getNextOption()) != null) {
1471 switch (opt) {
1472 case "--user":
1473 userId = UserHandle.parseUserArg(getNextArgRequired());
1474 break;
1475 case "--ephemeral":
1476 case "--instant":
1477 installFlags |= PackageManager.INSTALL_INSTANT_APP;
1478 installFlags &= ~PackageManager.INSTALL_FULL_APP;
1479 break;
1480 case "--full":
1481 installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1482 installFlags |= PackageManager.INSTALL_FULL_APP;
1483 break;
Chandan Nathe8e463b2019-01-28 15:23:38 +00001484 case "--wait":
1485 waitTillComplete = true;
1486 break;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001487 case "--restrict-permissions":
1488 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1489 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001490 default:
1491 pw.println("Error: Unknown option: " + opt);
1492 return 1;
1493 }
1494 }
1495
1496 final String packageName = getNextArg();
1497 if (packageName == null) {
1498 pw.println("Error: package name not specified");
1499 return 1;
1500 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08001501 final int translatedUserId =
1502 translateUserId(userId, UserHandle.USER_NULL, "runInstallExisting");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001503
Chandan Nathe8e463b2019-01-28 15:23:38 +00001504 int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001505 try {
Chandan Nathe8e463b2019-01-28 15:23:38 +00001506 if (waitTillComplete) {
1507 final LocalIntentReceiver receiver = new LocalIntentReceiver();
1508 final IPackageInstaller installer = mInterface.getPackageInstaller();
Todd Kennedyc3c52172019-11-26 13:20:59 -08001509 pw.println("Installing package " + packageName + " for user: " + translatedUserId);
Chandan Nathe8e463b2019-01-28 15:23:38 +00001510 installer.installExistingPackage(packageName, installFlags, installReason,
Todd Kennedyc3c52172019-11-26 13:20:59 -08001511 receiver.getIntentSender(), translatedUserId, null);
Chandan Nathe8e463b2019-01-28 15:23:38 +00001512 final Intent result = receiver.getResult();
1513 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1514 PackageInstaller.STATUS_FAILURE);
1515 pw.println("Received intent for package install");
1516 return status == PackageInstaller.STATUS_SUCCESS ? 0 : 1;
1517 }
1518
Todd Kennedyc3c52172019-11-26 13:20:59 -08001519 final int res = mInterface.installExistingPackageAsUser(packageName, translatedUserId,
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001520 installFlags, installReason, null);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001521 if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
1522 throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1523 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08001524 pw.println("Package " + packageName + " installed for user: " + translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001525 return 0;
1526 } catch (RemoteException | NameNotFoundException e) {
1527 pw.println(e.toString());
1528 return 1;
1529 }
1530 }
1531
1532 private int runSetInstallLocation() throws RemoteException {
1533 int loc;
1534
1535 String arg = getNextArg();
1536 if (arg == null) {
1537 getErrPrintWriter().println("Error: no install location specified.");
1538 return 1;
1539 }
1540 try {
1541 loc = Integer.parseInt(arg);
1542 } catch (NumberFormatException e) {
1543 getErrPrintWriter().println("Error: install location has to be a number.");
1544 return 1;
1545 }
1546 if (!mInterface.setInstallLocation(loc)) {
1547 getErrPrintWriter().println("Error: install location has to be a number.");
1548 return 1;
1549 }
1550 return 0;
1551 }
1552
1553 private int runGetInstallLocation() throws RemoteException {
1554 int loc = mInterface.getInstallLocation();
1555 String locStr = "invalid";
1556 if (loc == PackageHelper.APP_INSTALL_AUTO) {
1557 locStr = "auto";
1558 } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
1559 locStr = "internal";
1560 } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
1561 locStr = "external";
1562 }
1563 getOutPrintWriter().println(loc + "[" + locStr + "]");
1564 return 0;
1565 }
1566
1567 public int runMovePackage() throws RemoteException {
1568 final String packageName = getNextArg();
1569 if (packageName == null) {
1570 getErrPrintWriter().println("Error: package name not specified");
1571 return 1;
1572 }
1573 String volumeUuid = getNextArg();
1574 if ("internal".equals(volumeUuid)) {
1575 volumeUuid = null;
1576 }
1577
1578 final int moveId = mInterface.movePackage(packageName, volumeUuid);
1579
1580 int status = mInterface.getMoveStatus(moveId);
1581 while (!PackageManager.isMoveStatusFinished(status)) {
1582 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1583 status = mInterface.getMoveStatus(moveId);
1584 }
1585
1586 if (status == PackageManager.MOVE_SUCCEEDED) {
1587 getOutPrintWriter().println("Success");
1588 return 0;
1589 } else {
1590 getErrPrintWriter().println("Failure [" + status + "]");
1591 return 1;
1592 }
1593 }
1594
1595 public int runMovePrimaryStorage() throws RemoteException {
1596 String volumeUuid = getNextArg();
1597 if ("internal".equals(volumeUuid)) {
1598 volumeUuid = null;
1599 }
1600
1601 final int moveId = mInterface.movePrimaryStorage(volumeUuid);
1602
1603 int status = mInterface.getMoveStatus(moveId);
1604 while (!PackageManager.isMoveStatusFinished(status)) {
1605 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1606 status = mInterface.getMoveStatus(moveId);
1607 }
1608
1609 if (status == PackageManager.MOVE_SUCCEEDED) {
1610 getOutPrintWriter().println("Success");
1611 return 0;
1612 } else {
1613 getErrPrintWriter().println("Failure [" + status + "]");
1614 return 1;
1615 }
1616 }
1617
1618 private int runCompile() throws RemoteException {
1619 final PrintWriter pw = getOutPrintWriter();
1620 boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
1621 boolean forceCompilation = false;
1622 boolean allPackages = false;
1623 boolean clearProfileData = false;
1624 String compilerFilter = null;
1625 String compilationReason = null;
1626 String checkProfilesRaw = null;
1627 boolean secondaryDex = false;
1628 String split = null;
Eric Holka1485f62019-01-07 13:58:25 -08001629 boolean compileLayouts = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001630
1631 String opt;
1632 while ((opt = getNextOption()) != null) {
1633 switch (opt) {
1634 case "-a":
1635 allPackages = true;
1636 break;
1637 case "-c":
1638 clearProfileData = true;
1639 break;
1640 case "-f":
1641 forceCompilation = true;
1642 break;
1643 case "-m":
1644 compilerFilter = getNextArgRequired();
1645 break;
1646 case "-r":
1647 compilationReason = getNextArgRequired();
1648 break;
Eric Holka1485f62019-01-07 13:58:25 -08001649 case "--compile-layouts":
1650 compileLayouts = true;
1651 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001652 case "--check-prof":
1653 checkProfilesRaw = getNextArgRequired();
1654 break;
1655 case "--reset":
1656 forceCompilation = true;
1657 clearProfileData = true;
1658 compilationReason = "install";
1659 break;
1660 case "--secondary-dex":
1661 secondaryDex = true;
1662 break;
1663 case "--split":
1664 split = getNextArgRequired();
1665 break;
1666 default:
1667 pw.println("Error: Unknown option: " + opt);
1668 return 1;
1669 }
1670 }
1671
1672 if (checkProfilesRaw != null) {
1673 if ("true".equals(checkProfilesRaw)) {
1674 checkProfiles = true;
1675 } else if ("false".equals(checkProfilesRaw)) {
1676 checkProfiles = false;
1677 } else {
1678 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
1679 return 1;
1680 }
1681 }
1682
Eric Holka1485f62019-01-07 13:58:25 -08001683 final boolean compilerFilterGiven = compilerFilter != null;
1684 final boolean compilationReasonGiven = compilationReason != null;
1685 // Make sure exactly one of -m, -r, or --compile-layouts is given.
1686 if ((!compilerFilterGiven && !compilationReasonGiven && !compileLayouts)
1687 || (!compilerFilterGiven && compilationReasonGiven && compileLayouts)
1688 || (compilerFilterGiven && !compilationReasonGiven && compileLayouts)
1689 || (compilerFilterGiven && compilationReasonGiven && !compileLayouts)
1690 || (compilerFilterGiven && compilationReasonGiven && compileLayouts)) {
1691 pw.println("Must specify exactly one of compilation filter (\"-m\"), compilation " +
1692 "reason (\"-r\"), or compile layouts (\"--compile-layouts\")");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001693 return 1;
1694 }
1695
1696 if (allPackages && split != null) {
1697 pw.println("-a cannot be specified together with --split");
1698 return 1;
1699 }
1700
1701 if (secondaryDex && split != null) {
1702 pw.println("--secondary-dex cannot be specified together with --split");
1703 return 1;
1704 }
1705
Eric Holka1485f62019-01-07 13:58:25 -08001706 String targetCompilerFilter = null;
1707 if (compilerFilterGiven) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001708 if (!DexFile.isValidCompilerFilter(compilerFilter)) {
1709 pw.println("Error: \"" + compilerFilter +
1710 "\" is not a valid compilation filter.");
1711 return 1;
1712 }
1713 targetCompilerFilter = compilerFilter;
Eric Holka1485f62019-01-07 13:58:25 -08001714 }
1715 if (compilationReasonGiven) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001716 int reason = -1;
1717 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
1718 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
1719 compilationReason)) {
1720 reason = i;
1721 break;
1722 }
1723 }
1724 if (reason == -1) {
1725 pw.println("Error: Unknown compilation reason: " + compilationReason);
1726 return 1;
1727 }
1728 targetCompilerFilter =
1729 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
1730 }
1731
1732
1733 List<String> packageNames = null;
1734 if (allPackages) {
1735 packageNames = mInterface.getAllPackages();
1736 } else {
1737 String packageName = getNextArg();
1738 if (packageName == null) {
1739 pw.println("Error: package name not specified");
1740 return 1;
1741 }
1742 packageNames = Collections.singletonList(packageName);
1743 }
1744
1745 List<String> failedPackages = new ArrayList<>();
Andreas Gampecbd08d42017-11-20 17:03:17 -08001746 int index = 0;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001747 for (String packageName : packageNames) {
1748 if (clearProfileData) {
1749 mInterface.clearApplicationProfileData(packageName);
1750 }
1751
Andreas Gampecbd08d42017-11-20 17:03:17 -08001752 if (allPackages) {
1753 pw.println(++index + "/" + packageNames.size() + ": " + packageName);
1754 pw.flush();
1755 }
1756
Eric Holka1485f62019-01-07 13:58:25 -08001757 boolean result = true;
1758 if (compileLayouts) {
1759 PackageManagerInternal internal = LocalServices.getService(
1760 PackageManagerInternal.class);
1761 result = internal.compileLayouts(packageName);
1762 } else {
1763 result = secondaryDex
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001764 ? mInterface.performDexOptSecondary(packageName,
1765 targetCompilerFilter, forceCompilation)
1766 : mInterface.performDexOptMode(packageName,
1767 checkProfiles, targetCompilerFilter, forceCompilation,
1768 true /* bootComplete */, split);
Eric Holka1485f62019-01-07 13:58:25 -08001769 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001770 if (!result) {
1771 failedPackages.add(packageName);
1772 }
1773 }
1774
1775 if (failedPackages.isEmpty()) {
1776 pw.println("Success");
1777 return 0;
1778 } else if (failedPackages.size() == 1) {
1779 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
1780 return 1;
1781 } else {
1782 pw.print("Failure: the following packages could not be compiled: ");
1783 boolean is_first = true;
1784 for (String packageName : failedPackages) {
1785 if (is_first) {
1786 is_first = false;
1787 } else {
1788 pw.print(", ");
1789 }
1790 pw.print(packageName);
1791 }
1792 pw.println();
1793 return 1;
1794 }
1795 }
1796
1797 private int runreconcileSecondaryDexFiles() throws RemoteException {
1798 String packageName = getNextArg();
1799 mInterface.reconcileSecondaryDexFiles(packageName);
1800 return 0;
1801 }
1802
1803 public int runForceDexOpt() throws RemoteException {
1804 mInterface.forceDexOpt(getNextArgRequired());
1805 return 0;
1806 }
1807
1808 private int runDexoptJob() throws RemoteException {
Arthur Eubanks09dd1ec2017-09-15 09:28:51 -07001809 String arg;
1810 List<String> packageNames = new ArrayList<>();
1811 while ((arg = getNextArg()) != null) {
1812 packageNames.add(arg);
1813 }
1814 boolean result = mInterface.runBackgroundDexoptJob(packageNames.isEmpty() ? null :
1815 packageNames);
Andreas Gampefa8b57d2018-08-31 15:47:01 -07001816 getOutPrintWriter().println(result ? "Success" : "Failure");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001817 return result ? 0 : -1;
1818 }
1819
1820 private int runDumpProfiles() throws RemoteException {
1821 String packageName = getNextArg();
1822 mInterface.dumpProfiles(packageName);
1823 return 0;
1824 }
1825
Calin Juravle21216c62018-05-04 17:35:29 -07001826 private int runSnapshotProfile() throws RemoteException {
1827 PrintWriter pw = getOutPrintWriter();
1828
1829 // Parse the arguments
1830 final String packageName = getNextArg();
1831 final boolean isBootImage = "android".equals(packageName);
1832
1833 String codePath = null;
1834 String opt;
1835 while ((opt = getNextArg()) != null) {
1836 switch (opt) {
1837 case "--code-path":
1838 if (isBootImage) {
1839 pw.write("--code-path cannot be used for the boot image.");
1840 return -1;
1841 }
1842 codePath = getNextArg();
1843 break;
1844 default:
1845 pw.write("Unknown arg: " + opt);
1846 return -1;
1847 }
1848 }
1849
1850 // If no code path was explicitly requested, select the base code path.
1851 String baseCodePath = null;
1852 if (!isBootImage) {
1853 PackageInfo packageInfo = mInterface.getPackageInfo(packageName, /* flags */ 0,
1854 /* userId */0);
1855 if (packageInfo == null) {
1856 pw.write("Package not found " + packageName);
1857 return -1;
1858 }
1859 baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
1860 if (codePath == null) {
1861 codePath = baseCodePath;
1862 }
1863 }
1864
1865 // Create the profile snapshot.
1866 final SnapshotRuntimeProfileCallback callback = new SnapshotRuntimeProfileCallback();
1867 // The calling package is needed to debug permission access.
1868 final String callingPackage = (Binder.getCallingUid() == Process.ROOT_UID)
1869 ? "root" : "com.android.shell";
1870 final int profileType = isBootImage
1871 ? ArtManager.PROFILE_BOOT_IMAGE : ArtManager.PROFILE_APPS;
1872 if (!mInterface.getArtManager().isRuntimeProfilingEnabled(profileType, callingPackage)) {
1873 pw.println("Error: Runtime profiling is not enabled");
1874 return -1;
1875 }
1876 mInterface.getArtManager().snapshotRuntimeProfile(profileType, packageName,
1877 codePath, callback, callingPackage);
1878 if (!callback.waitTillDone()) {
1879 pw.println("Error: callback not called");
1880 return callback.mErrCode;
1881 }
1882
1883 // Copy the snapshot profile to the output profile file.
1884 try (InputStream inStream = new AutoCloseInputStream(callback.mProfileReadFd)) {
1885 final String outputFileSuffix = isBootImage || Objects.equals(baseCodePath, codePath)
1886 ? "" : ("-" + new File(codePath).getName());
1887 final String outputProfilePath =
1888 ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + packageName + outputFileSuffix + ".prof";
1889 try (OutputStream outStream = new FileOutputStream(outputProfilePath)) {
1890 Streams.copy(inStream, outStream);
1891 }
Calin Juravlebdd94d92018-05-17 01:23:15 -07001892 // Give read permissions to the other group.
1893 Os.chmod(outputProfilePath, /*mode*/ 0644 );
1894 } catch (IOException | ErrnoException e) {
Calin Juravle21216c62018-05-04 17:35:29 -07001895 pw.println("Error when reading the profile fd: " + e.getMessage());
1896 e.printStackTrace(pw);
1897 return -1;
1898 }
1899 return 0;
1900 }
1901
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001902 private ArrayList<String> getRemainingArgs() {
1903 ArrayList<String> args = new ArrayList<>();
1904 String arg;
1905 while ((arg = getNextArg()) != null) {
1906 args.add(arg);
1907 }
1908 return args;
1909 }
1910
Calin Juravle21216c62018-05-04 17:35:29 -07001911 private static class SnapshotRuntimeProfileCallback
1912 extends ISnapshotRuntimeProfileCallback.Stub {
1913 private boolean mSuccess = false;
1914 private int mErrCode = -1;
1915 private ParcelFileDescriptor mProfileReadFd = null;
1916 private CountDownLatch mDoneSignal = new CountDownLatch(1);
1917
1918 @Override
1919 public void onSuccess(ParcelFileDescriptor profileReadFd) {
1920 mSuccess = true;
1921 try {
1922 // We need to dup the descriptor. We are in the same process as system server
1923 // and we will be receiving the same object (which will be closed on the
1924 // server side).
1925 mProfileReadFd = profileReadFd.dup();
1926 } catch (IOException e) {
1927 e.printStackTrace();
1928 }
1929 mDoneSignal.countDown();
1930 }
1931
1932 @Override
1933 public void onError(int errCode) {
1934 mSuccess = false;
1935 mErrCode = errCode;
1936 mDoneSignal.countDown();
1937 }
1938
1939 boolean waitTillDone() {
1940 boolean done = false;
1941 try {
1942 // The time-out is an arbitrary large value. Since this is a local call the result
1943 // will come very fast.
1944 done = mDoneSignal.await(10000000, TimeUnit.MILLISECONDS);
1945 } catch (InterruptedException ignored) {
1946 }
1947 return done && mSuccess;
1948 }
1949 }
1950
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001951 private int runUninstall() throws RemoteException {
1952 final PrintWriter pw = getOutPrintWriter();
1953 int flags = 0;
1954 int userId = UserHandle.USER_ALL;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001955 long versionCode = PackageManager.VERSION_CODE_HIGHEST;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001956
1957 String opt;
1958 while ((opt = getNextOption()) != null) {
1959 switch (opt) {
1960 case "-k":
1961 flags |= PackageManager.DELETE_KEEP_DATA;
1962 break;
1963 case "--user":
1964 userId = UserHandle.parseUserArg(getNextArgRequired());
1965 break;
1966 case "--versionCode":
Dianne Hackborn3accca02013-09-20 09:32:11 -07001967 versionCode = Long.parseLong(getNextArgRequired());
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001968 break;
1969 default:
1970 pw.println("Error: Unknown option: " + opt);
1971 return 1;
1972 }
1973 }
1974
1975 final String packageName = getNextArg();
1976 if (packageName == null) {
1977 pw.println("Error: package name not specified");
1978 return 1;
1979 }
1980
1981 // if a split is specified, just remove it and not the whole package
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001982 ArrayList<String> splitNames = getRemainingArgs();
1983 if (!splitNames.isEmpty()) {
1984 return runRemoveSplits(packageName, splitNames);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001985 }
1986
Todd Kennedyc3c52172019-11-26 13:20:59 -08001987 if (userId == UserHandle.USER_ALL) {
1988 flags |= PackageManager.DELETE_ALL_USERS;
1989 }
1990 final int translatedUserId =
1991 translateUserId(userId, UserHandle.USER_SYSTEM, "runUninstall");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001992 final LocalIntentReceiver receiver = new LocalIntentReceiver();
Todd Kennedyc3c52172019-11-26 13:20:59 -08001993 final PackageManagerInternal internal =
1994 LocalServices.getService(PackageManagerInternal.class);
Nikita Ioffef012a222019-03-05 22:37:55 +00001995
1996 if (internal.isApexPackage(packageName)) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08001997 internal.uninstallApex(
Gavin Corkery4fd10882019-11-28 15:37:51 +00001998 packageName, versionCode, translatedUserId, receiver.getIntentSender(), flags);
Todd Kennedy2678a992019-11-27 10:21:23 -08001999 } else {
2000 if ((flags & PackageManager.DELETE_ALL_USERS) == 0) {
2001 final PackageInfo info = mInterface.getPackageInfo(packageName,
2002 PackageManager.MATCH_STATIC_SHARED_LIBRARIES, translatedUserId);
2003 if (info == null) {
2004 pw.println("Failure [not installed for " + translatedUserId + "]");
2005 return 1;
2006 }
2007 final boolean isSystem =
2008 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
2009 // If we are being asked to delete a system app for just one
2010 // user set flag so it disables rather than reverting to system
2011 // version of the app.
2012 if (isSystem) {
2013 flags |= PackageManager.DELETE_SYSTEM_APP;
2014 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002015 }
Nikita Ioffef012a222019-03-05 22:37:55 +00002016 mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
2017 versionCode), null /*callerPackageName*/, flags,
Todd Kennedyc3c52172019-11-26 13:20:59 -08002018 receiver.getIntentSender(), translatedUserId);
Nikita Ioffef012a222019-03-05 22:37:55 +00002019 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002020
2021 final Intent result = receiver.getResult();
2022 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
2023 PackageInstaller.STATUS_FAILURE);
2024 if (status == PackageInstaller.STATUS_SUCCESS) {
2025 pw.println("Success");
2026 return 0;
2027 } else {
2028 pw.println("Failure ["
2029 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
2030 return 1;
2031 }
2032 }
2033
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00002034 private int runRemoveSplits(String packageName, Collection<String> splitNames)
2035 throws RemoteException {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002036 final PrintWriter pw = getOutPrintWriter();
2037 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
2038 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
2039 sessionParams.appPackageName = packageName;
2040 final int sessionId =
2041 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
2042 boolean abandonSession = true;
2043 try {
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00002044 if (doRemoveSplits(sessionId, splitNames, false /*logSuccess*/)
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002045 != PackageInstaller.STATUS_SUCCESS) {
2046 return 1;
2047 }
2048 if (doCommitSession(sessionId, false /*logSuccess*/)
2049 != PackageInstaller.STATUS_SUCCESS) {
2050 return 1;
2051 }
2052 abandonSession = false;
2053 pw.println("Success");
2054 return 0;
2055 } finally {
2056 if (abandonSession) {
2057 try {
2058 doAbandonSession(sessionId, false /*logSuccess*/);
2059 } catch (Exception ignore) {
2060 }
2061 }
2062 }
2063 }
2064
2065 static class ClearDataObserver extends IPackageDataObserver.Stub {
2066 boolean finished;
2067 boolean result;
2068
2069 @Override
2070 public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
2071 synchronized (this) {
2072 finished = true;
2073 result = succeeded;
2074 notifyAll();
2075 }
2076 }
2077 }
2078
2079 private int runClear() throws RemoteException {
2080 int userId = UserHandle.USER_SYSTEM;
2081 String option = getNextOption();
2082 if (option != null && option.equals("--user")) {
2083 userId = UserHandle.parseUserArg(getNextArgRequired());
2084 }
2085
2086 String pkg = getNextArg();
2087 if (pkg == null) {
2088 getErrPrintWriter().println("Error: no package specified");
2089 return 1;
2090 }
2091
Todd Kennedy5385b512019-11-26 15:49:06 -08002092 final int translatedUserId =
2093 translateUserId(userId, UserHandle.USER_NULL, "runClear");
2094 final ClearDataObserver obs = new ClearDataObserver();
2095 ActivityManager.getService().clearApplicationUserData(pkg, false, obs, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002096 synchronized (obs) {
2097 while (!obs.finished) {
2098 try {
2099 obs.wait();
2100 } catch (InterruptedException e) {
2101 }
2102 }
2103 }
2104
2105 if (obs.result) {
2106 getOutPrintWriter().println("Success");
2107 return 0;
2108 } else {
2109 getErrPrintWriter().println("Failed");
2110 return 1;
2111 }
2112 }
2113
2114 private static String enabledSettingToString(int state) {
2115 switch (state) {
2116 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
2117 return "default";
2118 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
2119 return "enabled";
2120 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
2121 return "disabled";
2122 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
2123 return "disabled-user";
2124 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
2125 return "disabled-until-used";
2126 }
2127 return "unknown";
2128 }
2129
2130 private int runSetEnabledSetting(int state) throws RemoteException {
2131 int userId = UserHandle.USER_SYSTEM;
2132 String option = getNextOption();
2133 if (option != null && option.equals("--user")) {
2134 userId = UserHandle.parseUserArg(getNextArgRequired());
2135 }
2136
Todd Kennedyc3c52172019-11-26 13:20:59 -08002137 final String pkg = getNextArg();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002138 if (pkg == null) {
2139 getErrPrintWriter().println("Error: no package or component specified");
2140 return 1;
2141 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002142 final int translatedUserId =
2143 translateUserId(userId, UserHandle.USER_NULL, "runSetEnabledSetting");
2144 final ComponentName cn = ComponentName.unflattenFromString(pkg);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002145 if (cn == null) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002146 mInterface.setApplicationEnabledSetting(pkg, state, 0, translatedUserId,
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002147 "shell:" + android.os.Process.myUid());
2148 getOutPrintWriter().println("Package " + pkg + " new state: "
2149 + enabledSettingToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002150 mInterface.getApplicationEnabledSetting(pkg, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002151 return 0;
2152 } else {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002153 mInterface.setComponentEnabledSetting(cn, state, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002154 getOutPrintWriter().println("Component " + cn.toShortString() + " new state: "
2155 + enabledSettingToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002156 mInterface.getComponentEnabledSetting(cn, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002157 return 0;
2158 }
2159 }
2160
2161 private int runSetHiddenSetting(boolean state) throws RemoteException {
2162 int userId = UserHandle.USER_SYSTEM;
2163 String option = getNextOption();
2164 if (option != null && option.equals("--user")) {
2165 userId = UserHandle.parseUserArg(getNextArgRequired());
2166 }
2167
2168 String pkg = getNextArg();
2169 if (pkg == null) {
2170 getErrPrintWriter().println("Error: no package or component specified");
2171 return 1;
2172 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002173 final int translatedUserId =
2174 translateUserId(userId, UserHandle.USER_NULL, "runSetHiddenSetting");
2175 mInterface.setApplicationHiddenSettingAsUser(pkg, state, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002176 getOutPrintWriter().println("Package " + pkg + " new hidden state: "
Todd Kennedyc3c52172019-11-26 13:20:59 -08002177 + mInterface.getApplicationHiddenSettingAsUser(pkg, translatedUserId));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002178 return 0;
2179 }
2180
2181 private int runSuspend(boolean suspendedState) {
2182 final PrintWriter pw = getOutPrintWriter();
2183 int userId = UserHandle.USER_SYSTEM;
Suprabh Shukla3c3af142018-03-30 00:28:37 -07002184 String dialogMessage = null;
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002185 final PersistableBundle appExtras = new PersistableBundle();
2186 final PersistableBundle launcherExtras = new PersistableBundle();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002187 String opt;
2188 while ((opt = getNextOption()) != null) {
2189 switch (opt) {
2190 case "--user":
2191 userId = UserHandle.parseUserArg(getNextArgRequired());
2192 break;
Suprabh Shukla3c3af142018-03-30 00:28:37 -07002193 case "--dialogMessage":
2194 dialogMessage = getNextArgRequired();
2195 break;
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002196 case "--ael":
2197 case "--aes":
2198 case "--aed":
2199 case "--lel":
2200 case "--les":
2201 case "--led":
2202 final String key = getNextArgRequired();
2203 final String val = getNextArgRequired();
2204 if (!suspendedState) {
2205 break;
2206 }
2207 final PersistableBundle bundleToInsert =
2208 opt.startsWith("--a") ? appExtras : launcherExtras;
2209 switch (opt.charAt(4)) {
2210 case 'l':
2211 bundleToInsert.putLong(key, Long.valueOf(val));
2212 break;
2213 case 'd':
2214 bundleToInsert.putDouble(key, Double.valueOf(val));
2215 break;
2216 case 's':
2217 bundleToInsert.putString(key, val);
2218 break;
2219 }
2220 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002221 default:
2222 pw.println("Error: Unknown option: " + opt);
2223 return 1;
2224 }
2225 }
2226
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002227 final String packageName = getNextArg();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002228 if (packageName == null) {
2229 pw.println("Error: package name not specified");
2230 return 1;
2231 }
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002232 final String callingPackage =
2233 (Binder.getCallingUid() == Process.ROOT_UID) ? "root" : "com.android.shell";
Suprabh Shukla389cb6f2018-10-01 18:20:39 -07002234
2235 final SuspendDialogInfo info;
2236 if (!TextUtils.isEmpty(dialogMessage)) {
2237 info = new SuspendDialogInfo.Builder()
2238 .setMessage(dialogMessage)
2239 .build();
2240 } else {
2241 info = null;
2242 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002243 try {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002244 final int translatedUserId =
2245 translateUserId(userId, UserHandle.USER_NULL, "runSuspend");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002246 mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
Suprabh Shuklad3278442019-08-27 15:58:03 -07002247 ((appExtras.size() > 0) ? appExtras : null),
2248 ((launcherExtras.size() > 0) ? launcherExtras : null),
Todd Kennedyc3c52172019-11-26 13:20:59 -08002249 info, callingPackage, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002250 pw.println("Package " + packageName + " new suspended state: "
Todd Kennedyc3c52172019-11-26 13:20:59 -08002251 + mInterface.isPackageSuspendedForUser(packageName, translatedUserId));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002252 return 0;
2253 } catch (RemoteException | IllegalArgumentException e) {
2254 pw.println(e.toString());
2255 return 1;
2256 }
2257 }
2258
2259 private int runGrantRevokePermission(boolean grant) throws RemoteException {
2260 int userId = UserHandle.USER_SYSTEM;
2261
2262 String opt = null;
2263 while ((opt = getNextOption()) != null) {
2264 if (opt.equals("--user")) {
2265 userId = UserHandle.parseUserArg(getNextArgRequired());
2266 }
2267 }
2268
2269 String pkg = getNextArg();
2270 if (pkg == null) {
2271 getErrPrintWriter().println("Error: no package specified");
2272 return 1;
2273 }
2274 String perm = getNextArg();
2275 if (perm == null) {
2276 getErrPrintWriter().println("Error: no permission specified");
2277 return 1;
2278 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002279 final int translatedUserId =
2280 translateUserId(userId, UserHandle.USER_NULL, "runGrantRevokePermission");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002281 if (grant) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002282 mPermissionManager.grantRuntimePermission(pkg, perm, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002283 } else {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002284 mPermissionManager.revokeRuntimePermission(pkg, perm, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002285 }
2286 return 0;
2287 }
2288
2289 private int runResetPermissions() throws RemoteException {
Todd Kennedyc971a452019-07-08 16:04:52 -07002290 mPermissionManager.resetRuntimePermissions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002291 return 0;
2292 }
2293
2294 private int runSetPermissionEnforced() throws RemoteException {
2295 final String permission = getNextArg();
2296 if (permission == null) {
2297 getErrPrintWriter().println("Error: no permission specified");
2298 return 1;
2299 }
2300 final String enforcedRaw = getNextArg();
2301 if (enforcedRaw == null) {
2302 getErrPrintWriter().println("Error: no enforcement specified");
2303 return 1;
2304 }
Todd Kennedyc5b0e862019-07-16 09:47:58 -07002305 mPermissionManager.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002306 return 0;
2307 }
2308
Jiyong Park002fdbd2017-02-13 20:50:31 +09002309 private boolean isVendorApp(String pkg) {
2310 try {
2311 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
2312 return info != null && info.applicationInfo.isVendor();
2313 } catch (RemoteException e) {
2314 return false;
2315 }
2316 }
2317
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002318 private boolean isProductApp(String pkg) {
2319 try {
2320 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
2321 return info != null && info.applicationInfo.isProduct();
2322 } catch (RemoteException e) {
2323 return false;
2324 }
2325 }
2326
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002327 private boolean isSystemExtApp(String pkg) {
Dario Freni2bef1762018-06-01 14:02:08 +01002328 try {
2329 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002330 return info != null && info.applicationInfo.isSystemExt();
Dario Freni2bef1762018-06-01 14:02:08 +01002331 } catch (RemoteException e) {
2332 return false;
2333 }
2334 }
2335
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002336 private int runGetPrivappPermissions() {
2337 final String pkg = getNextArg();
2338 if (pkg == null) {
2339 getErrPrintWriter().println("Error: no package specified.");
2340 return 1;
2341 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002342
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002343 ArraySet<String> privAppPermissions = null;
2344 if (isVendorApp(pkg)) {
2345 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
2346 } else if (isProductApp(pkg)) {
2347 privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002348 } else if (isSystemExtApp(pkg)) {
Dario Freni2bef1762018-06-01 14:02:08 +01002349 privAppPermissions = SystemConfig.getInstance()
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002350 .getSystemExtPrivAppPermissions(pkg);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002351 } else {
2352 privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
2353 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002354
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002355 getOutPrintWriter().println(privAppPermissions == null
2356 ? "{}" : privAppPermissions.toString());
2357 return 0;
2358 }
2359
2360 private int runGetPrivappDenyPermissions() {
2361 final String pkg = getNextArg();
2362 if (pkg == null) {
2363 getErrPrintWriter().println("Error: no package specified.");
2364 return 1;
2365 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002366
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002367 ArraySet<String> privAppPermissions = null;
2368 if (isVendorApp(pkg)) {
2369 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
2370 } else if (isProductApp(pkg)) {
2371 privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002372 } else if (isSystemExtApp(pkg)) {
Dario Freni2bef1762018-06-01 14:02:08 +01002373 privAppPermissions = SystemConfig.getInstance()
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002374 .getSystemExtPrivAppDenyPermissions(pkg);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002375 } else {
2376 privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
2377 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002378
2379 getOutPrintWriter().println(privAppPermissions == null
2380 ? "{}" : privAppPermissions.toString());
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002381 return 0;
2382 }
2383
2384 private int runGetOemPermissions() {
2385 final String pkg = getNextArg();
2386 if (pkg == null) {
2387 getErrPrintWriter().println("Error: no package specified.");
2388 return 1;
2389 }
2390 final Map<String, Boolean> oemPermissions = SystemConfig.getInstance()
2391 .getOemPermissions(pkg);
2392 if (oemPermissions == null || oemPermissions.isEmpty()) {
2393 getOutPrintWriter().println("{}");
2394 } else {
2395 oemPermissions.forEach((permission, granted) ->
2396 getOutPrintWriter().println(permission + " granted:" + granted)
2397 );
2398 }
2399 return 0;
2400 }
2401
2402 private String linkStateToString(int state) {
2403 switch (state) {
2404 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
2405 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
2406 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
2407 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
2408 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
2409 }
2410 return "Unknown link state: " + state;
2411 }
2412
2413 // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
2414 private int runSetAppLink() throws RemoteException {
2415 int userId = UserHandle.USER_SYSTEM;
2416
2417 String opt;
2418 while ((opt = getNextOption()) != null) {
2419 if (opt.equals("--user")) {
2420 userId = UserHandle.parseUserArg(getNextArgRequired());
2421 } else {
2422 getErrPrintWriter().println("Error: unknown option: " + opt);
2423 return 1;
2424 }
2425 }
2426
2427 // Package name to act on; required
2428 final String pkg = getNextArg();
2429 if (pkg == null) {
2430 getErrPrintWriter().println("Error: no package specified.");
2431 return 1;
2432 }
2433
2434 // State to apply; {always|ask|never|undefined}, required
2435 final String modeString = getNextArg();
2436 if (modeString == null) {
2437 getErrPrintWriter().println("Error: no app link state specified.");
2438 return 1;
2439 }
2440
2441 final int newMode;
2442 switch (modeString.toLowerCase()) {
2443 case "undefined":
2444 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
2445 break;
2446
2447 case "always":
2448 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
2449 break;
2450
2451 case "ask":
2452 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
2453 break;
2454
2455 case "always-ask":
2456 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
2457 break;
2458
2459 case "never":
2460 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
2461 break;
2462
2463 default:
2464 getErrPrintWriter().println("Error: unknown app link state '" + modeString + "'");
2465 return 1;
2466 }
2467
Todd Kennedyc3c52172019-11-26 13:20:59 -08002468 final int translatedUserId =
2469 translateUserId(userId, UserHandle.USER_NULL, "runSetAppLink");
2470 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002471 if (info == null) {
2472 getErrPrintWriter().println("Error: package " + pkg + " not found.");
2473 return 1;
2474 }
2475
2476 if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2477 getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2478 return 1;
2479 }
2480
Todd Kennedyc3c52172019-11-26 13:20:59 -08002481 if (!mInterface.updateIntentVerificationStatus(pkg, newMode, translatedUserId)) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002482 getErrPrintWriter().println("Error: unable to update app link status for " + pkg);
2483 return 1;
2484 }
2485
2486 return 0;
2487 }
2488
2489 // pm get-app-link [--user USER_ID] PACKAGE
2490 private int runGetAppLink() throws RemoteException {
2491 int userId = UserHandle.USER_SYSTEM;
2492
2493 String opt;
2494 while ((opt = getNextOption()) != null) {
2495 if (opt.equals("--user")) {
2496 userId = UserHandle.parseUserArg(getNextArgRequired());
2497 } else {
2498 getErrPrintWriter().println("Error: unknown option: " + opt);
2499 return 1;
2500 }
2501 }
2502
2503 // Package name to act on; required
2504 final String pkg = getNextArg();
2505 if (pkg == null) {
2506 getErrPrintWriter().println("Error: no package specified.");
2507 return 1;
2508 }
2509
Todd Kennedyc3c52172019-11-26 13:20:59 -08002510 final int translatedUserId =
2511 translateUserId(userId, UserHandle.USER_NULL, "runGetAppLink");
2512 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002513 if (info == null) {
2514 getErrPrintWriter().println("Error: package " + pkg + " not found.");
2515 return 1;
2516 }
2517
2518 if ((info.applicationInfo.privateFlags
2519 & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2520 getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2521 return 1;
2522 }
2523
2524 getOutPrintWriter().println(linkStateToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002525 mInterface.getIntentVerificationStatus(pkg, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002526
2527 return 0;
2528 }
2529
2530 private int runTrimCaches() throws RemoteException {
2531 String size = getNextArg();
2532 if (size == null) {
2533 getErrPrintWriter().println("Error: no size specified");
2534 return 1;
2535 }
2536 long multiplier = 1;
2537 int len = size.length();
2538 char c = size.charAt(len - 1);
2539 if (c < '0' || c > '9') {
2540 if (c == 'K' || c == 'k') {
2541 multiplier = 1024L;
2542 } else if (c == 'M' || c == 'm') {
2543 multiplier = 1024L*1024L;
2544 } else if (c == 'G' || c == 'g') {
2545 multiplier = 1024L*1024L*1024L;
2546 } else {
2547 getErrPrintWriter().println("Invalid suffix: " + c);
2548 return 1;
2549 }
2550 size = size.substring(0, len-1);
2551 }
2552 long sizeVal;
2553 try {
2554 sizeVal = Long.parseLong(size) * multiplier;
2555 } catch (NumberFormatException e) {
2556 getErrPrintWriter().println("Error: expected number at: " + size);
2557 return 1;
2558 }
2559 String volumeUuid = getNextArg();
2560 if ("internal".equals(volumeUuid)) {
2561 volumeUuid = null;
2562 }
2563 ClearDataObserver obs = new ClearDataObserver();
2564 mInterface.freeStorageAndNotify(volumeUuid, sizeVal,
2565 StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs);
2566 synchronized (obs) {
2567 while (!obs.finished) {
2568 try {
2569 obs.wait();
2570 } catch (InterruptedException e) {
2571 }
2572 }
2573 }
2574 return 0;
2575 }
2576
2577 private static boolean isNumber(String s) {
2578 try {
2579 Integer.parseInt(s);
2580 } catch (NumberFormatException nfe) {
2581 return false;
2582 }
2583 return true;
2584 }
2585
2586 public int runCreateUser() throws RemoteException {
2587 String name;
2588 int userId = -1;
2589 int flags = 0;
Bookatz029832a2019-10-04 16:50:22 -07002590 String userType = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002591 String opt;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002592 boolean preCreateOnly = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002593 while ((opt = getNextOption()) != null) {
Bookatz029832a2019-10-04 16:50:22 -07002594 String newUserType = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002595 if ("--profileOf".equals(opt)) {
2596 userId = UserHandle.parseUserArg(getNextArgRequired());
2597 } else if ("--managed".equals(opt)) {
Bookatz029832a2019-10-04 16:50:22 -07002598 newUserType = UserManager.USER_TYPE_PROFILE_MANAGED;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002599 } else if ("--restricted".equals(opt)) {
Bookatz029832a2019-10-04 16:50:22 -07002600 newUserType = UserManager.USER_TYPE_FULL_RESTRICTED;
2601 } else if ("--guest".equals(opt)) {
2602 newUserType = UserManager.USER_TYPE_FULL_GUEST;
2603 } else if ("--demo".equals(opt)) {
2604 newUserType = UserManager.USER_TYPE_FULL_DEMO;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002605 } else if ("--ephemeral".equals(opt)) {
2606 flags |= UserInfo.FLAG_EPHEMERAL;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002607 } else if ("--pre-create-only".equals(opt)) {
2608 preCreateOnly = true;
Bookatz029832a2019-10-04 16:50:22 -07002609 } else if ("--user-type".equals(opt)) {
2610 newUserType = getNextArgRequired();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002611 } else {
2612 getErrPrintWriter().println("Error: unknown option " + opt);
2613 return 1;
2614 }
Bookatz029832a2019-10-04 16:50:22 -07002615 // Ensure only one user-type was specified.
2616 if (newUserType != null) {
2617 if (userType != null && !userType.equals(newUserType)) {
2618 getErrPrintWriter().println("Error: more than one user type was specified ("
2619 + userType + " and " + newUserType + ")");
2620 return 1;
2621 }
2622 userType = newUserType;
2623 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002624 }
2625 String arg = getNextArg();
Felipe Lemee35f5b02019-10-14 15:37:44 -07002626 if (arg == null && !preCreateOnly) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002627 getErrPrintWriter().println("Error: no user name specified.");
2628 return 1;
2629 }
Felipe Lemee35f5b02019-10-14 15:37:44 -07002630 if (arg != null && preCreateOnly) {
2631 getErrPrintWriter().println("Warning: name is ignored for pre-created users");
2632 }
2633
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002634 name = arg;
Valentin Iftime89df4c82019-08-23 13:02:50 +02002635 UserInfo info = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002636 IUserManager um = IUserManager.Stub.asInterface(
2637 ServiceManager.getService(Context.USER_SERVICE));
2638 IAccountManager accm = IAccountManager.Stub.asInterface(
2639 ServiceManager.getService(Context.ACCOUNT_SERVICE));
Bookatz029832a2019-10-04 16:50:22 -07002640 if (userType == null) {
2641 userType = UserInfo.getDefaultUserType(flags);
2642 }
Valentin Iftime89df4c82019-08-23 13:02:50 +02002643 try {
2644 if (UserManager.isUserTypeRestricted(userType)) {
2645 // In non-split user mode, userId can only be SYSTEM
2646 int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
2647 info = um.createRestrictedProfileWithThrow(name, parentUserId);
2648 accm.addSharedAccountsFromParentUser(parentUserId, userId,
2649 (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
2650 } else if (userId < 0) {
2651 info = preCreateOnly ?
2652 um.preCreateUserWithThrow(userType) :
2653 um.createUserWithThrow(name, userType, flags);
2654 } else {
2655 info = um.createProfileForUserWithThrow(name, userType, flags, userId, null);
2656 }
2657 } catch (ServiceSpecificException e) {
2658 getErrPrintWriter().println("Error: " + e);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002659 }
2660
2661 if (info != null) {
2662 getOutPrintWriter().println("Success: created user id " + info.id);
2663 return 0;
2664 } else {
2665 getErrPrintWriter().println("Error: couldn't create User.");
2666 return 1;
2667 }
2668 }
2669
2670 public int runRemoveUser() throws RemoteException {
2671 int userId;
2672 String arg = getNextArg();
2673 if (arg == null) {
2674 getErrPrintWriter().println("Error: no user id specified.");
2675 return 1;
2676 }
2677 userId = UserHandle.parseUserArg(arg);
2678 IUserManager um = IUserManager.Stub.asInterface(
2679 ServiceManager.getService(Context.USER_SERVICE));
2680 if (um.removeUser(userId)) {
2681 getOutPrintWriter().println("Success: removed user");
2682 return 0;
2683 } else {
2684 getErrPrintWriter().println("Error: couldn't remove user id " + userId);
2685 return 1;
2686 }
2687 }
2688
2689 public int runSetUserRestriction() throws RemoteException {
2690 int userId = UserHandle.USER_SYSTEM;
2691 String opt = getNextOption();
2692 if (opt != null && "--user".equals(opt)) {
2693 userId = UserHandle.parseUserArg(getNextArgRequired());
2694 }
2695
2696 String restriction = getNextArg();
2697 String arg = getNextArg();
2698 boolean value;
2699 if ("1".equals(arg)) {
2700 value = true;
2701 } else if ("0".equals(arg)) {
2702 value = false;
2703 } else {
2704 getErrPrintWriter().println("Error: valid value not specified");
2705 return 1;
2706 }
Todd Kennedy5385b512019-11-26 15:49:06 -08002707 final int translatedUserId =
2708 translateUserId(userId, UserHandle.USER_NULL, "runSetUserRestriction");
2709 final IUserManager um = IUserManager.Stub.asInterface(
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002710 ServiceManager.getService(Context.USER_SERVICE));
Todd Kennedy5385b512019-11-26 15:49:06 -08002711 um.setUserRestriction(restriction, value, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002712 return 0;
2713 }
2714
2715 public int runGetMaxUsers() {
2716 getOutPrintWriter().println("Maximum supported users: "
2717 + UserManager.getMaxSupportedUsers());
2718 return 0;
2719 }
2720
Alex Chauc12189b2018-01-16 15:01:15 +00002721 public int runGetMaxRunningUsers() {
2722 ActivityManagerInternal activityManagerInternal =
2723 LocalServices.getService(ActivityManagerInternal.class);
2724 getOutPrintWriter().println("Maximum supported running users: "
2725 + activityManagerInternal.getMaxRunningUsers());
2726 return 0;
2727 }
2728
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002729 private static class InstallParams {
2730 SessionParams sessionParams;
2731 String installerPackageName;
2732 int userId = UserHandle.USER_ALL;
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002733 boolean mWaitForStagedSessionReady = true;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002734 long timeoutMs = DEFAULT_WAIT_MS;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002735 }
2736
2737 private InstallParams makeInstallParams() {
2738 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2739 final InstallParams params = new InstallParams();
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07002740
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002741 params.sessionParams = sessionParams;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07002742 // Whitelist all permissions by default
2743 sessionParams.installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
2744
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002745 String opt;
Patrick Baumanna9333492017-11-28 15:23:49 -08002746 boolean replaceExisting = true;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002747 while ((opt = getNextOption()) != null) {
2748 switch (opt) {
Patrick Baumanna9333492017-11-28 15:23:49 -08002749 case "-r": // ignore
2750 break;
2751 case "-R":
2752 replaceExisting = false;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002753 break;
2754 case "-i":
2755 params.installerPackageName = getNextArg();
2756 if (params.installerPackageName == null) {
2757 throw new IllegalArgumentException("Missing installer package");
2758 }
2759 break;
2760 case "-t":
2761 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
2762 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002763 case "-f":
2764 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
2765 break;
2766 case "-d":
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00002767 sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002768 break;
2769 case "-g":
2770 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
Svet Ganov83a3a4a2019-05-03 18:50:43 -07002771 break;
2772 case "--restrict-permissions":
2773 sessionParams.installFlags &=
2774 ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002775 break;
Todd Kennedyb1072712016-04-26 15:41:20 -07002776 case "--dont-kill":
2777 sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
2778 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002779 case "--originating-uri":
2780 sessionParams.originatingUri = Uri.parse(getNextArg());
2781 break;
2782 case "--referrer":
2783 sessionParams.referrerUri = Uri.parse(getNextArg());
2784 break;
2785 case "-p":
2786 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
2787 sessionParams.appPackageName = getNextArg();
2788 if (sessionParams.appPackageName == null) {
2789 throw new IllegalArgumentException("Missing inherit package name");
2790 }
2791 break;
Dianne Hackbornca3872c2017-10-30 14:19:32 -07002792 case "--pkg":
2793 sessionParams.appPackageName = getNextArg();
2794 if (sessionParams.appPackageName == null) {
2795 throw new IllegalArgumentException("Missing package name");
2796 }
2797 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002798 case "-S":
Todd Kennedy9caf94e2016-10-12 15:26:08 -07002799 final long sizeBytes = Long.parseLong(getNextArg());
2800 if (sizeBytes <= 0) {
2801 throw new IllegalArgumentException("Size must be positive");
2802 }
2803 sessionParams.setSize(sizeBytes);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002804 break;
2805 case "--abi":
2806 sessionParams.abiOverride = checkAbiArgument(getNextArg());
2807 break;
Todd Kennedy2699f062015-11-20 13:07:17 -08002808 case "--ephemeral":
Dianne Hackbornca3872c2017-10-30 14:19:32 -07002809 case "--instant":
Todd Kennedybe0b8892017-02-15 14:13:52 -08002810 case "--instantapp":
Todd Kennedyb7717682016-11-30 15:41:21 -08002811 sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
Todd Kennedy2699f062015-11-20 13:07:17 -08002812 break;
Todd Kennedybe0b8892017-02-15 14:13:52 -08002813 case "--full":
2814 sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
2815 break;
Todd Kennedy78a72502017-07-19 12:49:30 -07002816 case "--preload":
2817 sessionParams.setInstallAsVirtualPreload();
2818 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002819 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08002820 params.userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002821 break;
2822 case "--install-location":
2823 sessionParams.installLocation = Integer.parseInt(getNextArg());
2824 break;
Sunny Goyalabd4d442018-09-19 15:49:50 -07002825 case "--install-reason":
2826 sessionParams.installReason = Integer.parseInt(getNextArg());
2827 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002828 case "--force-uuid":
2829 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
2830 sessionParams.volumeUuid = getNextArg();
2831 if ("internal".equals(sessionParams.volumeUuid)) {
2832 sessionParams.volumeUuid = null;
2833 }
2834 break;
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002835 case "--force-sdk": // ignore
Todd Kennedyb1072712016-04-26 15:41:20 -07002836 break;
Dario Frenid8bf22e2018-08-31 14:18:04 +01002837 case "--apex":
Dario Freni3fa46d82019-01-23 19:31:47 +00002838 sessionParams.setInstallAsApex();
Dario Freni505b8152019-01-08 12:30:43 +00002839 sessionParams.setStaged();
Dario Frenid8bf22e2018-08-31 14:18:04 +01002840 break;
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002841 case "--multi-package":
2842 sessionParams.setMultiPackage();
2843 break;
Dario Freniaac4ba42018-12-06 15:47:16 +00002844 case "--staged":
2845 sessionParams.setStaged();
2846 break;
Patrick Baumann5ff0f9e2019-11-27 11:40:07 -08002847 case "--force-queryable":
2848 sessionParams.setForceQueryable();
2849 break;
Richard Uhlerb29f1452018-09-12 16:38:15 +01002850 case "--enable-rollback":
Richard Uhler88184a62019-04-16 11:30:25 +01002851 if (params.installerPackageName == null) {
2852 // com.android.shell has the TEST_MANAGE_ROLLBACKS
2853 // permission needed to enable rollback for non-module
2854 // packages, which is likely what the user wants when
2855 // enabling rollback through the shell command. Set
2856 // the installer to com.android.shell if no installer
2857 // has been provided so that the user doesn't have to
2858 // remember to set it themselves.
2859 params.installerPackageName = "com.android.shell";
2860 }
Richard Uhlerb29f1452018-09-12 16:38:15 +01002861 sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
2862 break;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002863 case "--wait":
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002864 params.mWaitForStagedSessionReady = true;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002865 try {
2866 params.timeoutMs = Long.parseLong(peekNextArg());
2867 getNextArg();
2868 } catch (NumberFormatException ignore) {
2869 }
2870 break;
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002871 case "--no-wait":
2872 params.mWaitForStagedSessionReady = false;
2873 break;
Chester Hsieh750b5ed2020-01-08 09:32:17 -08002874 case "--skip-verification":
2875 sessionParams.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;
2876 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002877 default:
2878 throw new IllegalArgumentException("Unknown option " + opt);
2879 }
Patrick Baumanndcf19162019-05-29 09:18:58 -07002880 }
2881 if (replaceExisting) {
2882 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002883 }
2884 return params;
2885 }
2886
Makoto Onuki4828a592016-03-15 18:06:57 -07002887 private int runSetHomeActivity() {
2888 final PrintWriter pw = getOutPrintWriter();
2889 int userId = UserHandle.USER_SYSTEM;
2890 String opt;
2891 while ((opt = getNextOption()) != null) {
2892 switch (opt) {
2893 case "--user":
2894 userId = UserHandle.parseUserArg(getNextArgRequired());
2895 break;
2896 default:
2897 pw.println("Error: Unknown option: " + opt);
2898 return 1;
2899 }
2900 }
2901
Bookatz2b5a6012019-04-16 19:41:28 -07002902 String pkgName;
Makoto Onuki4828a592016-03-15 18:06:57 -07002903 String component = getNextArg();
Bookatz2b5a6012019-04-16 19:41:28 -07002904 if (component.indexOf('/') < 0) {
2905 // No component specified, so assume it's just a package name.
2906 pkgName = component;
2907 } else {
2908 ComponentName componentName =
2909 component != null ? ComponentName.unflattenFromString(component) : null;
2910 if (componentName == null) {
2911 pw.println("Error: invalid component name");
2912 return 1;
2913 }
2914 pkgName = componentName.getPackageName();
Makoto Onuki4828a592016-03-15 18:06:57 -07002915 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002916 final int translatedUserId =
2917 translateUserId(userId, UserHandle.USER_NULL, "runSetHomeActivity");
Bookatz2b5a6012019-04-16 19:41:28 -07002918 final CompletableFuture<Boolean> future = new CompletableFuture<>();
2919 final RemoteCallback callback = new RemoteCallback(res -> future.complete(res != null));
Makoto Onuki4828a592016-03-15 18:06:57 -07002920 try {
Bookatz2b5a6012019-04-16 19:41:28 -07002921 IRoleManager roleManager = android.app.role.IRoleManager.Stub.asInterface(
2922 ServiceManager.getServiceOrThrow(Context.ROLE_SERVICE));
2923 roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName,
Todd Kennedyc3c52172019-11-26 13:20:59 -08002924 0, translatedUserId, callback);
Bookatz2b5a6012019-04-16 19:41:28 -07002925 boolean success = future.get();
2926 if (success) {
2927 pw.println("Success");
2928 return 0;
2929 } else {
2930 pw.println("Error: Failed to set default home.");
2931 return 1;
2932 }
Makoto Onuki3bdbf982016-06-23 16:56:35 -07002933 } catch (Exception e) {
Makoto Onuki4828a592016-03-15 18:06:57 -07002934 pw.println(e.toString());
2935 return 1;
2936 }
2937 }
2938
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002939 private int runSetInstaller() throws RemoteException {
2940 final String targetPackage = getNextArg();
2941 final String installerPackageName = getNextArg();
Fyodor Kupolov51245c72016-12-01 11:34:10 -08002942
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002943 if (targetPackage == null || installerPackageName == null) {
2944 getErrPrintWriter().println("Must provide both target and installer package names");
Todd Kennedy74629e32017-08-15 14:48:07 -07002945 return 1;
2946 }
Todd Kennedy74629e32017-08-15 14:48:07 -07002947
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002948 mInterface.setInstallerPackageName(targetPackage, installerPackageName);
2949 getOutPrintWriter().println("Success");
Svet Ganov087dce22017-09-07 15:42:16 -07002950 return 0;
2951 }
2952
Todd Kennedy0a3f0812017-05-08 14:43:15 -07002953 private int runGetInstantAppResolver() {
2954 final PrintWriter pw = getOutPrintWriter();
2955 try {
2956 final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent();
2957 if (instantAppsResolver == null) {
2958 return 1;
2959 }
2960 pw.println(instantAppsResolver.flattenToString());
2961 return 0;
2962 } catch (Exception e) {
2963 pw.println(e.toString());
2964 return 1;
2965 }
2966 }
2967
Tadashi G. Takaokabe5782f2017-02-14 16:41:49 +09002968 private int runHasFeature() {
2969 final PrintWriter err = getErrPrintWriter();
2970 final String featureName = getNextArg();
2971 if (featureName == null) {
2972 err.println("Error: expected FEATURE name");
2973 return 1;
2974 }
2975 final String versionString = getNextArg();
2976 try {
2977 final int version = (versionString == null) ? 0 : Integer.parseInt(versionString);
2978 final boolean hasFeature = mInterface.hasSystemFeature(featureName, version);
2979 getOutPrintWriter().println(hasFeature);
2980 return hasFeature ? 0 : 1;
2981 } catch (NumberFormatException e) {
2982 err.println("Error: illegal version number " + versionString);
2983 return 1;
2984 } catch (RemoteException e) {
2985 err.println(e.toString());
2986 return 1;
2987 }
2988 }
2989
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002990 private int runDump() {
2991 String pkg = getNextArg();
2992 if (pkg == null) {
2993 getErrPrintWriter().println("Error: no package specified");
2994 return 1;
2995 }
2996 ActivityManager.dumpPackageStateStatic(getOutFileDescriptor(), pkg);
2997 return 0;
2998 }
2999
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08003000 private int runSetHarmfulAppWarning() throws RemoteException {
3001 int userId = UserHandle.USER_CURRENT;
3002
3003 String opt;
3004 while ((opt = getNextOption()) != null) {
3005 if (opt.equals("--user")) {
3006 userId = UserHandle.parseUserArg(getNextArgRequired());
3007 } else {
3008 getErrPrintWriter().println("Error: Unknown option: " + opt);
3009 return -1;
3010 }
3011 }
3012
Todd Kennedyc3c52172019-11-26 13:20:59 -08003013 final int translatedUserId =
3014 translateUserId(userId, UserHandle.USER_NULL, "runSetHarmfulAppWarning");
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08003015 final String packageName = getNextArgRequired();
3016 final String warning = getNextArg();
3017
Todd Kennedyc3c52172019-11-26 13:20:59 -08003018 mInterface.setHarmfulAppWarning(packageName, warning, translatedUserId);
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08003019
3020 return 0;
3021 }
3022
Ben Gruver9ef60092018-01-10 11:32:30 -08003023 private int runGetHarmfulAppWarning() throws RemoteException {
3024 int userId = UserHandle.USER_CURRENT;
3025
3026 String opt;
3027 while ((opt = getNextOption()) != null) {
3028 if (opt.equals("--user")) {
3029 userId = UserHandle.parseUserArg(getNextArgRequired());
3030 } else {
3031 getErrPrintWriter().println("Error: Unknown option: " + opt);
3032 return -1;
3033 }
3034 }
3035
Todd Kennedyc3c52172019-11-26 13:20:59 -08003036 final int translatedUserId =
3037 translateUserId(userId, UserHandle.USER_NULL, "runGetHarmfulAppWarning");
Ben Gruver9ef60092018-01-10 11:32:30 -08003038 final String packageName = getNextArgRequired();
Todd Kennedyc3c52172019-11-26 13:20:59 -08003039 final CharSequence warning = mInterface.getHarmfulAppWarning(packageName, translatedUserId);
Ben Gruver9ef60092018-01-10 11:32:30 -08003040 if (!TextUtils.isEmpty(warning)) {
3041 getOutPrintWriter().println(warning);
3042 return 0;
3043 } else {
3044 return 1;
3045 }
3046 }
3047
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003048 private static String checkAbiArgument(String abi) {
3049 if (TextUtils.isEmpty(abi)) {
3050 throw new IllegalArgumentException("Missing ABI argument");
3051 }
3052
3053 if ("-".equals(abi)) {
3054 return abi;
3055 }
3056
3057 final String[] supportedAbis = Build.SUPPORTED_ABIS;
3058 for (String supportedAbi : supportedAbis) {
3059 if (supportedAbi.equals(abi)) {
3060 return abi;
3061 }
3062 }
3063
3064 throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
3065 }
3066
Todd Kennedyc3c52172019-11-26 13:20:59 -08003067 private int translateUserId(int userId, int allUserId, String logContext) {
3068 final boolean allowAll = (allUserId != UserHandle.USER_NULL);
3069 final int translatedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
3070 Binder.getCallingUid(), userId, allowAll, true, logContext, "pm command");
3071 return translatedUserId == UserHandle.USER_ALL ? allUserId : translatedUserId;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003072 }
3073
3074 private int doCreateSession(SessionParams params, String installerPackageName, int userId)
3075 throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003076 if (userId == UserHandle.USER_ALL) {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003077 params.installFlags |= PackageManager.INSTALL_ALL_USERS;
3078 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08003079 final int translatedUserId =
3080 translateUserId(userId, UserHandle.USER_SYSTEM, "doCreateSession");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003081 final int sessionId = mInterface.getPackageInstaller()
Todd Kennedyc3c52172019-11-26 13:20:59 -08003082 .createSession(params, installerPackageName, translatedUserId);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003083 return sessionId;
3084 }
3085
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003086 private int doAddFiles(int sessionId, ArrayList<String> args, long sessionSizeBytes,
3087 boolean isApex) throws RemoteException {
Alex Buynytskyyc282de92020-03-10 10:27:42 -07003088 PackageInstaller.Session session = null;
Alex Buynytskyyda208152019-11-11 09:34:05 -08003089 try {
Alex Buynytskyyc282de92020-03-10 10:27:42 -07003090 session = new PackageInstaller.Session(
3091 mInterface.getPackageInstaller().openSession(sessionId));
3092
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003093 // 1. Single file from stdin.
3094 if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) {
Alex Buynytskyy17d9da02020-02-12 16:03:30 -08003095 final String name = "base." + (isApex ? "apex" : "apk");
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003096 final Metadata metadata = Metadata.forStdIn(name);
Alex Buynytskyy17d9da02020-02-12 16:03:30 -08003097 session.addFile(LOCATION_DATA_APP, name, sessionSizeBytes,
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003098 metadata.toByteArray(), null);
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003099 return 0;
Alex Buynytskyyda208152019-11-11 09:34:05 -08003100 }
3101
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003102 for (String arg : args) {
3103 final int delimLocation = arg.indexOf(':');
3104
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003105 if (delimLocation != -1) {
Songchun Fan5f911c82020-02-19 16:23:08 -08003106 // 2. File with specified size read from stdin.
3107 if (processArgForStdin(arg, session) != 0) {
Alex Buynytskyy17d9da02020-02-12 16:03:30 -08003108 return 1;
3109 }
Songchun Fan5f911c82020-02-19 16:23:08 -08003110 } else {
3111 // 3. Local file.
3112 processArgForLocalFile(arg, session);
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003113 }
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003114 }
Alex Buynytskyyda208152019-11-11 09:34:05 -08003115 return 0;
Alex Buynytskyyc282de92020-03-10 10:27:42 -07003116 } catch (IllegalArgumentException e) {
3117 getErrPrintWriter().println("Failed to add file(s), reason: " + e);
3118 getOutPrintWriter().println("Failure [failed to add file(s)]");
3119 return 1;
Alex Buynytskyyda208152019-11-11 09:34:05 -08003120 } finally {
3121 IoUtils.closeQuietly(session);
3122 }
3123 }
3124
Songchun Fan5f911c82020-02-19 16:23:08 -08003125 private int processArgForStdin(String arg, PackageInstaller.Session session) {
3126 final String[] fileDesc = arg.split(":");
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003127 String name, fileId;
Songchun Fan5f911c82020-02-19 16:23:08 -08003128 long sizeBytes;
3129 byte[] signature = null;
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003130 int streamingVersion = 0;
Songchun Fan5f911c82020-02-19 16:23:08 -08003131
3132 try {
3133 if (fileDesc.length < 2) {
3134 getErrPrintWriter().println("Must specify file name and size");
3135 return 1;
3136 }
3137 name = fileDesc[0];
3138 sizeBytes = Long.parseUnsignedLong(fileDesc[1]);
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003139 fileId = name;
Songchun Fan5f911c82020-02-19 16:23:08 -08003140
3141 if (fileDesc.length > 2 && !TextUtils.isEmpty(fileDesc[2])) {
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003142 fileId = fileDesc[2];
Songchun Fan5f911c82020-02-19 16:23:08 -08003143 }
3144 if (fileDesc.length > 3) {
3145 signature = Base64.getDecoder().decode(fileDesc[3]);
3146 }
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003147 if (fileDesc.length > 4) {
3148 streamingVersion = Integer.parseUnsignedInt(fileDesc[4]);
3149 if (streamingVersion < 0 || streamingVersion > 1) {
3150 getErrPrintWriter().println(
3151 "Unsupported streaming version: " + streamingVersion);
3152 return 1;
3153 }
3154 }
Songchun Fan5f911c82020-02-19 16:23:08 -08003155 } catch (IllegalArgumentException e) {
3156 getErrPrintWriter().println(
3157 "Unable to parse file parameters: " + arg + ", reason: " + e);
3158 return 1;
3159 }
3160
3161 if (TextUtils.isEmpty(name)) {
3162 getErrPrintWriter().println("Empty file name in: " + arg);
3163 return 1;
3164 }
3165
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003166 final Metadata metadata;
3167
Songchun Fan5f911c82020-02-19 16:23:08 -08003168 if (signature != null) {
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003169 // Streaming/adb mode. Versions:
3170 // 0: data only streaming, tree has to be fully available,
3171 // 1: tree and data streaming.
3172 metadata = (streamingVersion == 0) ? Metadata.forDataOnlyStreaming(fileId)
3173 : Metadata.forStreaming(fileId);
Songchun Fan5f911c82020-02-19 16:23:08 -08003174 try {
Alex Buynytskyy14d5cc42020-05-12 09:14:10 -07003175 if ((signature.length > 0) && (V4Signature.readFrom(signature) == null)) {
Songchun Fan5f911c82020-02-19 16:23:08 -08003176 getErrPrintWriter().println("V4 signature is invalid in: " + arg);
3177 return 1;
3178 }
3179 } catch (Exception e) {
3180 getErrPrintWriter().println(
3181 "V4 signature is invalid: " + e + " in " + arg);
3182 return 1;
3183 }
3184 } else {
3185 // Single-shot read from stdin.
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003186 metadata = Metadata.forStdIn(fileId);
Songchun Fan5f911c82020-02-19 16:23:08 -08003187 }
3188
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003189 session.addFile(LOCATION_DATA_APP, name, sizeBytes, metadata.toByteArray(), signature);
Songchun Fan5f911c82020-02-19 16:23:08 -08003190 return 0;
3191 }
3192
3193 private void processArgForLocalFile(String arg, PackageInstaller.Session session) {
3194 final String inPath = arg;
3195
3196 final File file = new File(inPath);
3197 final String name = file.getName();
3198 final long size = file.length();
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003199 final Metadata metadata = Metadata.forLocalFile(inPath);
Songchun Fan5f911c82020-02-19 16:23:08 -08003200
Songchun Fan38dfe9a2020-02-20 18:12:47 -08003201 byte[] v4signatureBytes = null;
3202 // Try to load the v4 signature file for the APK; it might not exist.
3203 final String v4SignaturePath = inPath + V4Signature.EXT;
3204 final ParcelFileDescriptor pfd = openFileForSystem(v4SignaturePath, "r");
3205 if (pfd != null) {
3206 try {
3207 final V4Signature v4signature = V4Signature.readFrom(pfd);
3208 v4signatureBytes = v4signature.toByteArray();
3209 } catch (IOException ex) {
3210 Slog.e(TAG, "V4 signature file exists but failed to be parsed.", ex);
3211 } finally {
3212 IoUtils.closeQuietly(pfd);
3213 }
3214 }
Songchun Fan5f911c82020-02-19 16:23:08 -08003215
Alex Buynytskyy06970b92020-03-25 12:50:10 -07003216 session.addFile(LOCATION_DATA_APP, name, size, metadata.toByteArray(), v4signatureBytes);
Songchun Fan5f911c82020-02-19 16:23:08 -08003217 }
3218
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003219 private int doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes,
3220 boolean isApex) throws RemoteException {
3221 final boolean multipleSplits = splitPaths.size() > 1;
3222 for (String splitPath : splitPaths) {
3223 String splitName = multipleSplits ? new File(splitPath).getName()
3224 : "base." + (isApex ? "apex" : "apk");
3225
3226 if (doWriteSplit(sessionId, splitPath, sessionSizeBytes, splitName,
3227 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
3228 return 1;
3229 }
3230 }
3231 return 0;
3232 }
3233
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003234 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003235 boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003236 PackageInstaller.Session session = null;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003237 try {
Alex Buynytskyyda208152019-11-11 09:34:05 -08003238 session = new PackageInstaller.Session(
3239 mInterface.getPackageInstaller().openSession(sessionId));
3240
Jeff Sharkeya651b782018-07-23 13:45:28 -06003241 final PrintWriter pw = getOutPrintWriter();
Alex Buynytskyyda208152019-11-11 09:34:05 -08003242
Jeff Sharkeya651b782018-07-23 13:45:28 -06003243 final ParcelFileDescriptor fd;
3244 if (STDIN_PATH.equals(inPath)) {
3245 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
3246 } else if (inPath != null) {
3247 fd = openFileForSystem(inPath, "r");
3248 if (fd == null) {
3249 return -1;
3250 }
3251 sizeBytes = fd.getStatSize();
3252 if (sizeBytes < 0) {
3253 getErrPrintWriter().println("Unable to get size of: " + inPath);
3254 return -1;
3255 }
3256 } else {
3257 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
3258 }
3259 if (sizeBytes <= 0) {
3260 getErrPrintWriter().println("Error: must specify a APK size");
3261 return 1;
3262 }
3263
Jeff Sharkey0451de62018-02-02 11:27:21 -07003264 session.write(splitName, 0, sizeBytes, fd);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003265
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003266 if (logSuccess) {
Jeff Sharkey0451de62018-02-02 11:27:21 -07003267 pw.println("Success: streamed " + sizeBytes + " bytes");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003268 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003269 return 0;
3270 } catch (IOException e) {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07003271 getErrPrintWriter().println("Error: failed to write; " + e.getMessage());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003272 return 1;
3273 } finally {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003274 IoUtils.closeQuietly(session);
3275 }
3276 }
3277
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003278 private int doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)
3279 throws RemoteException {
3280 final PrintWriter pw = getOutPrintWriter();
3281 PackageInstaller.Session session = null;
3282 try {
3283 session = new PackageInstaller.Session(
3284 mInterface.getPackageInstaller().openSession(parentId));
3285 if (!session.isMultiPackage()) {
3286 getErrPrintWriter().println(
3287 "Error: parent session ID is not a multi-package session");
3288 return 1;
3289 }
3290 for (int i = 0; i < sessionIds.length; i++) {
3291 session.addChildSessionId(sessionIds[i]);
3292 }
3293 if (logSuccess) {
3294 pw.println("Success");
3295 }
3296 return 0;
3297 } finally {
3298 IoUtils.closeQuietly(session);
3299 }
3300 }
3301
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003302 private int doRemoveSplits(int sessionId, Collection<String> splitNames, boolean logSuccess)
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003303 throws RemoteException {
3304 final PrintWriter pw = getOutPrintWriter();
3305 PackageInstaller.Session session = null;
3306 try {
3307 session = new PackageInstaller.Session(
3308 mInterface.getPackageInstaller().openSession(sessionId));
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003309 for (String splitName : splitNames) {
3310 session.removeSplit(splitName);
3311 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003312
3313 if (logSuccess) {
3314 pw.println("Success");
3315 }
3316 return 0;
3317 } catch (IOException e) {
3318 pw.println("Error: failed to remove split; " + e.getMessage());
3319 return 1;
3320 } finally {
3321 IoUtils.closeQuietly(session);
3322 }
3323 }
3324
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003325 private int doCommitSession(int sessionId, boolean logSuccess)
3326 throws RemoteException {
3327
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003328 final PrintWriter pw = getOutPrintWriter();
3329 PackageInstaller.Session session = null;
3330 try {
3331 session = new PackageInstaller.Session(
3332 mInterface.getPackageInstaller().openSession(sessionId));
Dario Frenia8f4b132018-12-30 00:36:49 +00003333 if (!session.isMultiPackage() && !session.isStaged()) {
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003334 // Sanity check that all .dm files match an apk.
3335 // (The installer does not support standalone .dm files and will not process them.)
3336 try {
3337 DexMetadataHelper.validateDexPaths(session.getNames());
3338 } catch (IllegalStateException | IOException e) {
3339 pw.println(
3340 "Warning [Could not validate the dex paths: " + e.getMessage() + "]");
3341 }
Calin Juravle3fc56c32017-12-11 18:26:13 -08003342 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003343 final LocalIntentReceiver receiver = new LocalIntentReceiver();
3344 session.commit(receiver.getIntentSender());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003345 final Intent result = receiver.getResult();
3346 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
3347 PackageInstaller.STATUS_FAILURE);
3348 if (status == PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003349 if (logSuccess) {
Todd Kennedyb6e96e52016-07-20 16:27:39 -07003350 pw.println("Success");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003351 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003352 } else {
3353 pw.println("Failure ["
3354 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003355 }
3356 return status;
3357 } finally {
3358 IoUtils.closeQuietly(session);
3359 }
3360 }
3361
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003362 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003363 final PrintWriter pw = getOutPrintWriter();
3364 PackageInstaller.Session session = null;
3365 try {
3366 session = new PackageInstaller.Session(
3367 mInterface.getPackageInstaller().openSession(sessionId));
3368 session.abandon();
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003369 if (logSuccess) {
3370 pw.println("Success");
3371 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003372 return 0;
3373 } finally {
3374 IoUtils.closeQuietly(session);
3375 }
3376 }
3377
Todd Kennedy60459ab2015-10-30 11:32:16 -07003378 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
3379 boolean summary, int startProtectionLevel, int endProtectionLevel)
3380 throws RemoteException {
3381 final PrintWriter pw = getOutPrintWriter();
3382 final int groupCount = groupList.size();
3383 for (int i = 0; i < groupCount; i++) {
3384 String groupName = groupList.get(i);
3385 String prefix = "";
3386 if (groups) {
3387 if (i > 0) {
3388 pw.println("");
3389 }
3390 if (groupName != null) {
3391 PermissionGroupInfo pgi =
3392 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
3393 if (summary) {
3394 Resources res = getResources(pgi);
3395 if (res != null) {
3396 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
3397 } else {
3398 pw.print(pgi.name + ": ");
3399
3400 }
3401 } else {
3402 pw.println((labels ? "+ " : "") + "group:" + pgi.name);
3403 if (labels) {
3404 pw.println(" package:" + pgi.packageName);
3405 Resources res = getResources(pgi);
3406 if (res != null) {
3407 pw.println(" label:"
3408 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
3409 pw.println(" description:"
3410 + loadText(pgi, pgi.descriptionRes,
3411 pgi.nonLocalizedDescription));
3412 }
3413 }
3414 }
3415 } else {
3416 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
3417 }
3418 prefix = " ";
3419 }
Todd Kennedy1d29b4a2019-07-02 14:49:28 -07003420 List<PermissionInfo> ps = mPermissionManager
3421 .queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -07003422 final int count = ps.size();
3423 boolean first = true;
3424 for (int p = 0 ; p < count ; p++) {
3425 PermissionInfo pi = ps.get(p);
3426 if (groups && groupName == null && pi.group != null) {
3427 continue;
3428 }
3429 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
3430 if (base < startProtectionLevel
3431 || base > endProtectionLevel) {
3432 continue;
3433 }
3434 if (summary) {
3435 if (first) {
3436 first = false;
3437 } else {
3438 pw.print(", ");
3439 }
3440 Resources res = getResources(pi);
3441 if (res != null) {
3442 pw.print(loadText(pi, pi.labelRes,
3443 pi.nonLocalizedLabel));
3444 } else {
3445 pw.print(pi.name);
3446 }
3447 } else {
3448 pw.println(prefix + (labels ? "+ " : "")
3449 + "permission:" + pi.name);
3450 if (labels) {
3451 pw.println(prefix + " package:" + pi.packageName);
3452 Resources res = getResources(pi);
3453 if (res != null) {
3454 pw.println(prefix + " label:"
3455 + loadText(pi, pi.labelRes,
3456 pi.nonLocalizedLabel));
3457 pw.println(prefix + " description:"
3458 + loadText(pi, pi.descriptionRes,
3459 pi.nonLocalizedDescription));
3460 }
3461 pw.println(prefix + " protectionLevel:"
3462 + PermissionInfo.protectionToString(pi.protectionLevel));
3463 }
3464 }
3465 }
3466
3467 if (summary) {
3468 pw.println("");
3469 }
3470 }
3471 }
3472
3473 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
3474 throws RemoteException {
3475 if (nonLocalized != null) {
3476 return nonLocalized.toString();
3477 }
3478 if (res != 0) {
3479 Resources r = getResources(pii);
3480 if (r != null) {
3481 try {
3482 return r.getString(res);
3483 } catch (Resources.NotFoundException e) {
3484 }
3485 }
3486 }
3487 return null;
3488 }
3489
3490 private Resources getResources(PackageItemInfo pii) throws RemoteException {
3491 Resources res = mResourceCache.get(pii.packageName);
3492 if (res != null) return res;
3493
Patrick Baumannbc883f62019-05-21 11:20:11 -07003494 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName,
3495 PackageManager.MATCH_DISABLED_COMPONENTS
3496 | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
3497 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, 0);
Todd Kennedy60459ab2015-10-30 11:32:16 -07003498 AssetManager am = new AssetManager();
3499 am.addAssetPath(ai.publicSourceDir);
3500 res = new Resources(am, null, null);
3501 mResourceCache.put(pii.packageName, res);
3502 return res;
3503 }
3504
3505 @Override
3506 public void onHelp() {
3507 final PrintWriter pw = getOutPrintWriter();
3508 pw.println("Package manager (package) commands:");
3509 pw.println(" help");
3510 pw.println(" Print this help text.");
3511 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003512 pw.println(" path [--user USER_ID] PACKAGE");
3513 pw.println(" Print the path to the .apk of the given PACKAGE.");
3514 pw.println("");
3515 pw.println(" dump PACKAGE");
3516 pw.println(" Print various system state associated with the given PACKAGE.");
3517 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003518 pw.println(" has-feature FEATURE_NAME [version]");
3519 pw.println(" Prints true and returns exit status 0 when system has a FEATURE_NAME,");
3520 pw.println(" otherwise prints false and returns exit status 1");
3521 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003522 pw.println(" list features");
3523 pw.println(" Prints all features of the system.");
3524 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003525 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
3526 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE");
3527 pw.println(" Options:");
3528 pw.println(" -f: dump the name of the .apk file containing the test package");
3529 pw.println("");
3530 pw.println(" list libraries");
3531 pw.println(" Prints all system libraries.");
3532 pw.println("");
3533 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
Jiyong Parkf50a2932018-12-17 13:54:40 +09003534 pw.println(" [--show-versioncode] [--apex-only] [--uid UID] [--user USER_ID] [FILTER]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003535 pw.println(" Prints all packages; optionally only those whose name contains");
3536 pw.println(" the text in FILTER. Options are:");
3537 pw.println(" -f: see their associated file");
Jiyong Park4f49abe2018-12-11 13:37:17 +09003538 pw.println(" -a: all known packages (but excluding APEXes)");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003539 pw.println(" -d: filter to only show disabled packages");
3540 pw.println(" -e: filter to only show enabled packages");
3541 pw.println(" -s: filter to only show system packages");
3542 pw.println(" -3: filter to only show third party packages");
3543 pw.println(" -i: see the installer for the packages");
3544 pw.println(" -l: ignored (used for compatibility with older releases)");
3545 pw.println(" -U: also show the package UID");
3546 pw.println(" -u: also include uninstalled packages");
Jiyong Parkf50a2932018-12-17 13:54:40 +09003547 pw.println(" --show-versioncode: also show the version code");
Jiyong Park4f49abe2018-12-11 13:37:17 +09003548 pw.println(" --apex-only: only show APEX packages");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003549 pw.println(" --uid UID: filter to only show packages with the given UID");
3550 pw.println(" --user USER_ID: only list packages belonging to the given user");
3551 pw.println("");
3552 pw.println(" list permission-groups");
3553 pw.println(" Prints all known permission groups.");
3554 pw.println("");
3555 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
3556 pw.println(" Prints all known permissions; optionally only those in GROUP. Options are:");
3557 pw.println(" -g: organize by group");
3558 pw.println(" -f: print all information");
3559 pw.println(" -s: short summary");
3560 pw.println(" -d: only list dangerous permissions");
3561 pw.println(" -u: list only the permissions users will see");
3562 pw.println("");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003563 pw.println(" list staged-sessions [--only-ready] [--only-sessionid] [--only-parent]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003564 pw.println(" Prints all staged sessions.");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003565 pw.println(" --only-ready: show only staged sessions that are ready");
3566 pw.println(" --only-sessionid: show only sessionId of each session");
3567 pw.println(" --only-parent: hide all children sessions");
3568 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003569 pw.println(" list users");
3570 pw.println(" Prints all users.");
3571 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003572 pw.println(" resolve-activity [--brief] [--components] [--query-flags FLAGS]");
3573 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003574 pw.println(" Prints the activity that resolves to the given INTENT.");
3575 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003576 pw.println(" query-activities [--brief] [--components] [--query-flags FLAGS]");
3577 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003578 pw.println(" Prints all activities that can handle the given INTENT.");
3579 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003580 pw.println(" query-services [--brief] [--components] [--query-flags FLAGS]");
3581 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003582 pw.println(" Prints all services that can handle the given INTENT.");
3583 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003584 pw.println(" query-receivers [--brief] [--components] [--query-flags FLAGS]");
3585 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003586 pw.println(" Prints all broadcast receivers that can handle the given INTENT.");
3587 pw.println("");
Mark De Ruyterbfcd3392019-11-21 12:08:58 -08003588 pw.println(" install [-rtfdgw] [-i PACKAGE] [--user USER_ID|all|current]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003589 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003590 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
3591 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003592 pw.println(" [--preload] [--instant] [--full] [--dont-kill]");
Richard Uhlerb29f1452018-09-12 16:38:15 +01003593 pw.println(" [--enable-rollback]");
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01003594 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
3595 pw.println(" [--apex] [--wait TIMEOUT]");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003596 pw.println(" [PATH [SPLIT...]|-]");
3597 pw.println(" Install an application. Must provide the apk data to install, either as");
3598 pw.println(" file path(s) or '-' to read from stdin. Options are:");
Patrick Baumanna9333492017-11-28 15:23:49 -08003599 pw.println(" -R: disallow replacement of existing application");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003600 pw.println(" -t: allow test packages");
3601 pw.println(" -i: specify package name of installer owning the app");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003602 pw.println(" -f: install application on internal flash");
3603 pw.println(" -d: allow version code downgrade (debuggable packages only)");
3604 pw.println(" -p: partial application install (new split on top of existing pkg)");
3605 pw.println(" -g: grant all runtime permissions");
3606 pw.println(" -S: size in bytes of package, required for stdin");
3607 pw.println(" --user: install under the given user.");
3608 pw.println(" --dont-kill: installing a new feature split, don't kill running app");
Svet Ganov83a3a4a2019-05-03 18:50:43 -07003609 pw.println(" --restrict-permissions: don't whitelist restricted permissions at install");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003610 pw.println(" --originating-uri: set URI where app was downloaded from");
3611 pw.println(" --referrer: set URI that instigated the install of the app");
3612 pw.println(" --pkg: specify expected package name of app being installed");
3613 pw.println(" --abi: override the default ABI of the platform");
Todd Kennedybef39e02019-09-20 15:14:18 -07003614 pw.println(" --instant: cause the app to be installed as an ephemeral install app");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003615 pw.println(" --full: cause the app to be installed as a non-ephemeral full app");
3616 pw.println(" --install-location: force the install location:");
3617 pw.println(" 0=auto, 1=internal only, 2=prefer external");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003618 pw.println(" --install-reason: indicates why the app is being installed:");
3619 pw.println(" 0=unknown, 1=admin policy, 2=device restore,");
3620 pw.println(" 3=device setup, 4=user request");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003621 pw.println(" --force-uuid: force install on to disk volume with given UUID");
MÃ¥rten Kongstad2a5989342018-11-16 15:04:44 +01003622 pw.println(" --apex: install an .apex file, not an .apk");
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01003623 pw.println(" --wait: when performing staged install, wait TIMEOUT milliseconds");
3624 pw.println(" for pre-reboot verification to complete. If TIMEOUT is not");
3625 pw.println(" specified it will wait for " + DEFAULT_WAIT_MS + " milliseconds.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003626 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003627 pw.println(" install-existing [--user USER_ID|all|current]");
3628 pw.println(" [--instant] [--full] [--wait] [--restrict-permissions] PACKAGE");
3629 pw.println(" Installs an existing application for a new user. Options are:");
3630 pw.println(" --user: install for the given user.");
3631 pw.println(" --instant: install as an instant app");
3632 pw.println(" --full: install as a full app");
3633 pw.println(" --wait: wait until the package is installed");
3634 pw.println(" --restrict-permissions: don't whitelist restricted permissions");
3635 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003636 pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
3637 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003638 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
3639 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003640 pw.println(" [--preload] [--instant] [--full] [--dont-kill]");
MÃ¥rten Kongstad2a5989342018-11-16 15:04:44 +01003641 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [--apex] [-S BYTES]");
Dario Freniaac4ba42018-12-06 15:47:16 +00003642 pw.println(" [--multi-package] [--staged]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003643 pw.println(" Like \"install\", but starts an install session. Use \"install-write\"");
3644 pw.println(" to push data into the session, and \"install-commit\" to finish.");
3645 pw.println("");
3646 pw.println(" install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]");
3647 pw.println(" Write an apk into the given install session. If the path is '-', data");
3648 pw.println(" will be read from stdin. Options are:");
3649 pw.println(" -S: size in bytes of package, required for stdin");
3650 pw.println("");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003651 pw.println(" install-remove SESSION_ID SPLIT...");
3652 pw.println(" Mark SPLIT(s) as removed in the given install session.");
3653 pw.println("");
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003654 pw.println(" install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs");
3655 pw.println(" Add one or more session IDs to a multi-package session.");
3656 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003657 pw.println(" install-commit SESSION_ID");
3658 pw.println(" Commit the given active install session, installing the app.");
3659 pw.println("");
3660 pw.println(" install-abandon SESSION_ID");
3661 pw.println(" Delete the given active install session.");
3662 pw.println("");
3663 pw.println(" set-install-location LOCATION");
3664 pw.println(" Changes the default install location. NOTE this is only intended for debugging;");
3665 pw.println(" using this can cause applications to break and other undersireable behavior.");
3666 pw.println(" LOCATION is one of:");
3667 pw.println(" 0 [auto]: Let system decide the best location");
3668 pw.println(" 1 [internal]: Install on internal device storage");
3669 pw.println(" 2 [external]: Install on external media");
3670 pw.println("");
3671 pw.println(" get-install-location");
3672 pw.println(" Returns the current install location: 0, 1 or 2 as per set-install-location.");
3673 pw.println("");
3674 pw.println(" move-package PACKAGE [internal|UUID]");
3675 pw.println("");
3676 pw.println(" move-primary-storage [internal|UUID]");
3677 pw.println("");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003678 pw.println(" uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE]");
3679 pw.println(" PACKAGE [SPLIT...]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003680 pw.println(" Remove the given package name from the system. May remove an entire app");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003681 pw.println(" if no SPLIT names specified, otherwise will remove only the splits of the");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003682 pw.println(" given app. Options are:");
3683 pw.println(" -k: keep the data and cache directories around after package removal.");
3684 pw.println(" --user: remove the app from the given user.");
3685 pw.println(" --versionCode: only uninstall if the app has the given version code.");
3686 pw.println("");
3687 pw.println(" clear [--user USER_ID] PACKAGE");
3688 pw.println(" Deletes all data associated with a package.");
3689 pw.println("");
3690 pw.println(" enable [--user USER_ID] PACKAGE_OR_COMPONENT");
3691 pw.println(" disable [--user USER_ID] PACKAGE_OR_COMPONENT");
3692 pw.println(" disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
3693 pw.println(" disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
3694 pw.println(" default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
3695 pw.println(" These commands change the enabled state of a given package or");
3696 pw.println(" component (written as \"package/class\").");
3697 pw.println("");
3698 pw.println(" hide [--user USER_ID] PACKAGE_OR_COMPONENT");
3699 pw.println(" unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
3700 pw.println("");
3701 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE");
3702 pw.println(" Suspends the specified package (as user).");
3703 pw.println("");
3704 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE");
3705 pw.println(" Unsuspends the specified package (as user).");
3706 pw.println("");
3707 pw.println(" grant [--user USER_ID] PACKAGE PERMISSION");
3708 pw.println(" revoke [--user USER_ID] PACKAGE PERMISSION");
3709 pw.println(" These commands either grant or revoke permissions to apps. The permissions");
3710 pw.println(" must be declared as used in the app's manifest, be runtime permissions");
3711 pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
3712 pw.println("");
3713 pw.println(" reset-permissions");
3714 pw.println(" Revert all runtime permissions to their default state.");
3715 pw.println("");
3716 pw.println(" set-permission-enforced PERMISSION [true|false]");
3717 pw.println("");
3718 pw.println(" get-privapp-permissions TARGET-PACKAGE");
3719 pw.println(" Prints all privileged permissions for a package.");
3720 pw.println("");
3721 pw.println(" get-privapp-deny-permissions TARGET-PACKAGE");
3722 pw.println(" Prints all privileged permissions that are denied for a package.");
3723 pw.println("");
3724 pw.println(" get-oem-permissions TARGET-PACKAGE");
3725 pw.println(" Prints all OEM permissions for a package.");
3726 pw.println("");
3727 pw.println(" set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
3728 pw.println(" get-app-link [--user USER_ID] PACKAGE");
3729 pw.println("");
3730 pw.println(" trim-caches DESIRED_FREE_SPACE [internal|UUID]");
3731 pw.println(" Trim cache files to reach the given free space.");
3732 pw.println("");
Felipe Lemec1ca4412019-09-11 09:23:26 -07003733 pw.println(" list users");
3734 pw.println(" Lists the current users.");
3735 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003736 pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
Bookatz029832a2019-10-04 16:50:22 -07003737 pw.println(" [--guest] [--pre-create-only] [--user-type USER_TYPE] USER_NAME");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003738 pw.println(" Create a new user with the given USER_NAME, printing the new user identifier");
3739 pw.println(" of the user.");
Bookatz029832a2019-10-04 16:50:22 -07003740 // TODO(b/142482943): Consider fetching the list of user types from UMS.
3741 pw.println(" USER_TYPE is the name of a user type, e.g. android.os.usertype.profile.MANAGED.");
3742 pw.println(" If not specified, the default user type is android.os.usertype.full.SECONDARY.");
3743 pw.println(" --managed is shorthand for '--user-type android.os.usertype.profile.MANAGED'.");
3744 pw.println(" --restricted is shorthand for '--user-type android.os.usertype.full.RESTRICTED'.");
3745 pw.println(" --guest is shorthand for '--user-type android.os.usertype.full.GUEST'.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003746 pw.println("");
3747 pw.println(" remove-user USER_ID");
3748 pw.println(" Remove the user with the given USER_IDENTIFIER, deleting all data");
3749 pw.println(" associated with that user");
3750 pw.println("");
3751 pw.println(" set-user-restriction [--user USER_ID] RESTRICTION VALUE");
3752 pw.println("");
3753 pw.println(" get-max-users");
3754 pw.println("");
Alex Chauc12189b2018-01-16 15:01:15 +00003755 pw.println(" get-max-running-users");
3756 pw.println("");
Calin Juravleb6f844d2017-07-17 15:23:21 -07003757 pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
Richard Uhler568a9692016-05-03 16:02:52 -07003758 pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003759 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\". Options are:");
David Brazdil990fb6b2016-03-01 10:02:27 +00003760 pw.println(" -a: compile all packages");
David Brazdil9aa6db02016-03-08 12:57:12 +00003761 pw.println(" -c: clear profile data before compiling");
3762 pw.println(" -f: force compilation even if not needed");
David Brazdil493411a2016-02-01 13:48:46 +00003763 pw.println(" -m: select compilation mode");
Richard Uhler568a9692016-05-03 16:02:52 -07003764 pw.println(" MODE is one of the dex2oat compiler filters:");
Nicolas Geoffrayd1326522017-04-25 12:29:07 +01003765 pw.println(" assume-verified");
3766 pw.println(" extract");
3767 pw.println(" verify");
3768 pw.println(" quicken");
Richard Uhler568a9692016-05-03 16:02:52 -07003769 pw.println(" space-profile");
3770 pw.println(" space");
3771 pw.println(" speed-profile");
3772 pw.println(" speed");
3773 pw.println(" everything");
3774 pw.println(" -r: select compilation reason");
3775 pw.println(" REASON is one of:");
3776 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
3777 pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
3778 }
David Brazdilcf046952016-03-08 16:40:20 +00003779 pw.println(" --reset: restore package to its post-install state");
Richard Uhler568a9692016-05-03 16:02:52 -07003780 pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
Calin Juravlecb5f41e2017-01-25 17:16:08 -08003781 pw.println(" --secondary-dex: compile app secondary dex files");
Calin Juravleb6f844d2017-07-17 15:23:21 -07003782 pw.println(" --split SPLIT: compile only the given split name");
Eric Holka1485f62019-01-07 13:58:25 -08003783 pw.println(" --compile-layouts: compile layout resources for faster inflation");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003784 pw.println("");
3785 pw.println(" force-dex-opt PACKAGE");
3786 pw.println(" Force immediate execution of dex opt for the given PACKAGE.");
3787 pw.println("");
Calin Juravlecb5f41e2017-01-25 17:16:08 -08003788 pw.println(" bg-dexopt-job");
3789 pw.println(" Execute the background optimizations immediately.");
3790 pw.println(" Note that the command only runs the background optimizer logic. It may");
3791 pw.println(" overlap with the actual job but the job scheduler will not be able to");
3792 pw.println(" cancel it. It will also run even if the device is not in the idle");
3793 pw.println(" maintenance mode.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003794 pw.println("");
Calin Juravle1aa5f882017-01-25 01:05:50 -08003795 pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE");
3796 pw.println(" Reconciles the package secondary dex files with the generated oat files.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003797 pw.println("");
David Sehrcae13b02016-06-07 09:11:27 -07003798 pw.println(" dump-profiles TARGET-PACKAGE");
3799 pw.println(" Dumps method/class profile files to");
Calin Juravle21216c62018-05-04 17:35:29 -07003800 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + "TARGET-PACKAGE.txt");
3801 pw.println("");
3802 pw.println(" snapshot-profile TARGET-PACKAGE [--code-path path]");
3803 pw.println(" Take a snapshot of the package profiles to");
3804 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION
3805 + "TARGET-PACKAGE[-code-path].prof");
3806 pw.println(" If TARGET-PACKAGE=android it will take a snapshot of the boot image");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003807 pw.println("");
Makoto Onuki4828a592016-03-15 18:06:57 -07003808 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003809 pw.println(" Set the default home activity (aka launcher).");
Bookatz2b5a6012019-04-16 19:41:28 -07003810 pw.println(" TARGET-COMPONENT can be a package name (com.package.my) or a full");
3811 pw.println(" component (com.package.my/component.name). However, only the package name");
3812 pw.println(" matters: the actual component used will be determined automatically from");
3813 pw.println(" the package.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003814 pw.println("");
3815 pw.println(" set-installer PACKAGE INSTALLER");
3816 pw.println(" Set installer package name");
3817 pw.println("");
3818 pw.println(" get-instantapp-resolver");
3819 pw.println(" Return the name of the component that is the current instant app installer.");
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08003820 pw.println("");
3821 pw.println(" set-harmful-app-warning [--user <USER_ID>] <PACKAGE> [<WARNING>]");
3822 pw.println(" Mark the app as harmful with the given warning message.");
Ben Gruver9ef60092018-01-10 11:32:30 -08003823 pw.println("");
3824 pw.println(" get-harmful-app-warning [--user <USER_ID>] <PACKAGE>");
3825 pw.println(" Return the harmful app warning message for the given app, if present");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08003826 pw.println();
Patrick Baumanna980e142018-02-12 11:45:23 -08003827 pw.println(" uninstall-system-updates");
3828 pw.println(" Remove updates to all system applications and fall back to their /system " +
3829 "version.");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003830 pw.println("");
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +01003831 pw.println(" get-moduleinfo [--all | --installed] [module-name]");
3832 pw.println(" Displays module info. If module-name is specified only that info is shown");
3833 pw.println(" By default, without any argument only installed modules are shown.");
3834 pw.println(" --all: show all module info");
3835 pw.println(" --installed: show only installed modules");
3836 pw.println("");
Patrick Baumann4b491872020-02-25 11:51:44 -08003837 pw.println(" log-visibility [--enable|--disable] <PACKAGE>");
3838 pw.println(" Turns on debug logging when visibility is blocked for the given package.");
3839 pw.println(" --enable: turn on debug logging (default)");
3840 pw.println(" --disable: turn off debug logging");
3841 pw.println("");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08003842 Intent.printIntentArgsHelp(pw , "");
Todd Kennedy60459ab2015-10-30 11:32:16 -07003843 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003844
3845 private static class LocalIntentReceiver {
wangmingming155414292018-04-10 09:35:25 +08003846 private final LinkedBlockingQueue<Intent> mResult = new LinkedBlockingQueue<>();
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003847
3848 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
3849 @Override
Dianne Hackborn98305522017-05-05 17:53:53 -07003850 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003851 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
3852 try {
3853 mResult.offer(intent, 5, TimeUnit.SECONDS);
3854 } catch (InterruptedException e) {
3855 throw new RuntimeException(e);
3856 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003857 }
3858 };
3859
3860 public IntentSender getIntentSender() {
3861 return new IntentSender((IIntentSender) mLocalSender);
3862 }
3863
3864 public Intent getResult() {
3865 try {
3866 return mResult.take();
3867 } catch (InterruptedException e) {
3868 throw new RuntimeException(e);
3869 }
3870 }
3871 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07003872}