blob: c267cea163d5bd98e0b61e20cfbc5d6828941555 [file] [log] [blame]
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Todd Kennedy60459ab2015-10-30 11:32:16 -070017package com.android.server.pm;
18
Alex Buynytskyye0697872020-01-13 09:25:21 -080019import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
Jeff Sharkey0451de62018-02-02 11:27:21 -070020import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
21import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
22import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
23import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
24import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
25
Dianne Hackbornc81983a2017-10-20 16:16:32 -070026import android.accounts.IAccountManager;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080027import android.app.ActivityManager;
Alex Chauc12189b2018-01-16 15:01:15 +000028import android.app.ActivityManagerInternal;
Bookatz2b5a6012019-04-16 19:41:28 -070029import android.app.role.IRoleManager;
30import android.app.role.RoleManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -070031import android.content.ComponentName;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070032import android.content.Context;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080033import android.content.IIntentReceiver;
34import android.content.IIntentSender;
35import android.content.Intent;
36import android.content.IntentSender;
Todd Kennedy60459ab2015-10-30 11:32:16 -070037import android.content.pm.ApplicationInfo;
38import android.content.pm.FeatureInfo;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070039import android.content.pm.IPackageDataObserver;
Patrick Baumanna980e142018-02-12 11:45:23 -080040import android.content.pm.IPackageInstaller;
Todd Kennedy60459ab2015-10-30 11:32:16 -070041import android.content.pm.IPackageManager;
42import android.content.pm.InstrumentationInfo;
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +010043import android.content.pm.ModuleInfo;
Todd Kennedy60459ab2015-10-30 11:32:16 -070044import android.content.pm.PackageInfo;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080045import android.content.pm.PackageInstaller;
Abhijeet Kaur84b1f5d2019-01-21 17:18:03 +000046import android.content.pm.PackageInstaller.SessionInfo;
Jeff Sharkey0451de62018-02-02 11:27:21 -070047import android.content.pm.PackageInstaller.SessionParams;
Todd Kennedy60459ab2015-10-30 11:32:16 -070048import android.content.pm.PackageItemInfo;
49import android.content.pm.PackageManager;
Jeff Sharkey0451de62018-02-02 11:27:21 -070050import android.content.pm.PackageManager.NameNotFoundException;
Dario Freni788ecb12019-01-23 18:49:32 +000051import android.content.pm.PackageManagerInternal;
Shunta Sato4f26cb52016-06-28 09:29:19 +090052import android.content.pm.PackageParser.ApkLite;
53import android.content.pm.PackageParser.PackageLite;
54import android.content.pm.PackageParser.PackageParserException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070055import android.content.pm.ParceledListSlice;
56import android.content.pm.PermissionGroupInfo;
57import android.content.pm.PermissionInfo;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080058import android.content.pm.ResolveInfo;
Suprabh Shukla389cb6f2018-10-01 18:20:39 -070059import android.content.pm.SuspendDialogInfo;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070060import android.content.pm.UserInfo;
Svet Ganov67882122016-12-11 16:36:34 -080061import android.content.pm.VersionedPackage;
Calin Juravle21216c62018-05-04 17:35:29 -070062import android.content.pm.dex.ArtManager;
Calin Juravle3fc56c32017-12-11 18:26:13 -080063import android.content.pm.dex.DexMetadataHelper;
Calin Juravle21216c62018-05-04 17:35:29 -070064import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
Winson14ff7172019-10-23 10:42:27 -070065import android.content.pm.parsing.ApkLiteParseUtils;
Todd Kennedy60459ab2015-10-30 11:32:16 -070066import android.content.res.AssetManager;
67import android.content.res.Resources;
Narayan Kamathc5d752e2019-01-23 14:06:35 +000068import android.content.rollback.IRollbackManager;
69import android.content.rollback.PackageRollbackInfo;
70import android.content.rollback.RollbackInfo;
71import android.content.rollback.RollbackManager;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080072import android.net.Uri;
73import android.os.Binder;
74import android.os.Build;
75import android.os.Bundle;
Dianne Hackborn98305522017-05-05 17:53:53 -070076import android.os.IBinder;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070077import android.os.IUserManager;
Dianne Hackbornca3872c2017-10-30 14:19:32 -070078import android.os.ParcelFileDescriptor;
Calin Juravle21216c62018-05-04 17:35:29 -070079import android.os.ParcelFileDescriptor.AutoCloseInputStream;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080080import android.os.PersistableBundle;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070081import android.os.Process;
Bookatz2b5a6012019-04-16 19:41:28 -070082import android.os.RemoteCallback;
Todd Kennedy60459ab2015-10-30 11:32:16 -070083import android.os.RemoteException;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070084import android.os.ServiceManager;
Valentin Iftime89df4c82019-08-23 13:02:50 +020085import android.os.ServiceSpecificException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070086import android.os.ShellCommand;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070087import android.os.SystemClock;
Calin Juravle8bc758b2016-03-28 12:31:52 +010088import android.os.SystemProperties;
Todd Kennedy60459ab2015-10-30 11:32:16 -070089import android.os.UserHandle;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070090import android.os.UserManager;
Alex Buynytskyy8e9e6a32020-02-08 14:26:45 -080091import android.os.incremental.V4Signature;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070092import android.os.storage.StorageManager;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -070093import android.permission.IPermissionManager;
Calin Juravlebdd94d92018-05-17 01:23:15 -070094import android.system.ErrnoException;
95import android.system.Os;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080096import android.text.TextUtils;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070097import android.text.format.DateUtils;
Fyodor Kupolov51245c72016-12-01 11:34:10 -080098import android.util.ArraySet;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080099import android.util.PrintWriterPrinter;
Nikita Ioffebf883482019-08-08 22:09:31 +0100100import android.util.SparseArray;
Dario Freni2bef1762018-06-01 14:02:08 +0100101
Shunta Sato4f26cb52016-06-28 09:29:19 +0900102import com.android.internal.content.PackageHelper;
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700103import com.android.internal.util.ArrayUtils;
Nikita Ioffebf883482019-08-08 22:09:31 +0100104import com.android.internal.util.IndentingPrintWriter;
Alex Chauc12189b2018-01-16 15:01:15 +0000105import com.android.server.LocalServices;
Fyodor Kupolov51245c72016-12-01 11:34:10 -0800106import com.android.server.SystemConfig;
Dario Freni2bef1762018-06-01 14:02:08 +0100107
Andreas Gampebdd30d82016-03-20 11:32:11 -0700108import dalvik.system.DexFile;
Dario Freni2bef1762018-06-01 14:02:08 +0100109
110import libcore.io.IoUtils;
111import libcore.io.Streams;
112
Calin Juravle21216c62018-05-04 17:35:29 -0700113import java.io.File;
114import java.io.FileOutputStream;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800115import java.io.IOException;
Calin Juravle21216c62018-05-04 17:35:29 -0700116import java.io.InputStream;
117import java.io.OutputStream;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700118import java.io.PrintWriter;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800119import java.net.URISyntaxException;
Alex Buynytskyyda208152019-11-11 09:34:05 -0800120import java.nio.charset.StandardCharsets;
Calin Juravle21216c62018-05-04 17:35:29 -0700121import java.util.ArrayList;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000122import java.util.Collection;
Calin Juravle21216c62018-05-04 17:35:29 -0700123import java.util.Collections;
124import java.util.Comparator;
125import java.util.LinkedList;
126import java.util.List;
127import java.util.Map;
128import java.util.Objects;
129import java.util.WeakHashMap;
Bookatz2b5a6012019-04-16 19:41:28 -0700130import java.util.concurrent.CompletableFuture;
Calin Juravle21216c62018-05-04 17:35:29 -0700131import java.util.concurrent.CountDownLatch;
wangmingming155414292018-04-10 09:35:25 +0800132import java.util.concurrent.LinkedBlockingQueue;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800133import java.util.concurrent.TimeUnit;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700134
135class PackageManagerShellCommand extends ShellCommand {
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700136 /** Path for streaming APK content */
137 private static final String STDIN_PATH = "-";
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -0800138 private static final byte[] STDIN_PATH_BYTES = "-".getBytes(StandardCharsets.UTF_8);
Calin Juravle21216c62018-05-04 17:35:29 -0700139 /** Path where ART profiles snapshots are dumped for the shell user */
140 private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +0100141 private static final int DEFAULT_WAIT_MS = 60 * 1000;
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700142
Todd Kennedy60459ab2015-10-30 11:32:16 -0700143 final IPackageManager mInterface;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700144 final IPermissionManager mPermissionManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700145 final private WeakHashMap<String, Resources> mResourceCache =
146 new WeakHashMap<String, Resources>();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800147 int mTargetUser;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700148 boolean mBrief;
149 boolean mComponents;
Ng Zhi An73971312018-09-11 21:39:14 -0700150 int mQueryFlags;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700151
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700152 PackageManagerShellCommand(
153 PackageManagerService service, IPermissionManager permissionManager) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700154 mInterface = service;
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700155 mPermissionManager = permissionManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700156 }
157
158 @Override
159 public int onCommand(String cmd) {
160 if (cmd == null) {
161 return handleDefaultCommands(cmd);
162 }
163
164 final PrintWriter pw = getOutPrintWriter();
165 try {
Alex Buynytskyy476138c2019-12-20 14:41:47 -0800166 switch (cmd) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700167 case "path":
168 return runPath();
169 case "dump":
170 return runDump();
171 case "list":
172 return runList();
173 case "resolve-activity":
174 return runResolveActivity();
175 case "query-activities":
176 return runQueryIntentActivities();
177 case "query-services":
178 return runQueryIntentServices();
179 case "query-receivers":
180 return runQueryIntentReceivers();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800181 case "install":
182 return runInstall();
Alex Buynytskyyda208152019-11-11 09:34:05 -0800183 case "install-streaming":
184 return runStreamingInstall();
Alex Buynytskyy04f73912020-02-10 08:34:18 -0800185 case "install-incremental":
186 return runIncrementalInstall();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800187 case "install-abandon":
188 case "install-destroy":
189 return runInstallAbandon();
190 case "install-commit":
191 return runInstallCommit();
192 case "install-create":
193 return runInstallCreate();
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800194 case "install-remove":
195 return runInstallRemove();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800196 case "install-write":
197 return runInstallWrite();
Todd Kennedybe0b8892017-02-15 14:13:52 -0800198 case "install-existing":
199 return runInstallExisting();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700200 case "set-install-location":
201 return runSetInstallLocation();
202 case "get-install-location":
203 return runGetInstallLocation();
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000204 case "install-add-session":
205 return runInstallAddSession();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700206 case "move-package":
207 return runMovePackage();
208 case "move-primary-storage":
209 return runMovePrimaryStorage();
David Brazdil493411a2016-02-01 13:48:46 +0000210 case "compile":
211 return runCompile();
Calin Juravle1aa5f882017-01-25 01:05:50 -0800212 case "reconcile-secondary-dex-files":
213 return runreconcileSecondaryDexFiles();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700214 case "force-dex-opt":
215 return runForceDexOpt();
Calin Juravlecb5f41e2017-01-25 17:16:08 -0800216 case "bg-dexopt-job":
217 return runDexoptJob();
David Sehra8777082016-05-24 15:25:23 -0700218 case "dump-profiles":
219 return runDumpProfiles();
Calin Juravle21216c62018-05-04 17:35:29 -0700220 case "snapshot-profile":
221 return runSnapshotProfile();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800222 case "uninstall":
223 return runUninstall();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700224 case "clear":
225 return runClear();
226 case "enable":
227 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
228 case "disable":
229 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
230 case "disable-user":
231 return runSetEnabledSetting(
232 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
233 case "disable-until-used":
234 return runSetEnabledSetting(
235 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
236 case "default-state":
237 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
238 case "hide":
239 return runSetHiddenSetting(true);
240 case "unhide":
241 return runSetHiddenSetting(false);
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000242 case "suspend":
243 return runSuspend(true);
244 case "unsuspend":
245 return runSuspend(false);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700246 case "grant":
247 return runGrantRevokePermission(true);
248 case "revoke":
249 return runGrantRevokePermission(false);
250 case "reset-permissions":
251 return runResetPermissions();
252 case "set-permission-enforced":
253 return runSetPermissionEnforced();
Fyodor Kupolov51245c72016-12-01 11:34:10 -0800254 case "get-privapp-permissions":
255 return runGetPrivappPermissions();
Todd Kennedy74629e32017-08-15 14:48:07 -0700256 case "get-privapp-deny-permissions":
257 return runGetPrivappDenyPermissions();
Svet Ganov087dce22017-09-07 15:42:16 -0700258 case "get-oem-permissions":
259 return runGetOemPermissions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700260 case "set-app-link":
261 return runSetAppLink();
262 case "get-app-link":
263 return runGetAppLink();
264 case "trim-caches":
265 return runTrimCaches();
266 case "create-user":
267 return runCreateUser();
268 case "remove-user":
269 return runRemoveUser();
270 case "set-user-restriction":
271 return runSetUserRestriction();
272 case "get-max-users":
273 return runGetMaxUsers();
Alex Chauc12189b2018-01-16 15:01:15 +0000274 case "get-max-running-users":
275 return runGetMaxRunningUsers();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700276 case "set-home-activity":
277 return runSetHomeActivity();
278 case "set-installer":
279 return runSetInstaller();
Todd Kennedy0a3f0812017-05-08 14:43:15 -0700280 case "get-instantapp-resolver":
281 return runGetInstantAppResolver();
Tadashi G. Takaokabe5782f2017-02-14 16:41:49 +0900282 case "has-feature":
283 return runHasFeature();
Ben Gruver1ab3d6e2017-12-07 13:45:08 -0800284 case "set-harmful-app-warning":
285 return runSetHarmfulAppWarning();
Ben Gruver9ef60092018-01-10 11:32:30 -0800286 case "get-harmful-app-warning":
287 return runGetHarmfulAppWarning();
Abhijeet Kaur84b1f5d2019-01-21 17:18:03 +0000288 case "get-stagedsessions":
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100289 return runListStagedSessions();
Patrick Baumanna980e142018-02-12 11:45:23 -0800290 case "uninstall-system-updates":
291 return uninstallSystemUpdates();
Narayan Kamathc5d752e2019-01-23 14:06:35 +0000292 case "rollback-app":
293 return runRollbackApp();
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +0100294 case "get-moduleinfo":
295 return runGetModuleInfo();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700296 default: {
297 String nextArg = getNextArg();
298 if (nextArg == null) {
299 if (cmd.equalsIgnoreCase("-l")) {
300 return runListPackages(false);
301 } else if (cmd.equalsIgnoreCase("-lf")) {
302 return runListPackages(true);
303 }
304 } else if (getNextArg() == null) {
305 if (cmd.equalsIgnoreCase("-p")) {
306 return displayPackageFilePath(nextArg, UserHandle.USER_SYSTEM);
307 }
308 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700309 return handleDefaultCommands(cmd);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700310 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700311 }
312 } catch (RemoteException e) {
313 pw.println("Remote exception: " + e);
314 }
315 return -1;
316 }
317
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +0100318 /**
319 * Shows module info
320 *
321 * Usage: get-moduleinfo [--all | --installed] [module-name]
322 * Example: get-moduleinfo, get-moduleinfo --all, get-moduleinfo xyz
323 */
324 private int runGetModuleInfo() {
325 final PrintWriter pw = getOutPrintWriter();
326 int flags = 0;
327
328 String opt;
329 while ((opt = getNextOption()) != null) {
330 switch (opt) {
331 case "--all":
332 flags |= PackageManager.MATCH_ALL;
333 break;
334 case "--installed":
335 break;
336 default:
337 pw.println("Error: Unknown option: " + opt);
338 return -1;
339 }
340 }
341
342 String moduleName = getNextArg();
343 try {
344 if (moduleName != null) {
345 ModuleInfo m = mInterface.getModuleInfo(moduleName, flags);
346 pw.println(m.toString() + " packageName: " + m.getPackageName());
347
348 } else {
349 List<ModuleInfo> modules = mInterface.getInstalledModules(flags);
350 for (ModuleInfo m: modules) {
351 pw.println(m.toString() + " packageName: " + m.getPackageName());
352 }
353 }
354 } catch (RemoteException e) {
355 pw.println("Failure [" + e.getClass().getName() + " - " + e.getMessage() + "]");
356 return -1;
357 }
358 return 1;
359 }
360
Patrick Baumanna980e142018-02-12 11:45:23 -0800361 private int uninstallSystemUpdates() {
362 final PrintWriter pw = getOutPrintWriter();
363 List<String> failedUninstalls = new LinkedList<>();
364 try {
365 final ParceledListSlice<ApplicationInfo> packages =
366 mInterface.getInstalledApplications(
367 PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
368 final IPackageInstaller installer = mInterface.getPackageInstaller();
369 List<ApplicationInfo> list = packages.getList();
370 for (ApplicationInfo info : list) {
371 if (info.isUpdatedSystemApp()) {
372 pw.println("Uninstalling updates to " + info.packageName + "...");
373 final LocalIntentReceiver receiver = new LocalIntentReceiver();
374 installer.uninstall(new VersionedPackage(info.packageName,
375 info.versionCode), null /*callerPackageName*/, 0 /* flags */,
376 receiver.getIntentSender(), 0);
377
378 final Intent result = receiver.getResult();
379 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
380 PackageInstaller.STATUS_FAILURE);
381 if (status != PackageInstaller.STATUS_SUCCESS) {
382 failedUninstalls.add(info.packageName);
383 }
384 }
385 }
386 } catch (RemoteException e) {
387 pw.println("Failure ["
388 + e.getClass().getName() + " - "
389 + e.getMessage() + "]");
390 return 0;
391 }
392 if (!failedUninstalls.isEmpty()) {
393 pw.println("Failure [Couldn't uninstall packages: "
394 + TextUtils.join(", ", failedUninstalls)
395 + "]");
396 return 0;
397 }
398 pw.println("Success");
399 return 1;
400 }
401
Narayan Kamathc5d752e2019-01-23 14:06:35 +0000402 private int runRollbackApp() {
403 final PrintWriter pw = getOutPrintWriter();
404
405 final String packageName = getNextArgRequired();
406 if (packageName == null) {
407 pw.println("Error: package name not specified");
408 return 1;
409 }
410
411 final LocalIntentReceiver receiver = new LocalIntentReceiver();
412 try {
413 IRollbackManager rm = IRollbackManager.Stub.asInterface(
414 ServiceManager.getService(Context.ROLLBACK_SERVICE));
415
416 RollbackInfo rollback = null;
417 for (RollbackInfo r : (List<RollbackInfo>) rm.getAvailableRollbacks().getList()) {
418 for (PackageRollbackInfo info : r.getPackages()) {
419 if (packageName.equals(info.getPackageName())) {
420 rollback = r;
421 break;
422 }
423 }
424 }
425
426 if (rollback == null) {
427 pw.println("No available rollbacks for: " + packageName);
428 return 1;
429 }
430
431 rm.commitRollback(rollback.getRollbackId(),
432 ParceledListSlice.<VersionedPackage>emptyList(),
433 "com.android.shell", receiver.getIntentSender());
434 } catch (RemoteException re) {
435 // Cannot happen.
436 }
437
438 final Intent result = receiver.getResult();
439 final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
440 RollbackManager.STATUS_FAILURE);
441 if (status == RollbackManager.STATUS_SUCCESS) {
442 pw.println("Success");
443 return 0;
444 } else {
445 pw.println("Failure ["
446 + result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE) + "]");
447 return 1;
448 }
449 }
450
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000451 private void setParamsSize(InstallParams params, List<String> inPaths) {
452 if (params.sessionParams.sizeBytes != -1 || STDIN_PATH.equals(inPaths.get(0))) {
453 return;
454 }
455
456 long sessionSize = 0;
457
458 for (String inPath : inPaths) {
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700459 final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");
460 if (fd == null) {
461 getErrPrintWriter().println("Error: Can't open file: " + inPath);
462 throw new IllegalArgumentException("Error: Can't open file: " + inPath);
463 }
464 try {
Winson14ff7172019-10-23 10:42:27 -0700465 ApkLite baseApk = ApkLiteParseUtils.parseApkLite(fd.getFileDescriptor(), inPath, 0);
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700466 PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
467 null, null);
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000468 sessionSize += PackageHelper.calculateInstalledSize(pkgLite,
469 params.sessionParams.abiOverride, fd.getFileDescriptor());
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700470 } catch (PackageParserException | IOException e) {
471 getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath);
472 throw new IllegalArgumentException(
473 "Error: Failed to parse APK file: " + inPath, e);
474 } finally {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900475 try {
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700476 fd.close();
477 } catch (IOException e) {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900478 }
479 }
480 }
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -0800481
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +0000482 params.sessionParams.setSize(sessionSize);
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700483 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700484 /**
485 * Displays the package file for a package.
486 * @param pckg
487 */
488 private int displayPackageFilePath(String pckg, int userId) throws RemoteException {
Bill Lin7fd81af2019-10-04 00:31:21 +0800489 PackageInfo info = mInterface.getPackageInfo(pckg, PackageManager.MATCH_APEX, userId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700490 if (info != null && info.applicationInfo != null) {
491 final PrintWriter pw = getOutPrintWriter();
492 pw.print("package:");
493 pw.println(info.applicationInfo.sourceDir);
494 if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
495 for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
496 pw.print("package:");
497 pw.println(splitSourceDir);
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800498 }
499 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700500 return 0;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800501 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700502 return 1;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800503 }
504
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700505 private int runPath() throws RemoteException {
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000506 int userId = UserHandle.USER_SYSTEM;
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700507 String option = getNextOption();
508 if (option != null && option.equals("--user")) {
509 userId = UserHandle.parseUserArg(getNextArgRequired());
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000510 }
511
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700512 String pkg = getNextArgRequired();
513 if (pkg == null) {
514 getErrPrintWriter().println("Error: no package specified");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000515 return 1;
516 }
Todd Kennedyc3c52172019-11-26 13:20:59 -0800517 final int translatedUserId =
518 translateUserId(userId, UserHandle.USER_NULL, "runPath");
519 return displayPackageFilePath(pkg, translatedUserId);
David Sehra8777082016-05-24 15:25:23 -0700520 }
521
Todd Kennedy60459ab2015-10-30 11:32:16 -0700522 private int runList() throws RemoteException {
523 final PrintWriter pw = getOutPrintWriter();
524 final String type = getNextArg();
525 if (type == null) {
526 pw.println("Error: didn't specify type of data to list");
527 return -1;
528 }
529 switch(type) {
530 case "features":
531 return runListFeatures();
532 case "instrumentation":
533 return runListInstrumentation();
534 case "libraries":
535 return runListLibraries();
536 case "package":
537 case "packages":
538 return runListPackages(false /*showSourceDir*/);
539 case "permission-groups":
540 return runListPermissionGroups();
541 case "permissions":
542 return runListPermissions();
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100543 case "staged-sessions":
544 return runListStagedSessions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700545 case "users":
546 ServiceManager.getService("user").shellCommand(
547 getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
548 new String[] { "list" }, getShellCallback(), adoptResultReceiver());
549 return 0;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700550 }
551 pw.println("Error: unknown list type '" + type + "'");
552 return -1;
553 }
554
555 private int runListFeatures() throws RemoteException {
556 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700557 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700558
559 // sort by name
560 Collections.sort(list, new Comparator<FeatureInfo>() {
561 public int compare(FeatureInfo o1, FeatureInfo o2) {
562 if (o1.name == o2.name) return 0;
563 if (o1.name == null) return -1;
564 if (o2.name == null) return 1;
565 return o1.name.compareTo(o2.name);
566 }
567 });
568
569 final int count = (list != null) ? list.size() : 0;
570 for (int p = 0; p < count; p++) {
571 FeatureInfo fi = list.get(p);
572 pw.print("feature:");
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700573 if (fi.name != null) {
574 pw.print(fi.name);
575 if (fi.version > 0) {
576 pw.print("=");
577 pw.print(fi.version);
578 }
579 pw.println();
580 } else {
581 pw.println("reqGlEsVersion=0x"
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700582 + Integer.toHexString(fi.reqGlEsVersion));
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700583 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700584 }
585 return 0;
586 }
587
588 private int runListInstrumentation() throws RemoteException {
589 final PrintWriter pw = getOutPrintWriter();
590 boolean showSourceDir = false;
591 String targetPackage = null;
592
593 try {
594 String opt;
595 while ((opt = getNextArg()) != null) {
596 switch (opt) {
597 case "-f":
598 showSourceDir = true;
599 break;
600 default:
601 if (opt.charAt(0) != '-') {
602 targetPackage = opt;
603 } else {
604 pw.println("Error: Unknown option: " + opt);
605 return -1;
606 }
607 break;
608 }
609 }
610 } catch (RuntimeException ex) {
611 pw.println("Error: " + ex.toString());
612 return -1;
613 }
614
615 final List<InstrumentationInfo> list =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700616 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700617
618 // sort by target package
619 Collections.sort(list, new Comparator<InstrumentationInfo>() {
620 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
621 return o1.targetPackage.compareTo(o2.targetPackage);
622 }
623 });
624
625 final int count = (list != null) ? list.size() : 0;
626 for (int p = 0; p < count; p++) {
627 final InstrumentationInfo ii = list.get(p);
628 pw.print("instrumentation:");
629 if (showSourceDir) {
630 pw.print(ii.sourceDir);
631 pw.print("=");
632 }
633 final ComponentName cn = new ComponentName(ii.packageName, ii.name);
634 pw.print(cn.flattenToShortString());
635 pw.print(" (target=");
636 pw.print(ii.targetPackage);
637 pw.println(")");
638 }
639 return 0;
640 }
641
642 private int runListLibraries() throws RemoteException {
643 final PrintWriter pw = getOutPrintWriter();
644 final List<String> list = new ArrayList<String>();
645 final String[] rawList = mInterface.getSystemSharedLibraryNames();
646 for (int i = 0; i < rawList.length; i++) {
647 list.add(rawList[i]);
648 }
649
650 // sort by name
651 Collections.sort(list, new Comparator<String>() {
652 public int compare(String o1, String o2) {
653 if (o1 == o2) return 0;
654 if (o1 == null) return -1;
655 if (o2 == null) return 1;
656 return o1.compareTo(o2);
657 }
658 });
659
660 final int count = (list != null) ? list.size() : 0;
661 for (int p = 0; p < count; p++) {
662 String lib = list.get(p);
663 pw.print("library:");
664 pw.println(lib);
665 }
666 return 0;
667 }
668
669 private int runListPackages(boolean showSourceDir) throws RemoteException {
670 final PrintWriter pw = getOutPrintWriter();
671 int getFlags = 0;
672 boolean listDisabled = false, listEnabled = false;
673 boolean listSystem = false, listThirdParty = false;
674 boolean listInstaller = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700675 boolean showUid = false;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800676 boolean showVersionCode = false;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900677 boolean listApexOnly = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700678 int uid = -1;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700679 int userId = UserHandle.USER_SYSTEM;
680 try {
681 String opt;
682 while ((opt = getNextOption()) != null) {
683 switch (opt) {
684 case "-d":
685 listDisabled = true;
686 break;
687 case "-e":
688 listEnabled = true;
689 break;
Andreas Gampe1f110452018-06-04 11:47:48 -0700690 case "-a":
691 getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
692 getFlags |= PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS;
693 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700694 case "-f":
695 showSourceDir = true;
696 break;
697 case "-i":
698 listInstaller = true;
699 break;
700 case "-l":
701 // old compat
702 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700703 case "-s":
704 listSystem = true;
705 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700706 case "-U":
707 showUid = true;
708 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700709 case "-u":
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700710 getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700711 break;
712 case "-3":
713 listThirdParty = true;
714 break;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800715 case "--show-versioncode":
716 showVersionCode = true;
717 break;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900718 case "--apex-only":
719 getFlags |= PackageManager.MATCH_APEX;
720 listApexOnly = true;
721 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700722 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800723 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy60459ab2015-10-30 11:32:16 -0700724 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700725 case "--uid":
726 showUid = true;
727 uid = Integer.parseInt(getNextArgRequired());
728 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700729 default:
730 pw.println("Error: Unknown option: " + opt);
731 return -1;
732 }
733 }
734 } catch (RuntimeException ex) {
735 pw.println("Error: " + ex.toString());
736 return -1;
737 }
738
739 final String filter = getNextArg();
740
Todd Kennedy5385b512019-11-26 15:49:06 -0800741 if (userId == UserHandle.USER_ALL) {
742 getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
743 }
Todd Kennedyc3c52172019-11-26 13:20:59 -0800744 final int translatedUserId =
Todd Kennedy5385b512019-11-26 15:49:06 -0800745 translateUserId(userId, UserHandle.USER_SYSTEM, "runListPackages");
Todd Kennedy60459ab2015-10-30 11:32:16 -0700746 @SuppressWarnings("unchecked")
747 final ParceledListSlice<PackageInfo> slice =
Todd Kennedyc3c52172019-11-26 13:20:59 -0800748 mInterface.getInstalledPackages(getFlags, translatedUserId);
Todd Kennedy60459ab2015-10-30 11:32:16 -0700749 final List<PackageInfo> packages = slice.getList();
750
751 final int count = packages.size();
752 for (int p = 0; p < count; p++) {
753 final PackageInfo info = packages.get(p);
754 if (filter != null && !info.packageName.contains(filter)) {
755 continue;
756 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900757 final boolean isApex = info.isApex;
758 if (uid != -1 && !isApex && info.applicationInfo.uid != uid) {
Felipe Lemeeece9862016-06-29 11:45:03 -0700759 continue;
760 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900761
762 final boolean isSystem = !isApex &&
Todd Kennedy60459ab2015-10-30 11:32:16 -0700763 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900764 final boolean isEnabled = !isApex && info.applicationInfo.enabled;
765 if ((!listDisabled || !isEnabled) &&
766 (!listEnabled || isEnabled) &&
Todd Kennedy60459ab2015-10-30 11:32:16 -0700767 (!listSystem || isSystem) &&
Jiyong Park4f49abe2018-12-11 13:37:17 +0900768 (!listThirdParty || !isSystem) &&
769 (!listApexOnly || isApex)) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700770 pw.print("package:");
JW Wang9a722632019-09-30 10:42:30 +0800771 if (showSourceDir) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700772 pw.print(info.applicationInfo.sourceDir);
773 pw.print("=");
774 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800775 pw.print(info.packageName);
Jiyong Parkf50a2932018-12-17 13:54:40 +0900776 if (showVersionCode) {
Todd Kennedybadc69a2017-01-24 11:05:47 -0800777 pw.print(" versionCode:");
Jiyong Parkf50a2932018-12-17 13:54:40 +0900778 if (info.applicationInfo != null) {
Dario Freni788ecb12019-01-23 18:49:32 +0000779 pw.print(info.applicationInfo.longVersionCode);
Jiyong Parkf50a2932018-12-17 13:54:40 +0900780 } else {
Dario Freni788ecb12019-01-23 18:49:32 +0000781 pw.print(info.getLongVersionCode());
Jiyong Parkf50a2932018-12-17 13:54:40 +0900782 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800783 }
Mohammad Samiul Islam6b7ad942019-05-07 20:28:00 +0100784 if (listInstaller) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700785 pw.print(" installer=");
786 pw.print(mInterface.getInstallerPackageName(info.packageName));
787 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900788 if (showUid && !isApex) {
Felipe Lemeeece9862016-06-29 11:45:03 -0700789 pw.print(" uid:");
790 pw.print(info.applicationInfo.uid);
791 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700792 pw.println();
793 }
794 }
795 return 0;
796 }
797
798 private int runListPermissionGroups() throws RemoteException {
799 final PrintWriter pw = getOutPrintWriter();
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700800 final List<PermissionGroupInfo> pgs =
801 mPermissionManager.getAllPermissionGroups(0).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700802
803 final int count = pgs.size();
804 for (int p = 0; p < count ; p++) {
805 final PermissionGroupInfo pgi = pgs.get(p);
806 pw.print("permission group:");
807 pw.println(pgi.name);
808 }
809 return 0;
810 }
811
812 private int runListPermissions() throws RemoteException {
813 final PrintWriter pw = getOutPrintWriter();
814 boolean labels = false;
815 boolean groups = false;
816 boolean userOnly = false;
817 boolean summary = false;
818 boolean dangerousOnly = false;
819 String opt;
820 while ((opt = getNextOption()) != null) {
821 switch (opt) {
822 case "-d":
823 dangerousOnly = true;
824 break;
825 case "-f":
826 labels = true;
827 break;
828 case "-g":
829 groups = true;
830 break;
831 case "-s":
832 groups = true;
833 labels = true;
834 summary = true;
835 break;
836 case "-u":
837 userOnly = true;
838 break;
839 default:
840 pw.println("Error: Unknown option: " + opt);
841 return 1;
842 }
843 }
844
845 final ArrayList<String> groupList = new ArrayList<String>();
846 if (groups) {
847 final List<PermissionGroupInfo> infos =
Todd Kennedy1d29b4a2019-07-02 14:49:28 -0700848 mPermissionManager.getAllPermissionGroups(0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700849 final int count = infos.size();
850 for (int i = 0; i < count; i++) {
851 groupList.add(infos.get(i).name);
852 }
853 groupList.add(null);
854 } else {
855 final String grp = getNextArg();
856 groupList.add(grp);
857 }
858
859 if (dangerousOnly) {
860 pw.println("Dangerous Permissions:");
861 pw.println("");
862 doListPermissions(groupList, groups, labels, summary,
863 PermissionInfo.PROTECTION_DANGEROUS,
864 PermissionInfo.PROTECTION_DANGEROUS);
865 if (userOnly) {
866 pw.println("Normal Permissions:");
867 pw.println("");
868 doListPermissions(groupList, groups, labels, summary,
869 PermissionInfo.PROTECTION_NORMAL,
870 PermissionInfo.PROTECTION_NORMAL);
871 }
872 } else if (userOnly) {
873 pw.println("Dangerous and Normal Permissions:");
874 pw.println("");
875 doListPermissions(groupList, groups, labels, summary,
876 PermissionInfo.PROTECTION_NORMAL,
877 PermissionInfo.PROTECTION_DANGEROUS);
878 } else {
879 pw.println("All Permissions:");
880 pw.println("");
881 doListPermissions(groupList, groups, labels, summary,
882 -10000, 10000);
883 }
884 return 0;
885 }
886
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100887 private static class SessionDump {
888 boolean onlyParent; // Show parent sessions only
889 boolean onlyReady; // Show only staged sessions that are in ready state
890 boolean onlySessionId; // Show sessionId only
891 }
892
893 // Returns true if the provided flag is a session flag and given SessionDump was updated
894 private boolean setSessionFlag(String flag, SessionDump sessionDump) {
895 switch (flag) {
896 case "--only-parent":
897 sessionDump.onlyParent = true;
898 break;
899 case "--only-ready":
900 sessionDump.onlyReady = true;
901 break;
902 case "--only-sessionid":
903 sessionDump.onlySessionId = true;
904 break;
905 default:
906 return false;
907 }
908 return true;
909 }
910
911 private int runListStagedSessions() {
Todd Kennedy5385b512019-11-26 15:49:06 -0800912 try (IndentingPrintWriter pw = new IndentingPrintWriter(
913 getOutPrintWriter(), /* singleIndent */ " ", /* wrapLength */ 120)) {
914 final SessionDump sessionDump = new SessionDump();
915 String opt;
916 while ((opt = getNextOption()) != null) {
917 if (!setSessionFlag(opt, sessionDump)) {
918 pw.println("Error: Unknown option: " + opt);
919 return -1;
920 }
921 }
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100922
Todd Kennedy5385b512019-11-26 15:49:06 -0800923 try {
924 final List<SessionInfo> stagedSessions =
925 mInterface.getPackageInstaller().getStagedSessions().getList();
926 printSessionList(pw, stagedSessions, sessionDump);
927 } catch (RemoteException e) {
928 pw.println("Failure ["
929 + e.getClass().getName() + " - "
930 + e.getMessage() + "]");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100931 return -1;
932 }
Todd Kennedy5385b512019-11-26 15:49:06 -0800933 return 1;
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100934 }
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +0100935 }
936
937 private void printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions,
938 SessionDump sessionDump) {
939 final SparseArray<SessionInfo> sessionById = new SparseArray<>(stagedSessions.size());
940 for (SessionInfo session : stagedSessions) {
941 sessionById.put(session.getSessionId(), session);
942 }
943 for (SessionInfo session: stagedSessions) {
944 if (sessionDump.onlyReady && !session.isStagedSessionReady()) {
945 continue;
946 }
947 if (session.getParentSessionId() != SessionInfo.INVALID_ID) {
948 continue;
949 }
950 printSession(pw, session, sessionDump);
951 if (session.isMultiPackage() && !sessionDump.onlyParent) {
952 pw.increaseIndent();
953 final int[] childIds = session.getChildSessionIds();
954 for (int i = 0; i < childIds.length; i++) {
955 final SessionInfo childSession = sessionById.get(childIds[i]);
956 if (childSession == null) {
957 if (sessionDump.onlySessionId) {
958 pw.println(childIds[i]);
959 } else {
960 pw.println("sessionId = " + childIds[i] + "; not found");
961 }
962 } else {
963 printSession(pw, childSession, sessionDump);
964 }
965 }
966 pw.decreaseIndent();
967 }
968 }
969 }
970
971 private static void printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump) {
972 if (sessionDump.onlySessionId) {
973 pw.println(session.getSessionId());
974 return;
975 }
976 pw.println("sessionId = " + session.getSessionId()
977 + "; appPackageName = " + session.getAppPackageName()
978 + "; isStaged = " + session.isStaged()
979 + "; isReady = " + session.isStagedSessionReady()
980 + "; isApplied = " + session.isStagedSessionApplied()
981 + "; isFailed = " + session.isStagedSessionFailed() + ";");
982 }
983
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800984 private Intent parseIntentAndUser() throws URISyntaxException {
985 mTargetUser = UserHandle.USER_CURRENT;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700986 mBrief = false;
987 mComponents = false;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800988 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
989 @Override
990 public boolean handleOption(String opt, ShellCommand cmd) {
991 if ("--user".equals(opt)) {
992 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
993 return true;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700994 } else if ("--brief".equals(opt)) {
995 mBrief = true;
996 return true;
997 } else if ("--components".equals(opt)) {
998 mComponents = true;
999 return true;
Ng Zhi An73971312018-09-11 21:39:14 -07001000 } else if ("--query-flags".equals(opt)) {
1001 mQueryFlags = Integer.decode(cmd.getNextArgRequired());
1002 return true;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001003 }
1004 return false;
1005 }
1006 });
1007 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1008 Binder.getCallingUid(), mTargetUser, false, false, null, null);
1009 return intent;
1010 }
1011
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001012 private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri,
1013 boolean brief, boolean components) {
1014 if (brief || components) {
1015 final ComponentName comp;
1016 if (ri.activityInfo != null) {
1017 comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
1018 } else if (ri.serviceInfo != null) {
1019 comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
1020 } else if (ri.providerInfo != null) {
1021 comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name);
1022 } else {
1023 comp = null;
1024 }
1025 if (comp != null) {
1026 if (!components) {
1027 pr.println(prefix + "priority=" + ri.priority
1028 + " preferredOrder=" + ri.preferredOrder
1029 + " match=0x" + Integer.toHexString(ri.match)
1030 + " specificIndex=" + ri.specificIndex
1031 + " isDefault=" + ri.isDefault);
1032 }
1033 pr.println(prefix + comp.flattenToShortString());
1034 return;
1035 }
1036 }
1037 ri.dump(pr, prefix);
1038 }
1039
Dianne Hackborn99878e92015-12-02 16:27:41 -08001040 private int runResolveActivity() {
1041 Intent intent;
1042 try {
1043 intent = parseIntentAndUser();
1044 } catch (URISyntaxException e) {
1045 throw new RuntimeException(e.getMessage(), e);
1046 }
1047 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001048 ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), mQueryFlags,
1049 mTargetUser);
Dianne Hackborn99878e92015-12-02 16:27:41 -08001050 PrintWriter pw = getOutPrintWriter();
1051 if (ri == null) {
1052 pw.println("No activity found");
1053 } else {
1054 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001055 printResolveInfo(pr, "", ri, mBrief, mComponents);
Dianne Hackborn99878e92015-12-02 16:27:41 -08001056 }
1057 } catch (RemoteException e) {
1058 throw new RuntimeException("Failed calling service", e);
1059 }
1060 return 0;
1061 }
1062
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001063 private int runQueryIntentActivities() {
1064 Intent intent;
1065 try {
1066 intent = parseIntentAndUser();
1067 } catch (URISyntaxException e) {
1068 throw new RuntimeException(e.getMessage(), e);
1069 }
1070 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001071 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(),
1072 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001073 PrintWriter pw = getOutPrintWriter();
1074 if (result == null || result.size() <= 0) {
1075 pw.println("No activities found");
1076 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001077 if (!mComponents) {
1078 pw.print(result.size()); pw.println(" activities found:");
1079 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1080 for (int i = 0; i < result.size(); i++) {
1081 pw.print(" Activity #"); pw.print(i); pw.println(":");
1082 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1083 }
1084 } else {
1085 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1086 for (int i = 0; i < result.size(); i++) {
1087 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1088 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001089 }
1090 }
1091 } catch (RemoteException e) {
1092 throw new RuntimeException("Failed calling service", e);
1093 }
1094 return 0;
1095 }
1096
1097 private int runQueryIntentServices() {
1098 Intent intent;
1099 try {
1100 intent = parseIntentAndUser();
1101 } catch (URISyntaxException e) {
1102 throw new RuntimeException(e.getMessage(), e);
1103 }
1104 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001105 List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(),
1106 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001107 PrintWriter pw = getOutPrintWriter();
1108 if (result == null || result.size() <= 0) {
1109 pw.println("No services found");
1110 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001111 if (!mComponents) {
1112 pw.print(result.size()); pw.println(" services found:");
1113 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1114 for (int i = 0; i < result.size(); i++) {
1115 pw.print(" Service #"); pw.print(i); pw.println(":");
1116 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1117 }
1118 } else {
1119 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1120 for (int i = 0; i < result.size(); i++) {
1121 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1122 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001123 }
1124 }
1125 } catch (RemoteException e) {
1126 throw new RuntimeException("Failed calling service", e);
1127 }
1128 return 0;
1129 }
1130
1131 private int runQueryIntentReceivers() {
1132 Intent intent;
1133 try {
1134 intent = parseIntentAndUser();
1135 } catch (URISyntaxException e) {
1136 throw new RuntimeException(e.getMessage(), e);
1137 }
1138 try {
Ng Zhi An73971312018-09-11 21:39:14 -07001139 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(),
1140 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001141 PrintWriter pw = getOutPrintWriter();
1142 if (result == null || result.size() <= 0) {
1143 pw.println("No receivers found");
1144 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001145 if (!mComponents) {
1146 pw.print(result.size()); pw.println(" receivers found:");
1147 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1148 for (int i = 0; i < result.size(); i++) {
1149 pw.print(" Receiver #"); pw.print(i); pw.println(":");
1150 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1151 }
1152 } else {
1153 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1154 for (int i = 0; i < result.size(); i++) {
1155 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1156 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001157 }
1158 }
1159 } catch (RemoteException e) {
1160 throw new RuntimeException("Failed calling service", e);
1161 }
1162 return 0;
1163 }
1164
Alex Buynytskyyda208152019-11-11 09:34:05 -08001165 private int runStreamingInstall() throws RemoteException {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001166 final InstallParams params = makeInstallParams();
Alex Buynytskyy1ecfcec2019-12-17 12:10:41 -08001167 if (params.sessionParams.dataLoaderParams == null) {
Alex Buynytskyy476138c2019-12-20 14:41:47 -08001168 params.sessionParams.setDataLoaderParams(
Alex Buynytskyycd4d3872020-02-08 17:50:50 -08001169 PackageManagerShellCommandDataLoader.getStreamingDataLoaderParams(this));
Alex Buynytskyyda208152019-11-11 09:34:05 -08001170 }
1171 return doRunInstall(params);
1172 }
1173
Alex Buynytskyy04f73912020-02-10 08:34:18 -08001174 private int runIncrementalInstall() throws RemoteException {
1175 final InstallParams params = makeInstallParams();
1176 if (params.sessionParams.dataLoaderParams == null) {
1177 params.sessionParams.setDataLoaderParams(
1178 PackageManagerShellCommandDataLoader.getIncrementalDataLoaderParams(this));
1179 }
1180 return doRunInstall(params);
1181 }
1182
Alex Buynytskyyda208152019-11-11 09:34:05 -08001183 private int runInstall() throws RemoteException {
1184 return doRunInstall(makeInstallParams());
1185 }
1186
1187 private int doRunInstall(final InstallParams params) throws RemoteException {
1188 final PrintWriter pw = getOutPrintWriter();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001189
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001190 final boolean isStreaming = params.sessionParams.dataLoaderParams != null;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001191 final boolean isApex =
1192 (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0;
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001193
1194 ArrayList<String> args = getRemainingArgs();
1195
1196 final boolean fromStdIn = args.isEmpty() || STDIN_PATH.equals(args.get(0));
1197 final boolean hasSplits = args.size() > 1;
1198
1199 if (fromStdIn && params.sessionParams.sizeBytes == -1) {
1200 pw.println("Error: must either specify a package size or an APK file");
1201 return 1;
1202 }
1203
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001204 if (isApex && hasSplits) {
1205 pw.println("Error: can't specify SPLIT(s) for APEX");
1206 return 1;
1207 }
1208
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001209 if (!isStreaming) {
1210 if (fromStdIn && hasSplits) {
1211 pw.println("Error: can't specify SPLIT(s) along with STDIN");
1212 return 1;
1213 }
1214
1215 if (args.isEmpty()) {
1216 args.add(STDIN_PATH);
1217 } else {
1218 setParamsSize(params, args);
1219 }
Alex Buynytskyyda208152019-11-11 09:34:05 -08001220 }
1221
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001222 final int sessionId = doCreateSession(params.sessionParams,
1223 params.installerPackageName, params.userId);
1224 boolean abandonSession = true;
1225 try {
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08001226 if (isStreaming) {
1227 if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex)
1228 != PackageInstaller.STATUS_SUCCESS) {
1229 return 1;
1230 }
1231 } else {
1232 if (doWriteSplits(sessionId, args, params.sessionParams.sizeBytes, isApex)
1233 != PackageInstaller.STATUS_SUCCESS) {
1234 return 1;
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001235 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001236 }
1237 if (doCommitSession(sessionId, false /*logSuccess*/)
1238 != PackageInstaller.STATUS_SUCCESS) {
1239 return 1;
1240 }
1241 abandonSession = false;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01001242
Nikita Ioffe62d918c2020-01-18 01:20:42 +00001243 if (!params.sessionParams.isStaged || !params.mWaitForStagedSessionReady) {
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01001244 pw.println("Success");
1245 return 0;
1246 }
1247
1248 long timeoutMs = params.timeoutMs <= 0
1249 ? DEFAULT_WAIT_MS
1250 : params.timeoutMs;
1251 PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
1252 .getSessionInfo(sessionId);
1253 long currentTime = System.currentTimeMillis();
1254 long endTime = currentTime + timeoutMs;
1255 // Using a loop instead of BroadcastReceiver since we can receive session update
1256 // broadcast only if packageInstallerName is "android". We can't always force
1257 // "android" as packageIntallerName, e.g, rollback auto implies
1258 // "-i com.android.shell".
1259 while (currentTime < endTime) {
1260 if (si != null
1261 && (si.isStagedSessionReady() || si.isStagedSessionFailed())) {
1262 break;
1263 }
1264 SystemClock.sleep(Math.min(endTime - currentTime, 100));
1265 currentTime = System.currentTimeMillis();
1266 si = mInterface.getPackageInstaller().getSessionInfo(sessionId);
1267 }
1268 if (si == null) {
1269 pw.println("Failure [failed to retrieve SessionInfo]");
1270 return 1;
1271 }
1272 if (!si.isStagedSessionReady() && !si.isStagedSessionFailed()) {
1273 pw.println("Failure [timed out after " + timeoutMs + " ms]");
1274 return 1;
1275 }
1276 if (!si.isStagedSessionReady()) {
1277 pw.println("Error [" + si.getStagedSessionErrorCode() + "] ["
1278 + si.getStagedSessionErrorMessage() + "]");
1279 return 1;
1280 }
Nikita Ioffe62d918c2020-01-18 01:20:42 +00001281 pw.println("Success. Reboot device to apply staged session");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001282 return 0;
1283 } finally {
1284 if (abandonSession) {
1285 try {
1286 doAbandonSession(sessionId, false /*logSuccess*/);
1287 } catch (Exception ignore) {
1288 }
1289 }
1290 }
1291 }
1292
1293 private int runInstallAbandon() throws RemoteException {
1294 final int sessionId = Integer.parseInt(getNextArg());
1295 return doAbandonSession(sessionId, true /*logSuccess*/);
1296 }
1297
1298 private int runInstallCommit() throws RemoteException {
1299 final int sessionId = Integer.parseInt(getNextArg());
1300 return doCommitSession(sessionId, true /*logSuccess*/);
1301 }
1302
1303 private int runInstallCreate() throws RemoteException {
1304 final PrintWriter pw = getOutPrintWriter();
1305 final InstallParams installParams = makeInstallParams();
1306 final int sessionId = doCreateSession(installParams.sessionParams,
1307 installParams.installerPackageName, installParams.userId);
1308
1309 // NOTE: adb depends on parsing this string
1310 pw.println("Success: created install session [" + sessionId + "]");
1311 return 0;
1312 }
1313
1314 private int runInstallWrite() throws RemoteException {
1315 long sizeBytes = -1;
1316
1317 String opt;
1318 while ((opt = getNextOption()) != null) {
1319 if (opt.equals("-S")) {
1320 sizeBytes = Long.parseLong(getNextArg());
1321 } else {
1322 throw new IllegalArgumentException("Unknown option: " + opt);
1323 }
1324 }
1325
1326 final int sessionId = Integer.parseInt(getNextArg());
1327 final String splitName = getNextArg();
1328 final String path = getNextArg();
1329 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
1330 }
1331
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001332 private int runInstallAddSession() throws RemoteException {
1333 final PrintWriter pw = getOutPrintWriter();
1334 final int parentSessionId = Integer.parseInt(getNextArg());
1335
1336 List<Integer> otherSessionIds = new ArrayList<>();
1337 String opt;
1338 while ((opt = getNextArg()) != null) {
1339 otherSessionIds.add(Integer.parseInt(opt));
1340 }
1341 if (otherSessionIds.size() == 0) {
1342 pw.println("Error: At least two sessions are required.");
1343 return 1;
1344 }
1345 return doInstallAddSession(parentSessionId, ArrayUtils.convertToIntArray(otherSessionIds),
1346 true /*logSuccess*/);
1347 }
1348
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001349 private int runInstallRemove() throws RemoteException {
1350 final PrintWriter pw = getOutPrintWriter();
1351
1352 final int sessionId = Integer.parseInt(getNextArg());
1353
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001354 ArrayList<String> splitNames = getRemainingArgs();
1355 if (splitNames.isEmpty()) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001356 pw.println("Error: split name not specified");
1357 return 1;
1358 }
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001359 return doRemoveSplits(sessionId, splitNames, true /*logSuccess*/);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001360 }
1361
1362 private int runInstallExisting() throws RemoteException {
1363 final PrintWriter pw = getOutPrintWriter();
Todd Kennedybef39e02019-09-20 15:14:18 -07001364 int userId = UserHandle.USER_CURRENT;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001365 int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001366 String opt;
Chandan Nathe8e463b2019-01-28 15:23:38 +00001367 boolean waitTillComplete = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001368 while ((opt = getNextOption()) != null) {
1369 switch (opt) {
1370 case "--user":
1371 userId = UserHandle.parseUserArg(getNextArgRequired());
1372 break;
1373 case "--ephemeral":
1374 case "--instant":
1375 installFlags |= PackageManager.INSTALL_INSTANT_APP;
1376 installFlags &= ~PackageManager.INSTALL_FULL_APP;
1377 break;
1378 case "--full":
1379 installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1380 installFlags |= PackageManager.INSTALL_FULL_APP;
1381 break;
Chandan Nathe8e463b2019-01-28 15:23:38 +00001382 case "--wait":
1383 waitTillComplete = true;
1384 break;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001385 case "--restrict-permissions":
1386 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1387 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001388 default:
1389 pw.println("Error: Unknown option: " + opt);
1390 return 1;
1391 }
1392 }
1393
1394 final String packageName = getNextArg();
1395 if (packageName == null) {
1396 pw.println("Error: package name not specified");
1397 return 1;
1398 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08001399 final int translatedUserId =
1400 translateUserId(userId, UserHandle.USER_NULL, "runInstallExisting");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001401
Chandan Nathe8e463b2019-01-28 15:23:38 +00001402 int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001403 try {
Chandan Nathe8e463b2019-01-28 15:23:38 +00001404 if (waitTillComplete) {
1405 final LocalIntentReceiver receiver = new LocalIntentReceiver();
1406 final IPackageInstaller installer = mInterface.getPackageInstaller();
Todd Kennedyc3c52172019-11-26 13:20:59 -08001407 pw.println("Installing package " + packageName + " for user: " + translatedUserId);
Chandan Nathe8e463b2019-01-28 15:23:38 +00001408 installer.installExistingPackage(packageName, installFlags, installReason,
Todd Kennedyc3c52172019-11-26 13:20:59 -08001409 receiver.getIntentSender(), translatedUserId, null);
Chandan Nathe8e463b2019-01-28 15:23:38 +00001410 final Intent result = receiver.getResult();
1411 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1412 PackageInstaller.STATUS_FAILURE);
1413 pw.println("Received intent for package install");
1414 return status == PackageInstaller.STATUS_SUCCESS ? 0 : 1;
1415 }
1416
Todd Kennedyc3c52172019-11-26 13:20:59 -08001417 final int res = mInterface.installExistingPackageAsUser(packageName, translatedUserId,
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07001418 installFlags, installReason, null);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001419 if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
1420 throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1421 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08001422 pw.println("Package " + packageName + " installed for user: " + translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001423 return 0;
1424 } catch (RemoteException | NameNotFoundException e) {
1425 pw.println(e.toString());
1426 return 1;
1427 }
1428 }
1429
1430 private int runSetInstallLocation() throws RemoteException {
1431 int loc;
1432
1433 String arg = getNextArg();
1434 if (arg == null) {
1435 getErrPrintWriter().println("Error: no install location specified.");
1436 return 1;
1437 }
1438 try {
1439 loc = Integer.parseInt(arg);
1440 } catch (NumberFormatException e) {
1441 getErrPrintWriter().println("Error: install location has to be a number.");
1442 return 1;
1443 }
1444 if (!mInterface.setInstallLocation(loc)) {
1445 getErrPrintWriter().println("Error: install location has to be a number.");
1446 return 1;
1447 }
1448 return 0;
1449 }
1450
1451 private int runGetInstallLocation() throws RemoteException {
1452 int loc = mInterface.getInstallLocation();
1453 String locStr = "invalid";
1454 if (loc == PackageHelper.APP_INSTALL_AUTO) {
1455 locStr = "auto";
1456 } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
1457 locStr = "internal";
1458 } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
1459 locStr = "external";
1460 }
1461 getOutPrintWriter().println(loc + "[" + locStr + "]");
1462 return 0;
1463 }
1464
1465 public int runMovePackage() throws RemoteException {
1466 final String packageName = getNextArg();
1467 if (packageName == null) {
1468 getErrPrintWriter().println("Error: package name not specified");
1469 return 1;
1470 }
1471 String volumeUuid = getNextArg();
1472 if ("internal".equals(volumeUuid)) {
1473 volumeUuid = null;
1474 }
1475
1476 final int moveId = mInterface.movePackage(packageName, volumeUuid);
1477
1478 int status = mInterface.getMoveStatus(moveId);
1479 while (!PackageManager.isMoveStatusFinished(status)) {
1480 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1481 status = mInterface.getMoveStatus(moveId);
1482 }
1483
1484 if (status == PackageManager.MOVE_SUCCEEDED) {
1485 getOutPrintWriter().println("Success");
1486 return 0;
1487 } else {
1488 getErrPrintWriter().println("Failure [" + status + "]");
1489 return 1;
1490 }
1491 }
1492
1493 public int runMovePrimaryStorage() throws RemoteException {
1494 String volumeUuid = getNextArg();
1495 if ("internal".equals(volumeUuid)) {
1496 volumeUuid = null;
1497 }
1498
1499 final int moveId = mInterface.movePrimaryStorage(volumeUuid);
1500
1501 int status = mInterface.getMoveStatus(moveId);
1502 while (!PackageManager.isMoveStatusFinished(status)) {
1503 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1504 status = mInterface.getMoveStatus(moveId);
1505 }
1506
1507 if (status == PackageManager.MOVE_SUCCEEDED) {
1508 getOutPrintWriter().println("Success");
1509 return 0;
1510 } else {
1511 getErrPrintWriter().println("Failure [" + status + "]");
1512 return 1;
1513 }
1514 }
1515
1516 private int runCompile() throws RemoteException {
1517 final PrintWriter pw = getOutPrintWriter();
1518 boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
1519 boolean forceCompilation = false;
1520 boolean allPackages = false;
1521 boolean clearProfileData = false;
1522 String compilerFilter = null;
1523 String compilationReason = null;
1524 String checkProfilesRaw = null;
1525 boolean secondaryDex = false;
1526 String split = null;
Eric Holka1485f62019-01-07 13:58:25 -08001527 boolean compileLayouts = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001528
1529 String opt;
1530 while ((opt = getNextOption()) != null) {
1531 switch (opt) {
1532 case "-a":
1533 allPackages = true;
1534 break;
1535 case "-c":
1536 clearProfileData = true;
1537 break;
1538 case "-f":
1539 forceCompilation = true;
1540 break;
1541 case "-m":
1542 compilerFilter = getNextArgRequired();
1543 break;
1544 case "-r":
1545 compilationReason = getNextArgRequired();
1546 break;
Eric Holka1485f62019-01-07 13:58:25 -08001547 case "--compile-layouts":
1548 compileLayouts = true;
1549 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001550 case "--check-prof":
1551 checkProfilesRaw = getNextArgRequired();
1552 break;
1553 case "--reset":
1554 forceCompilation = true;
1555 clearProfileData = true;
1556 compilationReason = "install";
1557 break;
1558 case "--secondary-dex":
1559 secondaryDex = true;
1560 break;
1561 case "--split":
1562 split = getNextArgRequired();
1563 break;
1564 default:
1565 pw.println("Error: Unknown option: " + opt);
1566 return 1;
1567 }
1568 }
1569
1570 if (checkProfilesRaw != null) {
1571 if ("true".equals(checkProfilesRaw)) {
1572 checkProfiles = true;
1573 } else if ("false".equals(checkProfilesRaw)) {
1574 checkProfiles = false;
1575 } else {
1576 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
1577 return 1;
1578 }
1579 }
1580
Eric Holka1485f62019-01-07 13:58:25 -08001581 final boolean compilerFilterGiven = compilerFilter != null;
1582 final boolean compilationReasonGiven = compilationReason != null;
1583 // Make sure exactly one of -m, -r, or --compile-layouts is given.
1584 if ((!compilerFilterGiven && !compilationReasonGiven && !compileLayouts)
1585 || (!compilerFilterGiven && compilationReasonGiven && compileLayouts)
1586 || (compilerFilterGiven && !compilationReasonGiven && compileLayouts)
1587 || (compilerFilterGiven && compilationReasonGiven && !compileLayouts)
1588 || (compilerFilterGiven && compilationReasonGiven && compileLayouts)) {
1589 pw.println("Must specify exactly one of compilation filter (\"-m\"), compilation " +
1590 "reason (\"-r\"), or compile layouts (\"--compile-layouts\")");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001591 return 1;
1592 }
1593
1594 if (allPackages && split != null) {
1595 pw.println("-a cannot be specified together with --split");
1596 return 1;
1597 }
1598
1599 if (secondaryDex && split != null) {
1600 pw.println("--secondary-dex cannot be specified together with --split");
1601 return 1;
1602 }
1603
Eric Holka1485f62019-01-07 13:58:25 -08001604 String targetCompilerFilter = null;
1605 if (compilerFilterGiven) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001606 if (!DexFile.isValidCompilerFilter(compilerFilter)) {
1607 pw.println("Error: \"" + compilerFilter +
1608 "\" is not a valid compilation filter.");
1609 return 1;
1610 }
1611 targetCompilerFilter = compilerFilter;
Eric Holka1485f62019-01-07 13:58:25 -08001612 }
1613 if (compilationReasonGiven) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001614 int reason = -1;
1615 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
1616 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
1617 compilationReason)) {
1618 reason = i;
1619 break;
1620 }
1621 }
1622 if (reason == -1) {
1623 pw.println("Error: Unknown compilation reason: " + compilationReason);
1624 return 1;
1625 }
1626 targetCompilerFilter =
1627 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
1628 }
1629
1630
1631 List<String> packageNames = null;
1632 if (allPackages) {
1633 packageNames = mInterface.getAllPackages();
1634 } else {
1635 String packageName = getNextArg();
1636 if (packageName == null) {
1637 pw.println("Error: package name not specified");
1638 return 1;
1639 }
1640 packageNames = Collections.singletonList(packageName);
1641 }
1642
1643 List<String> failedPackages = new ArrayList<>();
Andreas Gampecbd08d42017-11-20 17:03:17 -08001644 int index = 0;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001645 for (String packageName : packageNames) {
1646 if (clearProfileData) {
1647 mInterface.clearApplicationProfileData(packageName);
1648 }
1649
Andreas Gampecbd08d42017-11-20 17:03:17 -08001650 if (allPackages) {
1651 pw.println(++index + "/" + packageNames.size() + ": " + packageName);
1652 pw.flush();
1653 }
1654
Eric Holka1485f62019-01-07 13:58:25 -08001655 boolean result = true;
1656 if (compileLayouts) {
1657 PackageManagerInternal internal = LocalServices.getService(
1658 PackageManagerInternal.class);
1659 result = internal.compileLayouts(packageName);
1660 } else {
1661 result = secondaryDex
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001662 ? mInterface.performDexOptSecondary(packageName,
1663 targetCompilerFilter, forceCompilation)
1664 : mInterface.performDexOptMode(packageName,
1665 checkProfiles, targetCompilerFilter, forceCompilation,
1666 true /* bootComplete */, split);
Eric Holka1485f62019-01-07 13:58:25 -08001667 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001668 if (!result) {
1669 failedPackages.add(packageName);
1670 }
1671 }
1672
1673 if (failedPackages.isEmpty()) {
1674 pw.println("Success");
1675 return 0;
1676 } else if (failedPackages.size() == 1) {
1677 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
1678 return 1;
1679 } else {
1680 pw.print("Failure: the following packages could not be compiled: ");
1681 boolean is_first = true;
1682 for (String packageName : failedPackages) {
1683 if (is_first) {
1684 is_first = false;
1685 } else {
1686 pw.print(", ");
1687 }
1688 pw.print(packageName);
1689 }
1690 pw.println();
1691 return 1;
1692 }
1693 }
1694
1695 private int runreconcileSecondaryDexFiles() throws RemoteException {
1696 String packageName = getNextArg();
1697 mInterface.reconcileSecondaryDexFiles(packageName);
1698 return 0;
1699 }
1700
1701 public int runForceDexOpt() throws RemoteException {
1702 mInterface.forceDexOpt(getNextArgRequired());
1703 return 0;
1704 }
1705
1706 private int runDexoptJob() throws RemoteException {
Arthur Eubanks09dd1ec2017-09-15 09:28:51 -07001707 String arg;
1708 List<String> packageNames = new ArrayList<>();
1709 while ((arg = getNextArg()) != null) {
1710 packageNames.add(arg);
1711 }
1712 boolean result = mInterface.runBackgroundDexoptJob(packageNames.isEmpty() ? null :
1713 packageNames);
Andreas Gampefa8b57d2018-08-31 15:47:01 -07001714 getOutPrintWriter().println(result ? "Success" : "Failure");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001715 return result ? 0 : -1;
1716 }
1717
1718 private int runDumpProfiles() throws RemoteException {
1719 String packageName = getNextArg();
1720 mInterface.dumpProfiles(packageName);
1721 return 0;
1722 }
1723
Calin Juravle21216c62018-05-04 17:35:29 -07001724 private int runSnapshotProfile() throws RemoteException {
1725 PrintWriter pw = getOutPrintWriter();
1726
1727 // Parse the arguments
1728 final String packageName = getNextArg();
1729 final boolean isBootImage = "android".equals(packageName);
1730
1731 String codePath = null;
1732 String opt;
1733 while ((opt = getNextArg()) != null) {
1734 switch (opt) {
1735 case "--code-path":
1736 if (isBootImage) {
1737 pw.write("--code-path cannot be used for the boot image.");
1738 return -1;
1739 }
1740 codePath = getNextArg();
1741 break;
1742 default:
1743 pw.write("Unknown arg: " + opt);
1744 return -1;
1745 }
1746 }
1747
1748 // If no code path was explicitly requested, select the base code path.
1749 String baseCodePath = null;
1750 if (!isBootImage) {
1751 PackageInfo packageInfo = mInterface.getPackageInfo(packageName, /* flags */ 0,
1752 /* userId */0);
1753 if (packageInfo == null) {
1754 pw.write("Package not found " + packageName);
1755 return -1;
1756 }
1757 baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
1758 if (codePath == null) {
1759 codePath = baseCodePath;
1760 }
1761 }
1762
1763 // Create the profile snapshot.
1764 final SnapshotRuntimeProfileCallback callback = new SnapshotRuntimeProfileCallback();
1765 // The calling package is needed to debug permission access.
1766 final String callingPackage = (Binder.getCallingUid() == Process.ROOT_UID)
1767 ? "root" : "com.android.shell";
1768 final int profileType = isBootImage
1769 ? ArtManager.PROFILE_BOOT_IMAGE : ArtManager.PROFILE_APPS;
1770 if (!mInterface.getArtManager().isRuntimeProfilingEnabled(profileType, callingPackage)) {
1771 pw.println("Error: Runtime profiling is not enabled");
1772 return -1;
1773 }
1774 mInterface.getArtManager().snapshotRuntimeProfile(profileType, packageName,
1775 codePath, callback, callingPackage);
1776 if (!callback.waitTillDone()) {
1777 pw.println("Error: callback not called");
1778 return callback.mErrCode;
1779 }
1780
1781 // Copy the snapshot profile to the output profile file.
1782 try (InputStream inStream = new AutoCloseInputStream(callback.mProfileReadFd)) {
1783 final String outputFileSuffix = isBootImage || Objects.equals(baseCodePath, codePath)
1784 ? "" : ("-" + new File(codePath).getName());
1785 final String outputProfilePath =
1786 ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + packageName + outputFileSuffix + ".prof";
1787 try (OutputStream outStream = new FileOutputStream(outputProfilePath)) {
1788 Streams.copy(inStream, outStream);
1789 }
Calin Juravlebdd94d92018-05-17 01:23:15 -07001790 // Give read permissions to the other group.
1791 Os.chmod(outputProfilePath, /*mode*/ 0644 );
1792 } catch (IOException | ErrnoException e) {
Calin Juravle21216c62018-05-04 17:35:29 -07001793 pw.println("Error when reading the profile fd: " + e.getMessage());
1794 e.printStackTrace(pw);
1795 return -1;
1796 }
1797 return 0;
1798 }
1799
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001800 private ArrayList<String> getRemainingArgs() {
1801 ArrayList<String> args = new ArrayList<>();
1802 String arg;
1803 while ((arg = getNextArg()) != null) {
1804 args.add(arg);
1805 }
1806 return args;
1807 }
1808
Calin Juravle21216c62018-05-04 17:35:29 -07001809 private static class SnapshotRuntimeProfileCallback
1810 extends ISnapshotRuntimeProfileCallback.Stub {
1811 private boolean mSuccess = false;
1812 private int mErrCode = -1;
1813 private ParcelFileDescriptor mProfileReadFd = null;
1814 private CountDownLatch mDoneSignal = new CountDownLatch(1);
1815
1816 @Override
1817 public void onSuccess(ParcelFileDescriptor profileReadFd) {
1818 mSuccess = true;
1819 try {
1820 // We need to dup the descriptor. We are in the same process as system server
1821 // and we will be receiving the same object (which will be closed on the
1822 // server side).
1823 mProfileReadFd = profileReadFd.dup();
1824 } catch (IOException e) {
1825 e.printStackTrace();
1826 }
1827 mDoneSignal.countDown();
1828 }
1829
1830 @Override
1831 public void onError(int errCode) {
1832 mSuccess = false;
1833 mErrCode = errCode;
1834 mDoneSignal.countDown();
1835 }
1836
1837 boolean waitTillDone() {
1838 boolean done = false;
1839 try {
1840 // The time-out is an arbitrary large value. Since this is a local call the result
1841 // will come very fast.
1842 done = mDoneSignal.await(10000000, TimeUnit.MILLISECONDS);
1843 } catch (InterruptedException ignored) {
1844 }
1845 return done && mSuccess;
1846 }
1847 }
1848
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001849 private int runUninstall() throws RemoteException {
1850 final PrintWriter pw = getOutPrintWriter();
1851 int flags = 0;
1852 int userId = UserHandle.USER_ALL;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001853 long versionCode = PackageManager.VERSION_CODE_HIGHEST;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001854
1855 String opt;
1856 while ((opt = getNextOption()) != null) {
1857 switch (opt) {
1858 case "-k":
1859 flags |= PackageManager.DELETE_KEEP_DATA;
1860 break;
1861 case "--user":
1862 userId = UserHandle.parseUserArg(getNextArgRequired());
1863 break;
1864 case "--versionCode":
Dianne Hackborn3accca02013-09-20 09:32:11 -07001865 versionCode = Long.parseLong(getNextArgRequired());
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001866 break;
1867 default:
1868 pw.println("Error: Unknown option: " + opt);
1869 return 1;
1870 }
1871 }
1872
1873 final String packageName = getNextArg();
1874 if (packageName == null) {
1875 pw.println("Error: package name not specified");
1876 return 1;
1877 }
1878
1879 // if a split is specified, just remove it and not the whole package
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001880 ArrayList<String> splitNames = getRemainingArgs();
1881 if (!splitNames.isEmpty()) {
1882 return runRemoveSplits(packageName, splitNames);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001883 }
1884
Todd Kennedyc3c52172019-11-26 13:20:59 -08001885 if (userId == UserHandle.USER_ALL) {
1886 flags |= PackageManager.DELETE_ALL_USERS;
1887 }
1888 final int translatedUserId =
1889 translateUserId(userId, UserHandle.USER_SYSTEM, "runUninstall");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001890 final LocalIntentReceiver receiver = new LocalIntentReceiver();
Todd Kennedyc3c52172019-11-26 13:20:59 -08001891 final PackageManagerInternal internal =
1892 LocalServices.getService(PackageManagerInternal.class);
Nikita Ioffef012a222019-03-05 22:37:55 +00001893
1894 if (internal.isApexPackage(packageName)) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08001895 internal.uninstallApex(
Gavin Corkery4fd10882019-11-28 15:37:51 +00001896 packageName, versionCode, translatedUserId, receiver.getIntentSender(), flags);
Todd Kennedy2678a992019-11-27 10:21:23 -08001897 } else {
1898 if ((flags & PackageManager.DELETE_ALL_USERS) == 0) {
1899 final PackageInfo info = mInterface.getPackageInfo(packageName,
1900 PackageManager.MATCH_STATIC_SHARED_LIBRARIES, translatedUserId);
1901 if (info == null) {
1902 pw.println("Failure [not installed for " + translatedUserId + "]");
1903 return 1;
1904 }
1905 final boolean isSystem =
1906 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
1907 // If we are being asked to delete a system app for just one
1908 // user set flag so it disables rather than reverting to system
1909 // version of the app.
1910 if (isSystem) {
1911 flags |= PackageManager.DELETE_SYSTEM_APP;
1912 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08001913 }
Nikita Ioffef012a222019-03-05 22:37:55 +00001914 mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
1915 versionCode), null /*callerPackageName*/, flags,
Todd Kennedyc3c52172019-11-26 13:20:59 -08001916 receiver.getIntentSender(), translatedUserId);
Nikita Ioffef012a222019-03-05 22:37:55 +00001917 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001918
1919 final Intent result = receiver.getResult();
1920 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1921 PackageInstaller.STATUS_FAILURE);
1922 if (status == PackageInstaller.STATUS_SUCCESS) {
1923 pw.println("Success");
1924 return 0;
1925 } else {
1926 pw.println("Failure ["
1927 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
1928 return 1;
1929 }
1930 }
1931
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001932 private int runRemoveSplits(String packageName, Collection<String> splitNames)
1933 throws RemoteException {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001934 final PrintWriter pw = getOutPrintWriter();
1935 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
1936 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1937 sessionParams.appPackageName = packageName;
1938 final int sessionId =
1939 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
1940 boolean abandonSession = true;
1941 try {
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00001942 if (doRemoveSplits(sessionId, splitNames, false /*logSuccess*/)
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001943 != PackageInstaller.STATUS_SUCCESS) {
1944 return 1;
1945 }
1946 if (doCommitSession(sessionId, false /*logSuccess*/)
1947 != PackageInstaller.STATUS_SUCCESS) {
1948 return 1;
1949 }
1950 abandonSession = false;
1951 pw.println("Success");
1952 return 0;
1953 } finally {
1954 if (abandonSession) {
1955 try {
1956 doAbandonSession(sessionId, false /*logSuccess*/);
1957 } catch (Exception ignore) {
1958 }
1959 }
1960 }
1961 }
1962
1963 static class ClearDataObserver extends IPackageDataObserver.Stub {
1964 boolean finished;
1965 boolean result;
1966
1967 @Override
1968 public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1969 synchronized (this) {
1970 finished = true;
1971 result = succeeded;
1972 notifyAll();
1973 }
1974 }
1975 }
1976
1977 private int runClear() throws RemoteException {
1978 int userId = UserHandle.USER_SYSTEM;
1979 String option = getNextOption();
1980 if (option != null && option.equals("--user")) {
1981 userId = UserHandle.parseUserArg(getNextArgRequired());
1982 }
1983
1984 String pkg = getNextArg();
1985 if (pkg == null) {
1986 getErrPrintWriter().println("Error: no package specified");
1987 return 1;
1988 }
1989
Todd Kennedy5385b512019-11-26 15:49:06 -08001990 final int translatedUserId =
1991 translateUserId(userId, UserHandle.USER_NULL, "runClear");
1992 final ClearDataObserver obs = new ClearDataObserver();
1993 ActivityManager.getService().clearApplicationUserData(pkg, false, obs, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001994 synchronized (obs) {
1995 while (!obs.finished) {
1996 try {
1997 obs.wait();
1998 } catch (InterruptedException e) {
1999 }
2000 }
2001 }
2002
2003 if (obs.result) {
2004 getOutPrintWriter().println("Success");
2005 return 0;
2006 } else {
2007 getErrPrintWriter().println("Failed");
2008 return 1;
2009 }
2010 }
2011
2012 private static String enabledSettingToString(int state) {
2013 switch (state) {
2014 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
2015 return "default";
2016 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
2017 return "enabled";
2018 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
2019 return "disabled";
2020 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
2021 return "disabled-user";
2022 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
2023 return "disabled-until-used";
2024 }
2025 return "unknown";
2026 }
2027
2028 private int runSetEnabledSetting(int state) throws RemoteException {
2029 int userId = UserHandle.USER_SYSTEM;
2030 String option = getNextOption();
2031 if (option != null && option.equals("--user")) {
2032 userId = UserHandle.parseUserArg(getNextArgRequired());
2033 }
2034
Todd Kennedyc3c52172019-11-26 13:20:59 -08002035 final String pkg = getNextArg();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002036 if (pkg == null) {
2037 getErrPrintWriter().println("Error: no package or component specified");
2038 return 1;
2039 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002040 final int translatedUserId =
2041 translateUserId(userId, UserHandle.USER_NULL, "runSetEnabledSetting");
2042 final ComponentName cn = ComponentName.unflattenFromString(pkg);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002043 if (cn == null) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002044 mInterface.setApplicationEnabledSetting(pkg, state, 0, translatedUserId,
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002045 "shell:" + android.os.Process.myUid());
2046 getOutPrintWriter().println("Package " + pkg + " new state: "
2047 + enabledSettingToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002048 mInterface.getApplicationEnabledSetting(pkg, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002049 return 0;
2050 } else {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002051 mInterface.setComponentEnabledSetting(cn, state, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002052 getOutPrintWriter().println("Component " + cn.toShortString() + " new state: "
2053 + enabledSettingToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002054 mInterface.getComponentEnabledSetting(cn, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002055 return 0;
2056 }
2057 }
2058
2059 private int runSetHiddenSetting(boolean state) throws RemoteException {
2060 int userId = UserHandle.USER_SYSTEM;
2061 String option = getNextOption();
2062 if (option != null && option.equals("--user")) {
2063 userId = UserHandle.parseUserArg(getNextArgRequired());
2064 }
2065
2066 String pkg = getNextArg();
2067 if (pkg == null) {
2068 getErrPrintWriter().println("Error: no package or component specified");
2069 return 1;
2070 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002071 final int translatedUserId =
2072 translateUserId(userId, UserHandle.USER_NULL, "runSetHiddenSetting");
2073 mInterface.setApplicationHiddenSettingAsUser(pkg, state, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002074 getOutPrintWriter().println("Package " + pkg + " new hidden state: "
Todd Kennedyc3c52172019-11-26 13:20:59 -08002075 + mInterface.getApplicationHiddenSettingAsUser(pkg, translatedUserId));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002076 return 0;
2077 }
2078
2079 private int runSuspend(boolean suspendedState) {
2080 final PrintWriter pw = getOutPrintWriter();
2081 int userId = UserHandle.USER_SYSTEM;
Suprabh Shukla3c3af142018-03-30 00:28:37 -07002082 String dialogMessage = null;
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002083 final PersistableBundle appExtras = new PersistableBundle();
2084 final PersistableBundle launcherExtras = new PersistableBundle();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002085 String opt;
2086 while ((opt = getNextOption()) != null) {
2087 switch (opt) {
2088 case "--user":
2089 userId = UserHandle.parseUserArg(getNextArgRequired());
2090 break;
Suprabh Shukla3c3af142018-03-30 00:28:37 -07002091 case "--dialogMessage":
2092 dialogMessage = getNextArgRequired();
2093 break;
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002094 case "--ael":
2095 case "--aes":
2096 case "--aed":
2097 case "--lel":
2098 case "--les":
2099 case "--led":
2100 final String key = getNextArgRequired();
2101 final String val = getNextArgRequired();
2102 if (!suspendedState) {
2103 break;
2104 }
2105 final PersistableBundle bundleToInsert =
2106 opt.startsWith("--a") ? appExtras : launcherExtras;
2107 switch (opt.charAt(4)) {
2108 case 'l':
2109 bundleToInsert.putLong(key, Long.valueOf(val));
2110 break;
2111 case 'd':
2112 bundleToInsert.putDouble(key, Double.valueOf(val));
2113 break;
2114 case 's':
2115 bundleToInsert.putString(key, val);
2116 break;
2117 }
2118 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002119 default:
2120 pw.println("Error: Unknown option: " + opt);
2121 return 1;
2122 }
2123 }
2124
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002125 final String packageName = getNextArg();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002126 if (packageName == null) {
2127 pw.println("Error: package name not specified");
2128 return 1;
2129 }
Suprabh Shukla021b57a2018-03-08 18:21:50 -08002130 final String callingPackage =
2131 (Binder.getCallingUid() == Process.ROOT_UID) ? "root" : "com.android.shell";
Suprabh Shukla389cb6f2018-10-01 18:20:39 -07002132
2133 final SuspendDialogInfo info;
2134 if (!TextUtils.isEmpty(dialogMessage)) {
2135 info = new SuspendDialogInfo.Builder()
2136 .setMessage(dialogMessage)
2137 .build();
2138 } else {
2139 info = null;
2140 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002141 try {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002142 final int translatedUserId =
2143 translateUserId(userId, UserHandle.USER_NULL, "runSuspend");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002144 mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
Suprabh Shuklad3278442019-08-27 15:58:03 -07002145 ((appExtras.size() > 0) ? appExtras : null),
2146 ((launcherExtras.size() > 0) ? launcherExtras : null),
Todd Kennedyc3c52172019-11-26 13:20:59 -08002147 info, callingPackage, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002148 pw.println("Package " + packageName + " new suspended state: "
Todd Kennedyc3c52172019-11-26 13:20:59 -08002149 + mInterface.isPackageSuspendedForUser(packageName, translatedUserId));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002150 return 0;
2151 } catch (RemoteException | IllegalArgumentException e) {
2152 pw.println(e.toString());
2153 return 1;
2154 }
2155 }
2156
2157 private int runGrantRevokePermission(boolean grant) throws RemoteException {
2158 int userId = UserHandle.USER_SYSTEM;
2159
2160 String opt = null;
2161 while ((opt = getNextOption()) != null) {
2162 if (opt.equals("--user")) {
2163 userId = UserHandle.parseUserArg(getNextArgRequired());
2164 }
2165 }
2166
2167 String pkg = getNextArg();
2168 if (pkg == null) {
2169 getErrPrintWriter().println("Error: no package specified");
2170 return 1;
2171 }
2172 String perm = getNextArg();
2173 if (perm == null) {
2174 getErrPrintWriter().println("Error: no permission specified");
2175 return 1;
2176 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002177 final int translatedUserId =
2178 translateUserId(userId, UserHandle.USER_NULL, "runGrantRevokePermission");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002179 if (grant) {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002180 mPermissionManager.grantRuntimePermission(pkg, perm, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002181 } else {
Todd Kennedyc3c52172019-11-26 13:20:59 -08002182 mPermissionManager.revokeRuntimePermission(pkg, perm, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002183 }
2184 return 0;
2185 }
2186
2187 private int runResetPermissions() throws RemoteException {
Todd Kennedyc971a452019-07-08 16:04:52 -07002188 mPermissionManager.resetRuntimePermissions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002189 return 0;
2190 }
2191
2192 private int runSetPermissionEnforced() throws RemoteException {
2193 final String permission = getNextArg();
2194 if (permission == null) {
2195 getErrPrintWriter().println("Error: no permission specified");
2196 return 1;
2197 }
2198 final String enforcedRaw = getNextArg();
2199 if (enforcedRaw == null) {
2200 getErrPrintWriter().println("Error: no enforcement specified");
2201 return 1;
2202 }
Todd Kennedyc5b0e862019-07-16 09:47:58 -07002203 mPermissionManager.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002204 return 0;
2205 }
2206
Jiyong Park002fdbd2017-02-13 20:50:31 +09002207 private boolean isVendorApp(String pkg) {
2208 try {
2209 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
2210 return info != null && info.applicationInfo.isVendor();
2211 } catch (RemoteException e) {
2212 return false;
2213 }
2214 }
2215
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002216 private boolean isProductApp(String pkg) {
2217 try {
2218 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
2219 return info != null && info.applicationInfo.isProduct();
2220 } catch (RemoteException e) {
2221 return false;
2222 }
2223 }
2224
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002225 private boolean isSystemExtApp(String pkg) {
Dario Freni2bef1762018-06-01 14:02:08 +01002226 try {
2227 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002228 return info != null && info.applicationInfo.isSystemExt();
Dario Freni2bef1762018-06-01 14:02:08 +01002229 } catch (RemoteException e) {
2230 return false;
2231 }
2232 }
2233
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002234 private int runGetPrivappPermissions() {
2235 final String pkg = getNextArg();
2236 if (pkg == null) {
2237 getErrPrintWriter().println("Error: no package specified.");
2238 return 1;
2239 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002240
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002241 ArraySet<String> privAppPermissions = null;
2242 if (isVendorApp(pkg)) {
2243 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
2244 } else if (isProductApp(pkg)) {
2245 privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002246 } else if (isSystemExtApp(pkg)) {
Dario Freni2bef1762018-06-01 14:02:08 +01002247 privAppPermissions = SystemConfig.getInstance()
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002248 .getSystemExtPrivAppPermissions(pkg);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002249 } else {
2250 privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
2251 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002252
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002253 getOutPrintWriter().println(privAppPermissions == null
2254 ? "{}" : privAppPermissions.toString());
2255 return 0;
2256 }
2257
2258 private int runGetPrivappDenyPermissions() {
2259 final String pkg = getNextArg();
2260 if (pkg == null) {
2261 getErrPrintWriter().println("Error: no package specified.");
2262 return 1;
2263 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002264
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002265 ArraySet<String> privAppPermissions = null;
2266 if (isVendorApp(pkg)) {
2267 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
2268 } else if (isProductApp(pkg)) {
2269 privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002270 } else if (isSystemExtApp(pkg)) {
Dario Freni2bef1762018-06-01 14:02:08 +01002271 privAppPermissions = SystemConfig.getInstance()
Jeongik Cha9ec059a2019-07-04 21:12:06 +09002272 .getSystemExtPrivAppDenyPermissions(pkg);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09002273 } else {
2274 privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
2275 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09002276
2277 getOutPrintWriter().println(privAppPermissions == null
2278 ? "{}" : privAppPermissions.toString());
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002279 return 0;
2280 }
2281
2282 private int runGetOemPermissions() {
2283 final String pkg = getNextArg();
2284 if (pkg == null) {
2285 getErrPrintWriter().println("Error: no package specified.");
2286 return 1;
2287 }
2288 final Map<String, Boolean> oemPermissions = SystemConfig.getInstance()
2289 .getOemPermissions(pkg);
2290 if (oemPermissions == null || oemPermissions.isEmpty()) {
2291 getOutPrintWriter().println("{}");
2292 } else {
2293 oemPermissions.forEach((permission, granted) ->
2294 getOutPrintWriter().println(permission + " granted:" + granted)
2295 );
2296 }
2297 return 0;
2298 }
2299
2300 private String linkStateToString(int state) {
2301 switch (state) {
2302 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
2303 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
2304 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
2305 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
2306 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
2307 }
2308 return "Unknown link state: " + state;
2309 }
2310
2311 // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
2312 private int runSetAppLink() throws RemoteException {
2313 int userId = UserHandle.USER_SYSTEM;
2314
2315 String opt;
2316 while ((opt = getNextOption()) != null) {
2317 if (opt.equals("--user")) {
2318 userId = UserHandle.parseUserArg(getNextArgRequired());
2319 } else {
2320 getErrPrintWriter().println("Error: unknown option: " + opt);
2321 return 1;
2322 }
2323 }
2324
2325 // Package name to act on; required
2326 final String pkg = getNextArg();
2327 if (pkg == null) {
2328 getErrPrintWriter().println("Error: no package specified.");
2329 return 1;
2330 }
2331
2332 // State to apply; {always|ask|never|undefined}, required
2333 final String modeString = getNextArg();
2334 if (modeString == null) {
2335 getErrPrintWriter().println("Error: no app link state specified.");
2336 return 1;
2337 }
2338
2339 final int newMode;
2340 switch (modeString.toLowerCase()) {
2341 case "undefined":
2342 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
2343 break;
2344
2345 case "always":
2346 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
2347 break;
2348
2349 case "ask":
2350 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
2351 break;
2352
2353 case "always-ask":
2354 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
2355 break;
2356
2357 case "never":
2358 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
2359 break;
2360
2361 default:
2362 getErrPrintWriter().println("Error: unknown app link state '" + modeString + "'");
2363 return 1;
2364 }
2365
Todd Kennedyc3c52172019-11-26 13:20:59 -08002366 final int translatedUserId =
2367 translateUserId(userId, UserHandle.USER_NULL, "runSetAppLink");
2368 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002369 if (info == null) {
2370 getErrPrintWriter().println("Error: package " + pkg + " not found.");
2371 return 1;
2372 }
2373
2374 if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2375 getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2376 return 1;
2377 }
2378
Todd Kennedyc3c52172019-11-26 13:20:59 -08002379 if (!mInterface.updateIntentVerificationStatus(pkg, newMode, translatedUserId)) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002380 getErrPrintWriter().println("Error: unable to update app link status for " + pkg);
2381 return 1;
2382 }
2383
2384 return 0;
2385 }
2386
2387 // pm get-app-link [--user USER_ID] PACKAGE
2388 private int runGetAppLink() throws RemoteException {
2389 int userId = UserHandle.USER_SYSTEM;
2390
2391 String opt;
2392 while ((opt = getNextOption()) != null) {
2393 if (opt.equals("--user")) {
2394 userId = UserHandle.parseUserArg(getNextArgRequired());
2395 } else {
2396 getErrPrintWriter().println("Error: unknown option: " + opt);
2397 return 1;
2398 }
2399 }
2400
2401 // Package name to act on; required
2402 final String pkg = getNextArg();
2403 if (pkg == null) {
2404 getErrPrintWriter().println("Error: no package specified.");
2405 return 1;
2406 }
2407
Todd Kennedyc3c52172019-11-26 13:20:59 -08002408 final int translatedUserId =
2409 translateUserId(userId, UserHandle.USER_NULL, "runGetAppLink");
2410 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002411 if (info == null) {
2412 getErrPrintWriter().println("Error: package " + pkg + " not found.");
2413 return 1;
2414 }
2415
2416 if ((info.applicationInfo.privateFlags
2417 & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2418 getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2419 return 1;
2420 }
2421
2422 getOutPrintWriter().println(linkStateToString(
Todd Kennedyc3c52172019-11-26 13:20:59 -08002423 mInterface.getIntentVerificationStatus(pkg, translatedUserId)));
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002424
2425 return 0;
2426 }
2427
2428 private int runTrimCaches() throws RemoteException {
2429 String size = getNextArg();
2430 if (size == null) {
2431 getErrPrintWriter().println("Error: no size specified");
2432 return 1;
2433 }
2434 long multiplier = 1;
2435 int len = size.length();
2436 char c = size.charAt(len - 1);
2437 if (c < '0' || c > '9') {
2438 if (c == 'K' || c == 'k') {
2439 multiplier = 1024L;
2440 } else if (c == 'M' || c == 'm') {
2441 multiplier = 1024L*1024L;
2442 } else if (c == 'G' || c == 'g') {
2443 multiplier = 1024L*1024L*1024L;
2444 } else {
2445 getErrPrintWriter().println("Invalid suffix: " + c);
2446 return 1;
2447 }
2448 size = size.substring(0, len-1);
2449 }
2450 long sizeVal;
2451 try {
2452 sizeVal = Long.parseLong(size) * multiplier;
2453 } catch (NumberFormatException e) {
2454 getErrPrintWriter().println("Error: expected number at: " + size);
2455 return 1;
2456 }
2457 String volumeUuid = getNextArg();
2458 if ("internal".equals(volumeUuid)) {
2459 volumeUuid = null;
2460 }
2461 ClearDataObserver obs = new ClearDataObserver();
2462 mInterface.freeStorageAndNotify(volumeUuid, sizeVal,
2463 StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs);
2464 synchronized (obs) {
2465 while (!obs.finished) {
2466 try {
2467 obs.wait();
2468 } catch (InterruptedException e) {
2469 }
2470 }
2471 }
2472 return 0;
2473 }
2474
2475 private static boolean isNumber(String s) {
2476 try {
2477 Integer.parseInt(s);
2478 } catch (NumberFormatException nfe) {
2479 return false;
2480 }
2481 return true;
2482 }
2483
2484 public int runCreateUser() throws RemoteException {
2485 String name;
2486 int userId = -1;
2487 int flags = 0;
Bookatz029832a2019-10-04 16:50:22 -07002488 String userType = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002489 String opt;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002490 boolean preCreateOnly = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002491 while ((opt = getNextOption()) != null) {
Bookatz029832a2019-10-04 16:50:22 -07002492 String newUserType = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002493 if ("--profileOf".equals(opt)) {
2494 userId = UserHandle.parseUserArg(getNextArgRequired());
2495 } else if ("--managed".equals(opt)) {
Bookatz029832a2019-10-04 16:50:22 -07002496 newUserType = UserManager.USER_TYPE_PROFILE_MANAGED;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002497 } else if ("--restricted".equals(opt)) {
Bookatz029832a2019-10-04 16:50:22 -07002498 newUserType = UserManager.USER_TYPE_FULL_RESTRICTED;
2499 } else if ("--guest".equals(opt)) {
2500 newUserType = UserManager.USER_TYPE_FULL_GUEST;
2501 } else if ("--demo".equals(opt)) {
2502 newUserType = UserManager.USER_TYPE_FULL_DEMO;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002503 } else if ("--ephemeral".equals(opt)) {
2504 flags |= UserInfo.FLAG_EPHEMERAL;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002505 } else if ("--pre-create-only".equals(opt)) {
2506 preCreateOnly = true;
Bookatz029832a2019-10-04 16:50:22 -07002507 } else if ("--user-type".equals(opt)) {
2508 newUserType = getNextArgRequired();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002509 } else {
2510 getErrPrintWriter().println("Error: unknown option " + opt);
2511 return 1;
2512 }
Bookatz029832a2019-10-04 16:50:22 -07002513 // Ensure only one user-type was specified.
2514 if (newUserType != null) {
2515 if (userType != null && !userType.equals(newUserType)) {
2516 getErrPrintWriter().println("Error: more than one user type was specified ("
2517 + userType + " and " + newUserType + ")");
2518 return 1;
2519 }
2520 userType = newUserType;
2521 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002522 }
2523 String arg = getNextArg();
Felipe Lemee35f5b02019-10-14 15:37:44 -07002524 if (arg == null && !preCreateOnly) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002525 getErrPrintWriter().println("Error: no user name specified.");
2526 return 1;
2527 }
Felipe Lemee35f5b02019-10-14 15:37:44 -07002528 if (arg != null && preCreateOnly) {
2529 getErrPrintWriter().println("Warning: name is ignored for pre-created users");
2530 }
2531
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002532 name = arg;
Valentin Iftime89df4c82019-08-23 13:02:50 +02002533 UserInfo info = null;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002534 IUserManager um = IUserManager.Stub.asInterface(
2535 ServiceManager.getService(Context.USER_SERVICE));
2536 IAccountManager accm = IAccountManager.Stub.asInterface(
2537 ServiceManager.getService(Context.ACCOUNT_SERVICE));
Bookatz029832a2019-10-04 16:50:22 -07002538 if (userType == null) {
2539 userType = UserInfo.getDefaultUserType(flags);
2540 }
Valentin Iftime89df4c82019-08-23 13:02:50 +02002541 try {
2542 if (UserManager.isUserTypeRestricted(userType)) {
2543 // In non-split user mode, userId can only be SYSTEM
2544 int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
2545 info = um.createRestrictedProfileWithThrow(name, parentUserId);
2546 accm.addSharedAccountsFromParentUser(parentUserId, userId,
2547 (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
2548 } else if (userId < 0) {
2549 info = preCreateOnly ?
2550 um.preCreateUserWithThrow(userType) :
2551 um.createUserWithThrow(name, userType, flags);
2552 } else {
2553 info = um.createProfileForUserWithThrow(name, userType, flags, userId, null);
2554 }
2555 } catch (ServiceSpecificException e) {
2556 getErrPrintWriter().println("Error: " + e);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002557 }
2558
2559 if (info != null) {
2560 getOutPrintWriter().println("Success: created user id " + info.id);
2561 return 0;
2562 } else {
2563 getErrPrintWriter().println("Error: couldn't create User.");
2564 return 1;
2565 }
2566 }
2567
2568 public int runRemoveUser() throws RemoteException {
2569 int userId;
2570 String arg = getNextArg();
2571 if (arg == null) {
2572 getErrPrintWriter().println("Error: no user id specified.");
2573 return 1;
2574 }
2575 userId = UserHandle.parseUserArg(arg);
2576 IUserManager um = IUserManager.Stub.asInterface(
2577 ServiceManager.getService(Context.USER_SERVICE));
2578 if (um.removeUser(userId)) {
2579 getOutPrintWriter().println("Success: removed user");
2580 return 0;
2581 } else {
2582 getErrPrintWriter().println("Error: couldn't remove user id " + userId);
2583 return 1;
2584 }
2585 }
2586
2587 public int runSetUserRestriction() throws RemoteException {
2588 int userId = UserHandle.USER_SYSTEM;
2589 String opt = getNextOption();
2590 if (opt != null && "--user".equals(opt)) {
2591 userId = UserHandle.parseUserArg(getNextArgRequired());
2592 }
2593
2594 String restriction = getNextArg();
2595 String arg = getNextArg();
2596 boolean value;
2597 if ("1".equals(arg)) {
2598 value = true;
2599 } else if ("0".equals(arg)) {
2600 value = false;
2601 } else {
2602 getErrPrintWriter().println("Error: valid value not specified");
2603 return 1;
2604 }
Todd Kennedy5385b512019-11-26 15:49:06 -08002605 final int translatedUserId =
2606 translateUserId(userId, UserHandle.USER_NULL, "runSetUserRestriction");
2607 final IUserManager um = IUserManager.Stub.asInterface(
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002608 ServiceManager.getService(Context.USER_SERVICE));
Todd Kennedy5385b512019-11-26 15:49:06 -08002609 um.setUserRestriction(restriction, value, translatedUserId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002610 return 0;
2611 }
2612
2613 public int runGetMaxUsers() {
2614 getOutPrintWriter().println("Maximum supported users: "
2615 + UserManager.getMaxSupportedUsers());
2616 return 0;
2617 }
2618
Alex Chauc12189b2018-01-16 15:01:15 +00002619 public int runGetMaxRunningUsers() {
2620 ActivityManagerInternal activityManagerInternal =
2621 LocalServices.getService(ActivityManagerInternal.class);
2622 getOutPrintWriter().println("Maximum supported running users: "
2623 + activityManagerInternal.getMaxRunningUsers());
2624 return 0;
2625 }
2626
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002627 private static class InstallParams {
2628 SessionParams sessionParams;
2629 String installerPackageName;
2630 int userId = UserHandle.USER_ALL;
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002631 boolean mWaitForStagedSessionReady = true;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002632 long timeoutMs = DEFAULT_WAIT_MS;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002633 }
2634
2635 private InstallParams makeInstallParams() {
2636 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2637 final InstallParams params = new InstallParams();
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07002638
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002639 params.sessionParams = sessionParams;
Philip P. Moltmannbfcffa02019-05-13 17:10:46 -07002640 // Whitelist all permissions by default
2641 sessionParams.installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
2642
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002643 String opt;
Patrick Baumanna9333492017-11-28 15:23:49 -08002644 boolean replaceExisting = true;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002645 while ((opt = getNextOption()) != null) {
2646 switch (opt) {
Patrick Baumanna9333492017-11-28 15:23:49 -08002647 case "-r": // ignore
2648 break;
2649 case "-R":
2650 replaceExisting = false;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002651 break;
2652 case "-i":
2653 params.installerPackageName = getNextArg();
2654 if (params.installerPackageName == null) {
2655 throw new IllegalArgumentException("Missing installer package");
2656 }
2657 break;
2658 case "-t":
2659 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
2660 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002661 case "-f":
2662 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
2663 break;
2664 case "-d":
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00002665 sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002666 break;
2667 case "-g":
2668 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
Svet Ganov83a3a4a2019-05-03 18:50:43 -07002669 break;
2670 case "--restrict-permissions":
2671 sessionParams.installFlags &=
2672 ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002673 break;
Todd Kennedyb1072712016-04-26 15:41:20 -07002674 case "--dont-kill":
2675 sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
2676 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002677 case "--originating-uri":
2678 sessionParams.originatingUri = Uri.parse(getNextArg());
2679 break;
2680 case "--referrer":
2681 sessionParams.referrerUri = Uri.parse(getNextArg());
2682 break;
2683 case "-p":
2684 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
2685 sessionParams.appPackageName = getNextArg();
2686 if (sessionParams.appPackageName == null) {
2687 throw new IllegalArgumentException("Missing inherit package name");
2688 }
2689 break;
Dianne Hackbornca3872c2017-10-30 14:19:32 -07002690 case "--pkg":
2691 sessionParams.appPackageName = getNextArg();
2692 if (sessionParams.appPackageName == null) {
2693 throw new IllegalArgumentException("Missing package name");
2694 }
2695 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002696 case "-S":
Todd Kennedy9caf94e2016-10-12 15:26:08 -07002697 final long sizeBytes = Long.parseLong(getNextArg());
2698 if (sizeBytes <= 0) {
2699 throw new IllegalArgumentException("Size must be positive");
2700 }
2701 sessionParams.setSize(sizeBytes);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002702 break;
2703 case "--abi":
2704 sessionParams.abiOverride = checkAbiArgument(getNextArg());
2705 break;
Todd Kennedy2699f062015-11-20 13:07:17 -08002706 case "--ephemeral":
Dianne Hackbornca3872c2017-10-30 14:19:32 -07002707 case "--instant":
Todd Kennedybe0b8892017-02-15 14:13:52 -08002708 case "--instantapp":
Todd Kennedyb7717682016-11-30 15:41:21 -08002709 sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
Todd Kennedy2699f062015-11-20 13:07:17 -08002710 break;
Todd Kennedybe0b8892017-02-15 14:13:52 -08002711 case "--full":
2712 sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
2713 break;
Todd Kennedy78a72502017-07-19 12:49:30 -07002714 case "--preload":
2715 sessionParams.setInstallAsVirtualPreload();
2716 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002717 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08002718 params.userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002719 break;
2720 case "--install-location":
2721 sessionParams.installLocation = Integer.parseInt(getNextArg());
2722 break;
Sunny Goyalabd4d442018-09-19 15:49:50 -07002723 case "--install-reason":
2724 sessionParams.installReason = Integer.parseInt(getNextArg());
2725 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002726 case "--force-uuid":
2727 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
2728 sessionParams.volumeUuid = getNextArg();
2729 if ("internal".equals(sessionParams.volumeUuid)) {
2730 sessionParams.volumeUuid = null;
2731 }
2732 break;
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002733 case "--force-sdk": // ignore
Todd Kennedyb1072712016-04-26 15:41:20 -07002734 break;
Dario Frenid8bf22e2018-08-31 14:18:04 +01002735 case "--apex":
Dario Freni3fa46d82019-01-23 19:31:47 +00002736 sessionParams.setInstallAsApex();
Dario Freni505b8152019-01-08 12:30:43 +00002737 sessionParams.setStaged();
Dario Frenid8bf22e2018-08-31 14:18:04 +01002738 break;
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002739 case "--multi-package":
2740 sessionParams.setMultiPackage();
2741 break;
Dario Freniaac4ba42018-12-06 15:47:16 +00002742 case "--staged":
2743 sessionParams.setStaged();
2744 break;
Patrick Baumann5ff0f9e2019-11-27 11:40:07 -08002745 case "--force-queryable":
2746 sessionParams.setForceQueryable();
2747 break;
Richard Uhlerb29f1452018-09-12 16:38:15 +01002748 case "--enable-rollback":
Richard Uhler88184a62019-04-16 11:30:25 +01002749 if (params.installerPackageName == null) {
2750 // com.android.shell has the TEST_MANAGE_ROLLBACKS
2751 // permission needed to enable rollback for non-module
2752 // packages, which is likely what the user wants when
2753 // enabling rollback through the shell command. Set
2754 // the installer to com.android.shell if no installer
2755 // has been provided so that the user doesn't have to
2756 // remember to set it themselves.
2757 params.installerPackageName = "com.android.shell";
2758 }
Richard Uhlerb29f1452018-09-12 16:38:15 +01002759 sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
2760 break;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002761 case "--wait":
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002762 params.mWaitForStagedSessionReady = true;
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01002763 try {
2764 params.timeoutMs = Long.parseLong(peekNextArg());
2765 getNextArg();
2766 } catch (NumberFormatException ignore) {
2767 }
2768 break;
Nikita Ioffe62d918c2020-01-18 01:20:42 +00002769 case "--no-wait":
2770 params.mWaitForStagedSessionReady = false;
2771 break;
Chester Hsieh750b5ed2020-01-08 09:32:17 -08002772 case "--skip-verification":
2773 sessionParams.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;
2774 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002775 default:
2776 throw new IllegalArgumentException("Unknown option " + opt);
2777 }
Patrick Baumanndcf19162019-05-29 09:18:58 -07002778 }
2779 if (replaceExisting) {
2780 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002781 }
2782 return params;
2783 }
2784
Makoto Onuki4828a592016-03-15 18:06:57 -07002785 private int runSetHomeActivity() {
2786 final PrintWriter pw = getOutPrintWriter();
2787 int userId = UserHandle.USER_SYSTEM;
2788 String opt;
2789 while ((opt = getNextOption()) != null) {
2790 switch (opt) {
2791 case "--user":
2792 userId = UserHandle.parseUserArg(getNextArgRequired());
2793 break;
2794 default:
2795 pw.println("Error: Unknown option: " + opt);
2796 return 1;
2797 }
2798 }
2799
Bookatz2b5a6012019-04-16 19:41:28 -07002800 String pkgName;
Makoto Onuki4828a592016-03-15 18:06:57 -07002801 String component = getNextArg();
Bookatz2b5a6012019-04-16 19:41:28 -07002802 if (component.indexOf('/') < 0) {
2803 // No component specified, so assume it's just a package name.
2804 pkgName = component;
2805 } else {
2806 ComponentName componentName =
2807 component != null ? ComponentName.unflattenFromString(component) : null;
2808 if (componentName == null) {
2809 pw.println("Error: invalid component name");
2810 return 1;
2811 }
2812 pkgName = componentName.getPackageName();
Makoto Onuki4828a592016-03-15 18:06:57 -07002813 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002814 final int translatedUserId =
2815 translateUserId(userId, UserHandle.USER_NULL, "runSetHomeActivity");
Bookatz2b5a6012019-04-16 19:41:28 -07002816 final CompletableFuture<Boolean> future = new CompletableFuture<>();
2817 final RemoteCallback callback = new RemoteCallback(res -> future.complete(res != null));
Makoto Onuki4828a592016-03-15 18:06:57 -07002818 try {
Bookatz2b5a6012019-04-16 19:41:28 -07002819 IRoleManager roleManager = android.app.role.IRoleManager.Stub.asInterface(
2820 ServiceManager.getServiceOrThrow(Context.ROLE_SERVICE));
2821 roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName,
Todd Kennedyc3c52172019-11-26 13:20:59 -08002822 0, translatedUserId, callback);
Bookatz2b5a6012019-04-16 19:41:28 -07002823 boolean success = future.get();
2824 if (success) {
2825 pw.println("Success");
2826 return 0;
2827 } else {
2828 pw.println("Error: Failed to set default home.");
2829 return 1;
2830 }
Makoto Onuki3bdbf982016-06-23 16:56:35 -07002831 } catch (Exception e) {
Makoto Onuki4828a592016-03-15 18:06:57 -07002832 pw.println(e.toString());
2833 return 1;
2834 }
2835 }
2836
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002837 private int runSetInstaller() throws RemoteException {
2838 final String targetPackage = getNextArg();
2839 final String installerPackageName = getNextArg();
Fyodor Kupolov51245c72016-12-01 11:34:10 -08002840
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002841 if (targetPackage == null || installerPackageName == null) {
2842 getErrPrintWriter().println("Must provide both target and installer package names");
Todd Kennedy74629e32017-08-15 14:48:07 -07002843 return 1;
2844 }
Todd Kennedy74629e32017-08-15 14:48:07 -07002845
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002846 mInterface.setInstallerPackageName(targetPackage, installerPackageName);
2847 getOutPrintWriter().println("Success");
Svet Ganov087dce22017-09-07 15:42:16 -07002848 return 0;
2849 }
2850
Todd Kennedy0a3f0812017-05-08 14:43:15 -07002851 private int runGetInstantAppResolver() {
2852 final PrintWriter pw = getOutPrintWriter();
2853 try {
2854 final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent();
2855 if (instantAppsResolver == null) {
2856 return 1;
2857 }
2858 pw.println(instantAppsResolver.flattenToString());
2859 return 0;
2860 } catch (Exception e) {
2861 pw.println(e.toString());
2862 return 1;
2863 }
2864 }
2865
Tadashi G. Takaokabe5782f2017-02-14 16:41:49 +09002866 private int runHasFeature() {
2867 final PrintWriter err = getErrPrintWriter();
2868 final String featureName = getNextArg();
2869 if (featureName == null) {
2870 err.println("Error: expected FEATURE name");
2871 return 1;
2872 }
2873 final String versionString = getNextArg();
2874 try {
2875 final int version = (versionString == null) ? 0 : Integer.parseInt(versionString);
2876 final boolean hasFeature = mInterface.hasSystemFeature(featureName, version);
2877 getOutPrintWriter().println(hasFeature);
2878 return hasFeature ? 0 : 1;
2879 } catch (NumberFormatException e) {
2880 err.println("Error: illegal version number " + versionString);
2881 return 1;
2882 } catch (RemoteException e) {
2883 err.println(e.toString());
2884 return 1;
2885 }
2886 }
2887
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002888 private int runDump() {
2889 String pkg = getNextArg();
2890 if (pkg == null) {
2891 getErrPrintWriter().println("Error: no package specified");
2892 return 1;
2893 }
2894 ActivityManager.dumpPackageStateStatic(getOutFileDescriptor(), pkg);
2895 return 0;
2896 }
2897
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002898 private int runSetHarmfulAppWarning() throws RemoteException {
2899 int userId = UserHandle.USER_CURRENT;
2900
2901 String opt;
2902 while ((opt = getNextOption()) != null) {
2903 if (opt.equals("--user")) {
2904 userId = UserHandle.parseUserArg(getNextArgRequired());
2905 } else {
2906 getErrPrintWriter().println("Error: Unknown option: " + opt);
2907 return -1;
2908 }
2909 }
2910
Todd Kennedyc3c52172019-11-26 13:20:59 -08002911 final int translatedUserId =
2912 translateUserId(userId, UserHandle.USER_NULL, "runSetHarmfulAppWarning");
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002913 final String packageName = getNextArgRequired();
2914 final String warning = getNextArg();
2915
Todd Kennedyc3c52172019-11-26 13:20:59 -08002916 mInterface.setHarmfulAppWarning(packageName, warning, translatedUserId);
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002917
2918 return 0;
2919 }
2920
Ben Gruver9ef60092018-01-10 11:32:30 -08002921 private int runGetHarmfulAppWarning() throws RemoteException {
2922 int userId = UserHandle.USER_CURRENT;
2923
2924 String opt;
2925 while ((opt = getNextOption()) != null) {
2926 if (opt.equals("--user")) {
2927 userId = UserHandle.parseUserArg(getNextArgRequired());
2928 } else {
2929 getErrPrintWriter().println("Error: Unknown option: " + opt);
2930 return -1;
2931 }
2932 }
2933
Todd Kennedyc3c52172019-11-26 13:20:59 -08002934 final int translatedUserId =
2935 translateUserId(userId, UserHandle.USER_NULL, "runGetHarmfulAppWarning");
Ben Gruver9ef60092018-01-10 11:32:30 -08002936 final String packageName = getNextArgRequired();
Todd Kennedyc3c52172019-11-26 13:20:59 -08002937 final CharSequence warning = mInterface.getHarmfulAppWarning(packageName, translatedUserId);
Ben Gruver9ef60092018-01-10 11:32:30 -08002938 if (!TextUtils.isEmpty(warning)) {
2939 getOutPrintWriter().println(warning);
2940 return 0;
2941 } else {
2942 return 1;
2943 }
2944 }
2945
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002946 private static String checkAbiArgument(String abi) {
2947 if (TextUtils.isEmpty(abi)) {
2948 throw new IllegalArgumentException("Missing ABI argument");
2949 }
2950
2951 if ("-".equals(abi)) {
2952 return abi;
2953 }
2954
2955 final String[] supportedAbis = Build.SUPPORTED_ABIS;
2956 for (String supportedAbi : supportedAbis) {
2957 if (supportedAbi.equals(abi)) {
2958 return abi;
2959 }
2960 }
2961
2962 throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
2963 }
2964
Todd Kennedyc3c52172019-11-26 13:20:59 -08002965 private int translateUserId(int userId, int allUserId, String logContext) {
2966 final boolean allowAll = (allUserId != UserHandle.USER_NULL);
2967 final int translatedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2968 Binder.getCallingUid(), userId, allowAll, true, logContext, "pm command");
2969 return translatedUserId == UserHandle.USER_ALL ? allUserId : translatedUserId;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002970 }
2971
2972 private int doCreateSession(SessionParams params, String installerPackageName, int userId)
2973 throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002974 if (userId == UserHandle.USER_ALL) {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002975 params.installFlags |= PackageManager.INSTALL_ALL_USERS;
2976 }
Todd Kennedyc3c52172019-11-26 13:20:59 -08002977 final int translatedUserId =
2978 translateUserId(userId, UserHandle.USER_SYSTEM, "doCreateSession");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002979 final int sessionId = mInterface.getPackageInstaller()
Todd Kennedyc3c52172019-11-26 13:20:59 -08002980 .createSession(params, installerPackageName, translatedUserId);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002981 return sessionId;
2982 }
2983
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08002984 private int doAddFiles(int sessionId, ArrayList<String> args, long sessionSizeBytes,
2985 boolean isApex) throws RemoteException {
Alex Buynytskyyda208152019-11-11 09:34:05 -08002986 PackageInstaller.Session session = new PackageInstaller.Session(
2987 mInterface.getPackageInstaller().openSession(sessionId));
2988 try {
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08002989 // 1. Single file from stdin.
2990 if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) {
2991 String name = "base." + (isApex ? "apex" : "apk");
Alex Buynytskyye0697872020-01-13 09:25:21 -08002992 session.addFile(LOCATION_DATA_APP, name, sessionSizeBytes, STDIN_PATH_BYTES, null);
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08002993 return 0;
Alex Buynytskyyda208152019-11-11 09:34:05 -08002994 }
2995
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08002996 for (String arg : args) {
2997 final int delimLocation = arg.indexOf(':');
2998
2999 // 2. File with specified size read from stdin.
3000 if (delimLocation != -1) {
3001 String name = arg.substring(0, delimLocation);
3002 String sizeStr = arg.substring(delimLocation + 1);
3003 long sizeBytes;
3004
3005 if (TextUtils.isEmpty(name)) {
3006 getErrPrintWriter().println("Empty file name in: " + arg);
3007 return 1;
3008 }
3009 try {
3010 sizeBytes = Long.parseUnsignedLong(sizeStr);
3011 } catch (NumberFormatException e) {
3012 getErrPrintWriter().println("Unable to parse size from: " + arg);
3013 return 1;
3014 }
3015
Alex Buynytskyy04f73912020-02-10 08:34:18 -08003016 // Incremental requires unique metadatas, let's add a name to the dash.
3017 session.addFile(LOCATION_DATA_APP, name, sizeBytes,
3018 ("-" + name).getBytes(StandardCharsets.UTF_8), null);
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003019 continue;
3020 }
3021
3022 // 3. Local file.
3023 final String inPath = arg;
3024
Alex Buynytskyy04f73912020-02-10 08:34:18 -08003025 final File file = new File(inPath);
3026 final String name = file.getName();
3027 final long size = file.length();
Alex Buynytskyy8e9e6a32020-02-08 14:26:45 -08003028 final byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8);
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003029
Alex Buynytskyy8e9e6a32020-02-08 14:26:45 -08003030 // Try to load a v4 signature for the APK.
3031 final V4Signature v4signature = V4Signature.readFrom(
3032 new File(inPath + V4Signature.EXT));
3033 final byte[] v4signatureBytes =
3034 (v4signature != null) ? v4signature.toByteArray() : null;
3035
3036 session.addFile(LOCATION_DATA_APP, name, size, metadata, v4signatureBytes);
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003037 }
Alex Buynytskyyda208152019-11-11 09:34:05 -08003038 return 0;
3039 } finally {
3040 IoUtils.closeQuietly(session);
3041 }
3042 }
3043
Alex Buynytskyy43dd0b92020-01-10 13:40:36 -08003044 private int doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes,
3045 boolean isApex) throws RemoteException {
3046 final boolean multipleSplits = splitPaths.size() > 1;
3047 for (String splitPath : splitPaths) {
3048 String splitName = multipleSplits ? new File(splitPath).getName()
3049 : "base." + (isApex ? "apex" : "apk");
3050
3051 if (doWriteSplit(sessionId, splitPath, sessionSizeBytes, splitName,
3052 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
3053 return 1;
3054 }
3055 }
3056 return 0;
3057 }
3058
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003059 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003060 boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003061 PackageInstaller.Session session = null;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003062 try {
Alex Buynytskyyda208152019-11-11 09:34:05 -08003063 session = new PackageInstaller.Session(
3064 mInterface.getPackageInstaller().openSession(sessionId));
3065
Jeff Sharkeya651b782018-07-23 13:45:28 -06003066 final PrintWriter pw = getOutPrintWriter();
Alex Buynytskyyda208152019-11-11 09:34:05 -08003067
Jeff Sharkeya651b782018-07-23 13:45:28 -06003068 final ParcelFileDescriptor fd;
3069 if (STDIN_PATH.equals(inPath)) {
3070 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
3071 } else if (inPath != null) {
3072 fd = openFileForSystem(inPath, "r");
3073 if (fd == null) {
3074 return -1;
3075 }
3076 sizeBytes = fd.getStatSize();
3077 if (sizeBytes < 0) {
3078 getErrPrintWriter().println("Unable to get size of: " + inPath);
3079 return -1;
3080 }
3081 } else {
3082 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
3083 }
3084 if (sizeBytes <= 0) {
3085 getErrPrintWriter().println("Error: must specify a APK size");
3086 return 1;
3087 }
3088
Jeff Sharkey0451de62018-02-02 11:27:21 -07003089 session.write(splitName, 0, sizeBytes, fd);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003090
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003091 if (logSuccess) {
Jeff Sharkey0451de62018-02-02 11:27:21 -07003092 pw.println("Success: streamed " + sizeBytes + " bytes");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003093 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003094 return 0;
3095 } catch (IOException e) {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07003096 getErrPrintWriter().println("Error: failed to write; " + e.getMessage());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003097 return 1;
3098 } finally {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003099 IoUtils.closeQuietly(session);
3100 }
3101 }
3102
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003103 private int doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)
3104 throws RemoteException {
3105 final PrintWriter pw = getOutPrintWriter();
3106 PackageInstaller.Session session = null;
3107 try {
3108 session = new PackageInstaller.Session(
3109 mInterface.getPackageInstaller().openSession(parentId));
3110 if (!session.isMultiPackage()) {
3111 getErrPrintWriter().println(
3112 "Error: parent session ID is not a multi-package session");
3113 return 1;
3114 }
3115 for (int i = 0; i < sessionIds.length; i++) {
3116 session.addChildSessionId(sessionIds[i]);
3117 }
3118 if (logSuccess) {
3119 pw.println("Success");
3120 }
3121 return 0;
3122 } finally {
3123 IoUtils.closeQuietly(session);
3124 }
3125 }
3126
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003127 private int doRemoveSplits(int sessionId, Collection<String> splitNames, boolean logSuccess)
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003128 throws RemoteException {
3129 final PrintWriter pw = getOutPrintWriter();
3130 PackageInstaller.Session session = null;
3131 try {
3132 session = new PackageInstaller.Session(
3133 mInterface.getPackageInstaller().openSession(sessionId));
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003134 for (String splitName : splitNames) {
3135 session.removeSplit(splitName);
3136 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -08003137
3138 if (logSuccess) {
3139 pw.println("Success");
3140 }
3141 return 0;
3142 } catch (IOException e) {
3143 pw.println("Error: failed to remove split; " + e.getMessage());
3144 return 1;
3145 } finally {
3146 IoUtils.closeQuietly(session);
3147 }
3148 }
3149
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003150 private int doCommitSession(int sessionId, boolean logSuccess)
3151 throws RemoteException {
3152
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003153 final PrintWriter pw = getOutPrintWriter();
3154 PackageInstaller.Session session = null;
3155 try {
3156 session = new PackageInstaller.Session(
3157 mInterface.getPackageInstaller().openSession(sessionId));
Dario Frenia8f4b132018-12-30 00:36:49 +00003158 if (!session.isMultiPackage() && !session.isStaged()) {
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003159 // Sanity check that all .dm files match an apk.
3160 // (The installer does not support standalone .dm files and will not process them.)
3161 try {
3162 DexMetadataHelper.validateDexPaths(session.getNames());
3163 } catch (IllegalStateException | IOException e) {
3164 pw.println(
3165 "Warning [Could not validate the dex paths: " + e.getMessage() + "]");
3166 }
Calin Juravle3fc56c32017-12-11 18:26:13 -08003167 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003168 final LocalIntentReceiver receiver = new LocalIntentReceiver();
3169 session.commit(receiver.getIntentSender());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003170 final Intent result = receiver.getResult();
3171 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
3172 PackageInstaller.STATUS_FAILURE);
3173 if (status == PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003174 if (logSuccess) {
Todd Kennedyb6e96e52016-07-20 16:27:39 -07003175 pw.println("Success");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003176 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003177 } else {
3178 pw.println("Failure ["
3179 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003180 }
3181 return status;
3182 } finally {
3183 IoUtils.closeQuietly(session);
3184 }
3185 }
3186
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003187 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003188 final PrintWriter pw = getOutPrintWriter();
3189 PackageInstaller.Session session = null;
3190 try {
3191 session = new PackageInstaller.Session(
3192 mInterface.getPackageInstaller().openSession(sessionId));
3193 session.abandon();
Todd Kennedy8d9366c2015-12-16 13:47:14 -08003194 if (logSuccess) {
3195 pw.println("Success");
3196 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003197 return 0;
3198 } finally {
3199 IoUtils.closeQuietly(session);
3200 }
3201 }
3202
Todd Kennedy60459ab2015-10-30 11:32:16 -07003203 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
3204 boolean summary, int startProtectionLevel, int endProtectionLevel)
3205 throws RemoteException {
3206 final PrintWriter pw = getOutPrintWriter();
3207 final int groupCount = groupList.size();
3208 for (int i = 0; i < groupCount; i++) {
3209 String groupName = groupList.get(i);
3210 String prefix = "";
3211 if (groups) {
3212 if (i > 0) {
3213 pw.println("");
3214 }
3215 if (groupName != null) {
3216 PermissionGroupInfo pgi =
3217 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
3218 if (summary) {
3219 Resources res = getResources(pgi);
3220 if (res != null) {
3221 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
3222 } else {
3223 pw.print(pgi.name + ": ");
3224
3225 }
3226 } else {
3227 pw.println((labels ? "+ " : "") + "group:" + pgi.name);
3228 if (labels) {
3229 pw.println(" package:" + pgi.packageName);
3230 Resources res = getResources(pgi);
3231 if (res != null) {
3232 pw.println(" label:"
3233 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
3234 pw.println(" description:"
3235 + loadText(pgi, pgi.descriptionRes,
3236 pgi.nonLocalizedDescription));
3237 }
3238 }
3239 }
3240 } else {
3241 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
3242 }
3243 prefix = " ";
3244 }
Todd Kennedy1d29b4a2019-07-02 14:49:28 -07003245 List<PermissionInfo> ps = mPermissionManager
3246 .queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -07003247 final int count = ps.size();
3248 boolean first = true;
3249 for (int p = 0 ; p < count ; p++) {
3250 PermissionInfo pi = ps.get(p);
3251 if (groups && groupName == null && pi.group != null) {
3252 continue;
3253 }
3254 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
3255 if (base < startProtectionLevel
3256 || base > endProtectionLevel) {
3257 continue;
3258 }
3259 if (summary) {
3260 if (first) {
3261 first = false;
3262 } else {
3263 pw.print(", ");
3264 }
3265 Resources res = getResources(pi);
3266 if (res != null) {
3267 pw.print(loadText(pi, pi.labelRes,
3268 pi.nonLocalizedLabel));
3269 } else {
3270 pw.print(pi.name);
3271 }
3272 } else {
3273 pw.println(prefix + (labels ? "+ " : "")
3274 + "permission:" + pi.name);
3275 if (labels) {
3276 pw.println(prefix + " package:" + pi.packageName);
3277 Resources res = getResources(pi);
3278 if (res != null) {
3279 pw.println(prefix + " label:"
3280 + loadText(pi, pi.labelRes,
3281 pi.nonLocalizedLabel));
3282 pw.println(prefix + " description:"
3283 + loadText(pi, pi.descriptionRes,
3284 pi.nonLocalizedDescription));
3285 }
3286 pw.println(prefix + " protectionLevel:"
3287 + PermissionInfo.protectionToString(pi.protectionLevel));
3288 }
3289 }
3290 }
3291
3292 if (summary) {
3293 pw.println("");
3294 }
3295 }
3296 }
3297
3298 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
3299 throws RemoteException {
3300 if (nonLocalized != null) {
3301 return nonLocalized.toString();
3302 }
3303 if (res != 0) {
3304 Resources r = getResources(pii);
3305 if (r != null) {
3306 try {
3307 return r.getString(res);
3308 } catch (Resources.NotFoundException e) {
3309 }
3310 }
3311 }
3312 return null;
3313 }
3314
3315 private Resources getResources(PackageItemInfo pii) throws RemoteException {
3316 Resources res = mResourceCache.get(pii.packageName);
3317 if (res != null) return res;
3318
Patrick Baumannbc883f62019-05-21 11:20:11 -07003319 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName,
3320 PackageManager.MATCH_DISABLED_COMPONENTS
3321 | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
3322 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, 0);
Todd Kennedy60459ab2015-10-30 11:32:16 -07003323 AssetManager am = new AssetManager();
3324 am.addAssetPath(ai.publicSourceDir);
3325 res = new Resources(am, null, null);
3326 mResourceCache.put(pii.packageName, res);
3327 return res;
3328 }
3329
3330 @Override
3331 public void onHelp() {
3332 final PrintWriter pw = getOutPrintWriter();
3333 pw.println("Package manager (package) commands:");
3334 pw.println(" help");
3335 pw.println(" Print this help text.");
3336 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003337 pw.println(" path [--user USER_ID] PACKAGE");
3338 pw.println(" Print the path to the .apk of the given PACKAGE.");
3339 pw.println("");
3340 pw.println(" dump PACKAGE");
3341 pw.println(" Print various system state associated with the given PACKAGE.");
3342 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003343 pw.println(" has-feature FEATURE_NAME [version]");
3344 pw.println(" Prints true and returns exit status 0 when system has a FEATURE_NAME,");
3345 pw.println(" otherwise prints false and returns exit status 1");
3346 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003347 pw.println(" list features");
3348 pw.println(" Prints all features of the system.");
3349 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003350 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
3351 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE");
3352 pw.println(" Options:");
3353 pw.println(" -f: dump the name of the .apk file containing the test package");
3354 pw.println("");
3355 pw.println(" list libraries");
3356 pw.println(" Prints all system libraries.");
3357 pw.println("");
3358 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
Jiyong Parkf50a2932018-12-17 13:54:40 +09003359 pw.println(" [--show-versioncode] [--apex-only] [--uid UID] [--user USER_ID] [FILTER]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003360 pw.println(" Prints all packages; optionally only those whose name contains");
3361 pw.println(" the text in FILTER. Options are:");
3362 pw.println(" -f: see their associated file");
Jiyong Park4f49abe2018-12-11 13:37:17 +09003363 pw.println(" -a: all known packages (but excluding APEXes)");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003364 pw.println(" -d: filter to only show disabled packages");
3365 pw.println(" -e: filter to only show enabled packages");
3366 pw.println(" -s: filter to only show system packages");
3367 pw.println(" -3: filter to only show third party packages");
3368 pw.println(" -i: see the installer for the packages");
3369 pw.println(" -l: ignored (used for compatibility with older releases)");
3370 pw.println(" -U: also show the package UID");
3371 pw.println(" -u: also include uninstalled packages");
Jiyong Parkf50a2932018-12-17 13:54:40 +09003372 pw.println(" --show-versioncode: also show the version code");
Jiyong Park4f49abe2018-12-11 13:37:17 +09003373 pw.println(" --apex-only: only show APEX packages");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003374 pw.println(" --uid UID: filter to only show packages with the given UID");
3375 pw.println(" --user USER_ID: only list packages belonging to the given user");
3376 pw.println("");
3377 pw.println(" list permission-groups");
3378 pw.println(" Prints all known permission groups.");
3379 pw.println("");
3380 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
3381 pw.println(" Prints all known permissions; optionally only those in GROUP. Options are:");
3382 pw.println(" -g: organize by group");
3383 pw.println(" -f: print all information");
3384 pw.println(" -s: short summary");
3385 pw.println(" -d: only list dangerous permissions");
3386 pw.println(" -u: list only the permissions users will see");
3387 pw.println("");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003388 pw.println(" list staged-sessions [--only-ready] [--only-sessionid] [--only-parent]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003389 pw.println(" Prints all staged sessions.");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003390 pw.println(" --only-ready: show only staged sessions that are ready");
3391 pw.println(" --only-sessionid: show only sessionId of each session");
3392 pw.println(" --only-parent: hide all children sessions");
3393 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003394 pw.println(" list users");
3395 pw.println(" Prints all users.");
3396 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003397 pw.println(" resolve-activity [--brief] [--components] [--query-flags FLAGS]");
3398 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003399 pw.println(" Prints the activity that resolves to the given INTENT.");
3400 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003401 pw.println(" query-activities [--brief] [--components] [--query-flags FLAGS]");
3402 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003403 pw.println(" Prints all activities that can handle the given INTENT.");
3404 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003405 pw.println(" query-services [--brief] [--components] [--query-flags FLAGS]");
3406 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003407 pw.println(" Prints all services that can handle the given INTENT.");
3408 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07003409 pw.println(" query-receivers [--brief] [--components] [--query-flags FLAGS]");
3410 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003411 pw.println(" Prints all broadcast receivers that can handle the given INTENT.");
3412 pw.println("");
Mark De Ruyterbfcd3392019-11-21 12:08:58 -08003413 pw.println(" install [-rtfdgw] [-i PACKAGE] [--user USER_ID|all|current]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003414 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003415 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
3416 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003417 pw.println(" [--preload] [--instant] [--full] [--dont-kill]");
Richard Uhlerb29f1452018-09-12 16:38:15 +01003418 pw.println(" [--enable-rollback]");
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01003419 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
3420 pw.println(" [--apex] [--wait TIMEOUT]");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003421 pw.println(" [PATH [SPLIT...]|-]");
3422 pw.println(" Install an application. Must provide the apk data to install, either as");
3423 pw.println(" file path(s) or '-' to read from stdin. Options are:");
Patrick Baumanna9333492017-11-28 15:23:49 -08003424 pw.println(" -R: disallow replacement of existing application");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003425 pw.println(" -t: allow test packages");
3426 pw.println(" -i: specify package name of installer owning the app");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003427 pw.println(" -f: install application on internal flash");
3428 pw.println(" -d: allow version code downgrade (debuggable packages only)");
3429 pw.println(" -p: partial application install (new split on top of existing pkg)");
3430 pw.println(" -g: grant all runtime permissions");
3431 pw.println(" -S: size in bytes of package, required for stdin");
3432 pw.println(" --user: install under the given user.");
3433 pw.println(" --dont-kill: installing a new feature split, don't kill running app");
Svet Ganov83a3a4a2019-05-03 18:50:43 -07003434 pw.println(" --restrict-permissions: don't whitelist restricted permissions at install");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003435 pw.println(" --originating-uri: set URI where app was downloaded from");
3436 pw.println(" --referrer: set URI that instigated the install of the app");
3437 pw.println(" --pkg: specify expected package name of app being installed");
3438 pw.println(" --abi: override the default ABI of the platform");
Todd Kennedybef39e02019-09-20 15:14:18 -07003439 pw.println(" --instant: cause the app to be installed as an ephemeral install app");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003440 pw.println(" --full: cause the app to be installed as a non-ephemeral full app");
3441 pw.println(" --install-location: force the install location:");
3442 pw.println(" 0=auto, 1=internal only, 2=prefer external");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003443 pw.println(" --install-reason: indicates why the app is being installed:");
3444 pw.println(" 0=unknown, 1=admin policy, 2=device restore,");
3445 pw.println(" 3=device setup, 4=user request");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003446 pw.println(" --force-uuid: force install on to disk volume with given UUID");
MÃ¥rten Kongstad2a5989342018-11-16 15:04:44 +01003447 pw.println(" --apex: install an .apex file, not an .apk");
Mohammad Samiul Islambd02f422019-05-17 18:02:12 +01003448 pw.println(" --wait: when performing staged install, wait TIMEOUT milliseconds");
3449 pw.println(" for pre-reboot verification to complete. If TIMEOUT is not");
3450 pw.println(" specified it will wait for " + DEFAULT_WAIT_MS + " milliseconds.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003451 pw.println("");
Todd Kennedybef39e02019-09-20 15:14:18 -07003452 pw.println(" install-existing [--user USER_ID|all|current]");
3453 pw.println(" [--instant] [--full] [--wait] [--restrict-permissions] PACKAGE");
3454 pw.println(" Installs an existing application for a new user. Options are:");
3455 pw.println(" --user: install for the given user.");
3456 pw.println(" --instant: install as an instant app");
3457 pw.println(" --full: install as a full app");
3458 pw.println(" --wait: wait until the package is installed");
3459 pw.println(" --restrict-permissions: don't whitelist restricted permissions");
3460 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003461 pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
3462 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
Sunny Goyalabd4d442018-09-19 15:49:50 -07003463 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
3464 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
Todd Kennedybef39e02019-09-20 15:14:18 -07003465 pw.println(" [--preload] [--instant] [--full] [--dont-kill]");
MÃ¥rten Kongstad2a5989342018-11-16 15:04:44 +01003466 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [--apex] [-S BYTES]");
Dario Freniaac4ba42018-12-06 15:47:16 +00003467 pw.println(" [--multi-package] [--staged]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003468 pw.println(" Like \"install\", but starts an install session. Use \"install-write\"");
3469 pw.println(" to push data into the session, and \"install-commit\" to finish.");
3470 pw.println("");
3471 pw.println(" install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]");
3472 pw.println(" Write an apk into the given install session. If the path is '-', data");
3473 pw.println(" will be read from stdin. Options are:");
3474 pw.println(" -S: size in bytes of package, required for stdin");
3475 pw.println("");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003476 pw.println(" install-remove SESSION_ID SPLIT...");
3477 pw.println(" Mark SPLIT(s) as removed in the given install session.");
3478 pw.println("");
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003479 pw.println(" install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs");
3480 pw.println(" Add one or more session IDs to a multi-package session.");
3481 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003482 pw.println(" install-commit SESSION_ID");
3483 pw.println(" Commit the given active install session, installing the app.");
3484 pw.println("");
3485 pw.println(" install-abandon SESSION_ID");
3486 pw.println(" Delete the given active install session.");
3487 pw.println("");
3488 pw.println(" set-install-location LOCATION");
3489 pw.println(" Changes the default install location. NOTE this is only intended for debugging;");
3490 pw.println(" using this can cause applications to break and other undersireable behavior.");
3491 pw.println(" LOCATION is one of:");
3492 pw.println(" 0 [auto]: Let system decide the best location");
3493 pw.println(" 1 [internal]: Install on internal device storage");
3494 pw.println(" 2 [external]: Install on external media");
3495 pw.println("");
3496 pw.println(" get-install-location");
3497 pw.println(" Returns the current install location: 0, 1 or 2 as per set-install-location.");
3498 pw.println("");
3499 pw.println(" move-package PACKAGE [internal|UUID]");
3500 pw.println("");
3501 pw.println(" move-primary-storage [internal|UUID]");
3502 pw.println("");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003503 pw.println(" uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE]");
3504 pw.println(" PACKAGE [SPLIT...]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003505 pw.println(" Remove the given package name from the system. May remove an entire app");
Alex Buynytskyyf3ff9662019-11-11 20:52:45 +00003506 pw.println(" if no SPLIT names specified, otherwise will remove only the splits of the");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003507 pw.println(" given app. Options are:");
3508 pw.println(" -k: keep the data and cache directories around after package removal.");
3509 pw.println(" --user: remove the app from the given user.");
3510 pw.println(" --versionCode: only uninstall if the app has the given version code.");
3511 pw.println("");
3512 pw.println(" clear [--user USER_ID] PACKAGE");
3513 pw.println(" Deletes all data associated with a package.");
3514 pw.println("");
3515 pw.println(" enable [--user USER_ID] PACKAGE_OR_COMPONENT");
3516 pw.println(" disable [--user USER_ID] PACKAGE_OR_COMPONENT");
3517 pw.println(" disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
3518 pw.println(" disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
3519 pw.println(" default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
3520 pw.println(" These commands change the enabled state of a given package or");
3521 pw.println(" component (written as \"package/class\").");
3522 pw.println("");
3523 pw.println(" hide [--user USER_ID] PACKAGE_OR_COMPONENT");
3524 pw.println(" unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
3525 pw.println("");
3526 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE");
3527 pw.println(" Suspends the specified package (as user).");
3528 pw.println("");
3529 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE");
3530 pw.println(" Unsuspends the specified package (as user).");
3531 pw.println("");
3532 pw.println(" grant [--user USER_ID] PACKAGE PERMISSION");
3533 pw.println(" revoke [--user USER_ID] PACKAGE PERMISSION");
3534 pw.println(" These commands either grant or revoke permissions to apps. The permissions");
3535 pw.println(" must be declared as used in the app's manifest, be runtime permissions");
3536 pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
3537 pw.println("");
3538 pw.println(" reset-permissions");
3539 pw.println(" Revert all runtime permissions to their default state.");
3540 pw.println("");
3541 pw.println(" set-permission-enforced PERMISSION [true|false]");
3542 pw.println("");
3543 pw.println(" get-privapp-permissions TARGET-PACKAGE");
3544 pw.println(" Prints all privileged permissions for a package.");
3545 pw.println("");
3546 pw.println(" get-privapp-deny-permissions TARGET-PACKAGE");
3547 pw.println(" Prints all privileged permissions that are denied for a package.");
3548 pw.println("");
3549 pw.println(" get-oem-permissions TARGET-PACKAGE");
3550 pw.println(" Prints all OEM permissions for a package.");
3551 pw.println("");
3552 pw.println(" set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
3553 pw.println(" get-app-link [--user USER_ID] PACKAGE");
3554 pw.println("");
3555 pw.println(" trim-caches DESIRED_FREE_SPACE [internal|UUID]");
3556 pw.println(" Trim cache files to reach the given free space.");
3557 pw.println("");
Felipe Lemec1ca4412019-09-11 09:23:26 -07003558 pw.println(" list users");
3559 pw.println(" Lists the current users.");
3560 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003561 pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
Bookatz029832a2019-10-04 16:50:22 -07003562 pw.println(" [--guest] [--pre-create-only] [--user-type USER_TYPE] USER_NAME");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003563 pw.println(" Create a new user with the given USER_NAME, printing the new user identifier");
3564 pw.println(" of the user.");
Bookatz029832a2019-10-04 16:50:22 -07003565 // TODO(b/142482943): Consider fetching the list of user types from UMS.
3566 pw.println(" USER_TYPE is the name of a user type, e.g. android.os.usertype.profile.MANAGED.");
3567 pw.println(" If not specified, the default user type is android.os.usertype.full.SECONDARY.");
3568 pw.println(" --managed is shorthand for '--user-type android.os.usertype.profile.MANAGED'.");
3569 pw.println(" --restricted is shorthand for '--user-type android.os.usertype.full.RESTRICTED'.");
3570 pw.println(" --guest is shorthand for '--user-type android.os.usertype.full.GUEST'.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003571 pw.println("");
3572 pw.println(" remove-user USER_ID");
3573 pw.println(" Remove the user with the given USER_IDENTIFIER, deleting all data");
3574 pw.println(" associated with that user");
3575 pw.println("");
3576 pw.println(" set-user-restriction [--user USER_ID] RESTRICTION VALUE");
3577 pw.println("");
3578 pw.println(" get-max-users");
3579 pw.println("");
Alex Chauc12189b2018-01-16 15:01:15 +00003580 pw.println(" get-max-running-users");
3581 pw.println("");
Calin Juravleb6f844d2017-07-17 15:23:21 -07003582 pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
Richard Uhler568a9692016-05-03 16:02:52 -07003583 pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003584 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\". Options are:");
David Brazdil990fb6b2016-03-01 10:02:27 +00003585 pw.println(" -a: compile all packages");
David Brazdil9aa6db02016-03-08 12:57:12 +00003586 pw.println(" -c: clear profile data before compiling");
3587 pw.println(" -f: force compilation even if not needed");
David Brazdil493411a2016-02-01 13:48:46 +00003588 pw.println(" -m: select compilation mode");
Richard Uhler568a9692016-05-03 16:02:52 -07003589 pw.println(" MODE is one of the dex2oat compiler filters:");
Nicolas Geoffrayd1326522017-04-25 12:29:07 +01003590 pw.println(" assume-verified");
3591 pw.println(" extract");
3592 pw.println(" verify");
3593 pw.println(" quicken");
Richard Uhler568a9692016-05-03 16:02:52 -07003594 pw.println(" space-profile");
3595 pw.println(" space");
3596 pw.println(" speed-profile");
3597 pw.println(" speed");
3598 pw.println(" everything");
3599 pw.println(" -r: select compilation reason");
3600 pw.println(" REASON is one of:");
3601 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
3602 pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
3603 }
David Brazdilcf046952016-03-08 16:40:20 +00003604 pw.println(" --reset: restore package to its post-install state");
Richard Uhler568a9692016-05-03 16:02:52 -07003605 pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
Calin Juravlecb5f41e2017-01-25 17:16:08 -08003606 pw.println(" --secondary-dex: compile app secondary dex files");
Calin Juravleb6f844d2017-07-17 15:23:21 -07003607 pw.println(" --split SPLIT: compile only the given split name");
Eric Holka1485f62019-01-07 13:58:25 -08003608 pw.println(" --compile-layouts: compile layout resources for faster inflation");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003609 pw.println("");
3610 pw.println(" force-dex-opt PACKAGE");
3611 pw.println(" Force immediate execution of dex opt for the given PACKAGE.");
3612 pw.println("");
Calin Juravlecb5f41e2017-01-25 17:16:08 -08003613 pw.println(" bg-dexopt-job");
3614 pw.println(" Execute the background optimizations immediately.");
3615 pw.println(" Note that the command only runs the background optimizer logic. It may");
3616 pw.println(" overlap with the actual job but the job scheduler will not be able to");
3617 pw.println(" cancel it. It will also run even if the device is not in the idle");
3618 pw.println(" maintenance mode.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003619 pw.println("");
Calin Juravle1aa5f882017-01-25 01:05:50 -08003620 pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE");
3621 pw.println(" Reconciles the package secondary dex files with the generated oat files.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003622 pw.println("");
David Sehrcae13b02016-06-07 09:11:27 -07003623 pw.println(" dump-profiles TARGET-PACKAGE");
3624 pw.println(" Dumps method/class profile files to");
Calin Juravle21216c62018-05-04 17:35:29 -07003625 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + "TARGET-PACKAGE.txt");
3626 pw.println("");
3627 pw.println(" snapshot-profile TARGET-PACKAGE [--code-path path]");
3628 pw.println(" Take a snapshot of the package profiles to");
3629 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION
3630 + "TARGET-PACKAGE[-code-path].prof");
3631 pw.println(" If TARGET-PACKAGE=android it will take a snapshot of the boot image");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003632 pw.println("");
Makoto Onuki4828a592016-03-15 18:06:57 -07003633 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003634 pw.println(" Set the default home activity (aka launcher).");
Bookatz2b5a6012019-04-16 19:41:28 -07003635 pw.println(" TARGET-COMPONENT can be a package name (com.package.my) or a full");
3636 pw.println(" component (com.package.my/component.name). However, only the package name");
3637 pw.println(" matters: the actual component used will be determined automatically from");
3638 pw.println(" the package.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003639 pw.println("");
3640 pw.println(" set-installer PACKAGE INSTALLER");
3641 pw.println(" Set installer package name");
3642 pw.println("");
3643 pw.println(" get-instantapp-resolver");
3644 pw.println(" Return the name of the component that is the current instant app installer.");
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08003645 pw.println("");
3646 pw.println(" set-harmful-app-warning [--user <USER_ID>] <PACKAGE> [<WARNING>]");
3647 pw.println(" Mark the app as harmful with the given warning message.");
Ben Gruver9ef60092018-01-10 11:32:30 -08003648 pw.println("");
3649 pw.println(" get-harmful-app-warning [--user <USER_ID>] <PACKAGE>");
3650 pw.println(" Return the harmful app warning message for the given app, if present");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08003651 pw.println();
Patrick Baumanna980e142018-02-12 11:45:23 -08003652 pw.println(" uninstall-system-updates");
3653 pw.println(" Remove updates to all system applications and fall back to their /system " +
3654 "version.");
Mohammad Samiul Islamf50641a2019-09-02 14:37:33 +01003655 pw.println("");
Mohammad Samiul Islamc46ff382019-05-09 15:36:21 +01003656 pw.println(" get-moduleinfo [--all | --installed] [module-name]");
3657 pw.println(" Displays module info. If module-name is specified only that info is shown");
3658 pw.println(" By default, without any argument only installed modules are shown.");
3659 pw.println(" --all: show all module info");
3660 pw.println(" --installed: show only installed modules");
3661 pw.println("");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08003662 Intent.printIntentArgsHelp(pw , "");
Todd Kennedy60459ab2015-10-30 11:32:16 -07003663 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003664
3665 private static class LocalIntentReceiver {
wangmingming155414292018-04-10 09:35:25 +08003666 private final LinkedBlockingQueue<Intent> mResult = new LinkedBlockingQueue<>();
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003667
3668 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
3669 @Override
Dianne Hackborn98305522017-05-05 17:53:53 -07003670 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003671 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
3672 try {
3673 mResult.offer(intent, 5, TimeUnit.SECONDS);
3674 } catch (InterruptedException e) {
3675 throw new RuntimeException(e);
3676 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003677 }
3678 };
3679
3680 public IntentSender getIntentSender() {
3681 return new IntentSender((IIntentSender) mLocalSender);
3682 }
3683
3684 public Intent getResult() {
3685 try {
3686 return mResult.take();
3687 } catch (InterruptedException e) {
3688 throw new RuntimeException(e);
3689 }
3690 }
3691 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07003692}