blob: 2d1afa7e87a75a0cb35818eb6b120425ee7f514d [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
Jeff Sharkey0451de62018-02-02 11:27:21 -070019import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
20import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
21import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
22import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
23import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
24
Dianne Hackbornc81983a2017-10-20 16:16:32 -070025import android.accounts.IAccountManager;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080026import android.app.ActivityManager;
Alex Chauc12189b2018-01-16 15:01:15 +000027import android.app.ActivityManagerInternal;
Todd Kennedy60459ab2015-10-30 11:32:16 -070028import android.content.ComponentName;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070029import android.content.Context;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080030import android.content.IIntentReceiver;
31import android.content.IIntentSender;
32import android.content.Intent;
33import android.content.IntentSender;
Todd Kennedy60459ab2015-10-30 11:32:16 -070034import android.content.pm.ApplicationInfo;
35import android.content.pm.FeatureInfo;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070036import android.content.pm.IPackageDataObserver;
Patrick Baumanna980e142018-02-12 11:45:23 -080037import android.content.pm.IPackageInstaller;
Todd Kennedy60459ab2015-10-30 11:32:16 -070038import android.content.pm.IPackageManager;
39import android.content.pm.InstrumentationInfo;
40import android.content.pm.PackageInfo;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080041import android.content.pm.PackageInstaller;
Abhijeet Kaur84b1f5d2019-01-21 17:18:03 +000042import android.content.pm.PackageInstaller.SessionInfo;
Jeff Sharkey0451de62018-02-02 11:27:21 -070043import android.content.pm.PackageInstaller.SessionParams;
Todd Kennedy60459ab2015-10-30 11:32:16 -070044import android.content.pm.PackageItemInfo;
45import android.content.pm.PackageManager;
Jeff Sharkey0451de62018-02-02 11:27:21 -070046import android.content.pm.PackageManager.NameNotFoundException;
Dario Freni788ecb12019-01-23 18:49:32 +000047import android.content.pm.PackageManagerInternal;
Shunta Sato4f26cb52016-06-28 09:29:19 +090048import android.content.pm.PackageParser;
49import android.content.pm.PackageParser.ApkLite;
50import android.content.pm.PackageParser.PackageLite;
51import android.content.pm.PackageParser.PackageParserException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070052import android.content.pm.ParceledListSlice;
53import android.content.pm.PermissionGroupInfo;
54import android.content.pm.PermissionInfo;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080055import android.content.pm.ResolveInfo;
Suprabh Shukla389cb6f2018-10-01 18:20:39 -070056import android.content.pm.SuspendDialogInfo;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070057import android.content.pm.UserInfo;
Svet Ganov67882122016-12-11 16:36:34 -080058import android.content.pm.VersionedPackage;
Calin Juravle21216c62018-05-04 17:35:29 -070059import android.content.pm.dex.ArtManager;
Calin Juravle3fc56c32017-12-11 18:26:13 -080060import android.content.pm.dex.DexMetadataHelper;
Calin Juravle21216c62018-05-04 17:35:29 -070061import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
Todd Kennedy60459ab2015-10-30 11:32:16 -070062import android.content.res.AssetManager;
63import android.content.res.Resources;
Narayan Kamathc5d752e2019-01-23 14:06:35 +000064import android.content.rollback.IRollbackManager;
65import android.content.rollback.PackageRollbackInfo;
66import android.content.rollback.RollbackInfo;
67import android.content.rollback.RollbackManager;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080068import android.net.Uri;
69import android.os.Binder;
70import android.os.Build;
71import android.os.Bundle;
Dianne Hackborn98305522017-05-05 17:53:53 -070072import android.os.IBinder;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070073import android.os.IUserManager;
Dianne Hackbornca3872c2017-10-30 14:19:32 -070074import android.os.ParcelFileDescriptor;
Calin Juravle21216c62018-05-04 17:35:29 -070075import android.os.ParcelFileDescriptor.AutoCloseInputStream;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080076import android.os.PersistableBundle;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070077import android.os.Process;
Todd Kennedy60459ab2015-10-30 11:32:16 -070078import android.os.RemoteException;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070079import android.os.ServiceManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -070080import android.os.ShellCommand;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070081import android.os.SystemClock;
Calin Juravle8bc758b2016-03-28 12:31:52 +010082import android.os.SystemProperties;
Todd Kennedy60459ab2015-10-30 11:32:16 -070083import android.os.UserHandle;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070084import android.os.UserManager;
85import android.os.storage.StorageManager;
Calin Juravlebdd94d92018-05-17 01:23:15 -070086import android.system.ErrnoException;
87import android.system.Os;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080088import android.text.TextUtils;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070089import android.text.format.DateUtils;
Fyodor Kupolov51245c72016-12-01 11:34:10 -080090import android.util.ArraySet;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080091import android.util.PrintWriterPrinter;
Dario Freni2bef1762018-06-01 14:02:08 +010092
Shunta Sato4f26cb52016-06-28 09:29:19 +090093import com.android.internal.content.PackageHelper;
Dianne Hackbornc81983a2017-10-20 16:16:32 -070094import com.android.internal.util.ArrayUtils;
Alex Chauc12189b2018-01-16 15:01:15 +000095import com.android.server.LocalServices;
Fyodor Kupolov51245c72016-12-01 11:34:10 -080096import com.android.server.SystemConfig;
Dario Freni2bef1762018-06-01 14:02:08 +010097
Andreas Gampebdd30d82016-03-20 11:32:11 -070098import dalvik.system.DexFile;
Dario Freni2bef1762018-06-01 14:02:08 +010099
100import libcore.io.IoUtils;
101import libcore.io.Streams;
102
Calin Juravle21216c62018-05-04 17:35:29 -0700103import java.io.File;
104import java.io.FileOutputStream;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800105import java.io.IOException;
Calin Juravle21216c62018-05-04 17:35:29 -0700106import java.io.InputStream;
107import java.io.OutputStream;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700108import java.io.PrintWriter;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800109import java.net.URISyntaxException;
Calin Juravle21216c62018-05-04 17:35:29 -0700110import java.util.ArrayList;
111import java.util.Collections;
112import java.util.Comparator;
113import java.util.LinkedList;
114import java.util.List;
115import java.util.Map;
116import java.util.Objects;
117import java.util.WeakHashMap;
118import java.util.concurrent.CountDownLatch;
wangmingming155414292018-04-10 09:35:25 +0800119import java.util.concurrent.LinkedBlockingQueue;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800120import java.util.concurrent.TimeUnit;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700121
122class PackageManagerShellCommand extends ShellCommand {
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700123 /** Path for streaming APK content */
124 private static final String STDIN_PATH = "-";
Calin Juravle21216c62018-05-04 17:35:29 -0700125 /** Path where ART profiles snapshots are dumped for the shell user */
126 private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700127
Todd Kennedy60459ab2015-10-30 11:32:16 -0700128 final IPackageManager mInterface;
129 final private WeakHashMap<String, Resources> mResourceCache =
130 new WeakHashMap<String, Resources>();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800131 int mTargetUser;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700132 boolean mBrief;
133 boolean mComponents;
Ng Zhi An73971312018-09-11 21:39:14 -0700134 int mQueryFlags;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700135
136 PackageManagerShellCommand(PackageManagerService service) {
137 mInterface = service;
138 }
139
140 @Override
141 public int onCommand(String cmd) {
142 if (cmd == null) {
143 return handleDefaultCommands(cmd);
144 }
145
146 final PrintWriter pw = getOutPrintWriter();
147 try {
148 switch(cmd) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700149 case "path":
150 return runPath();
151 case "dump":
152 return runDump();
153 case "list":
154 return runList();
155 case "resolve-activity":
156 return runResolveActivity();
157 case "query-activities":
158 return runQueryIntentActivities();
159 case "query-services":
160 return runQueryIntentServices();
161 case "query-receivers":
162 return runQueryIntentReceivers();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800163 case "install":
164 return runInstall();
165 case "install-abandon":
166 case "install-destroy":
167 return runInstallAbandon();
168 case "install-commit":
169 return runInstallCommit();
170 case "install-create":
171 return runInstallCreate();
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800172 case "install-remove":
173 return runInstallRemove();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800174 case "install-write":
175 return runInstallWrite();
Todd Kennedybe0b8892017-02-15 14:13:52 -0800176 case "install-existing":
177 return runInstallExisting();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700178 case "set-install-location":
179 return runSetInstallLocation();
180 case "get-install-location":
181 return runGetInstallLocation();
Patrick Baumann0aff9b12018-11-08 14:05:08 +0000182 case "install-add-session":
183 return runInstallAddSession();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700184 case "move-package":
185 return runMovePackage();
186 case "move-primary-storage":
187 return runMovePrimaryStorage();
David Brazdil493411a2016-02-01 13:48:46 +0000188 case "compile":
189 return runCompile();
Calin Juravle1aa5f882017-01-25 01:05:50 -0800190 case "reconcile-secondary-dex-files":
191 return runreconcileSecondaryDexFiles();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700192 case "force-dex-opt":
193 return runForceDexOpt();
Calin Juravlecb5f41e2017-01-25 17:16:08 -0800194 case "bg-dexopt-job":
195 return runDexoptJob();
David Sehra8777082016-05-24 15:25:23 -0700196 case "dump-profiles":
197 return runDumpProfiles();
Calin Juravle21216c62018-05-04 17:35:29 -0700198 case "snapshot-profile":
199 return runSnapshotProfile();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800200 case "uninstall":
201 return runUninstall();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700202 case "clear":
203 return runClear();
204 case "enable":
205 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
206 case "disable":
207 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
208 case "disable-user":
209 return runSetEnabledSetting(
210 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
211 case "disable-until-used":
212 return runSetEnabledSetting(
213 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
214 case "default-state":
215 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
216 case "hide":
217 return runSetHiddenSetting(true);
218 case "unhide":
219 return runSetHiddenSetting(false);
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000220 case "suspend":
221 return runSuspend(true);
222 case "unsuspend":
223 return runSuspend(false);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700224 case "grant":
225 return runGrantRevokePermission(true);
226 case "revoke":
227 return runGrantRevokePermission(false);
228 case "reset-permissions":
229 return runResetPermissions();
230 case "set-permission-enforced":
231 return runSetPermissionEnforced();
Fyodor Kupolov51245c72016-12-01 11:34:10 -0800232 case "get-privapp-permissions":
233 return runGetPrivappPermissions();
Todd Kennedy74629e32017-08-15 14:48:07 -0700234 case "get-privapp-deny-permissions":
235 return runGetPrivappDenyPermissions();
Svet Ganov087dce22017-09-07 15:42:16 -0700236 case "get-oem-permissions":
237 return runGetOemPermissions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700238 case "set-app-link":
239 return runSetAppLink();
240 case "get-app-link":
241 return runGetAppLink();
242 case "trim-caches":
243 return runTrimCaches();
244 case "create-user":
245 return runCreateUser();
246 case "remove-user":
247 return runRemoveUser();
248 case "set-user-restriction":
249 return runSetUserRestriction();
250 case "get-max-users":
251 return runGetMaxUsers();
Alex Chauc12189b2018-01-16 15:01:15 +0000252 case "get-max-running-users":
253 return runGetMaxRunningUsers();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700254 case "set-home-activity":
255 return runSetHomeActivity();
256 case "set-installer":
257 return runSetInstaller();
Todd Kennedy0a3f0812017-05-08 14:43:15 -0700258 case "get-instantapp-resolver":
259 return runGetInstantAppResolver();
Tadashi G. Takaokabe5782f2017-02-14 16:41:49 +0900260 case "has-feature":
261 return runHasFeature();
Ben Gruver1ab3d6e2017-12-07 13:45:08 -0800262 case "set-harmful-app-warning":
263 return runSetHarmfulAppWarning();
Ben Gruver9ef60092018-01-10 11:32:30 -0800264 case "get-harmful-app-warning":
265 return runGetHarmfulAppWarning();
Abhijeet Kaur84b1f5d2019-01-21 17:18:03 +0000266 case "get-stagedsessions":
267 return getStagedSessions();
Patrick Baumanna980e142018-02-12 11:45:23 -0800268 case "uninstall-system-updates":
269 return uninstallSystemUpdates();
Narayan Kamathc5d752e2019-01-23 14:06:35 +0000270 case "rollback-app":
271 return runRollbackApp();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700272 default: {
273 String nextArg = getNextArg();
274 if (nextArg == null) {
275 if (cmd.equalsIgnoreCase("-l")) {
276 return runListPackages(false);
277 } else if (cmd.equalsIgnoreCase("-lf")) {
278 return runListPackages(true);
279 }
280 } else if (getNextArg() == null) {
281 if (cmd.equalsIgnoreCase("-p")) {
282 return displayPackageFilePath(nextArg, UserHandle.USER_SYSTEM);
283 }
284 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700285 return handleDefaultCommands(cmd);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700286 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700287 }
288 } catch (RemoteException e) {
289 pw.println("Remote exception: " + e);
290 }
291 return -1;
292 }
293
Abhijeet Kaur84b1f5d2019-01-21 17:18:03 +0000294 private int getStagedSessions() {
295 final PrintWriter pw = getOutPrintWriter();
296 try {
297 List<SessionInfo> stagedSessionsList =
298 mInterface.getPackageInstaller().getStagedSessions().getList();
299 for (SessionInfo session: stagedSessionsList) {
300 pw.println("appPackageName = " + session.getAppPackageName()
301 + "; sessionId = " + session.getSessionId()
302 + "; isStaged = " + session.isStaged()
Dario Freni60a96c12019-02-24 21:01:29 +0000303 + "; isStagedSessionReady = " + session.isStagedSessionReady()
304 + "; isStagedSessionApplied = " + session.isStagedSessionApplied()
305 + "; isStagedSessionFailed = " + session.isStagedSessionFailed() + ";");
Abhijeet Kaur84b1f5d2019-01-21 17:18:03 +0000306 }
307 } catch (RemoteException e) {
308 pw.println("Failure ["
309 + e.getClass().getName() + " - "
310 + e.getMessage() + "]");
311 return 0;
312 }
313 return 1;
314 }
315
Patrick Baumanna980e142018-02-12 11:45:23 -0800316 private int uninstallSystemUpdates() {
317 final PrintWriter pw = getOutPrintWriter();
318 List<String> failedUninstalls = new LinkedList<>();
319 try {
320 final ParceledListSlice<ApplicationInfo> packages =
321 mInterface.getInstalledApplications(
322 PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
323 final IPackageInstaller installer = mInterface.getPackageInstaller();
324 List<ApplicationInfo> list = packages.getList();
325 for (ApplicationInfo info : list) {
326 if (info.isUpdatedSystemApp()) {
327 pw.println("Uninstalling updates to " + info.packageName + "...");
328 final LocalIntentReceiver receiver = new LocalIntentReceiver();
329 installer.uninstall(new VersionedPackage(info.packageName,
330 info.versionCode), null /*callerPackageName*/, 0 /* flags */,
331 receiver.getIntentSender(), 0);
332
333 final Intent result = receiver.getResult();
334 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
335 PackageInstaller.STATUS_FAILURE);
336 if (status != PackageInstaller.STATUS_SUCCESS) {
337 failedUninstalls.add(info.packageName);
338 }
339 }
340 }
341 } catch (RemoteException e) {
342 pw.println("Failure ["
343 + e.getClass().getName() + " - "
344 + e.getMessage() + "]");
345 return 0;
346 }
347 if (!failedUninstalls.isEmpty()) {
348 pw.println("Failure [Couldn't uninstall packages: "
349 + TextUtils.join(", ", failedUninstalls)
350 + "]");
351 return 0;
352 }
353 pw.println("Success");
354 return 1;
355 }
356
Narayan Kamathc5d752e2019-01-23 14:06:35 +0000357 private int runRollbackApp() {
358 final PrintWriter pw = getOutPrintWriter();
359
360 final String packageName = getNextArgRequired();
361 if (packageName == null) {
362 pw.println("Error: package name not specified");
363 return 1;
364 }
365
366 final LocalIntentReceiver receiver = new LocalIntentReceiver();
367 try {
368 IRollbackManager rm = IRollbackManager.Stub.asInterface(
369 ServiceManager.getService(Context.ROLLBACK_SERVICE));
370
371 RollbackInfo rollback = null;
372 for (RollbackInfo r : (List<RollbackInfo>) rm.getAvailableRollbacks().getList()) {
373 for (PackageRollbackInfo info : r.getPackages()) {
374 if (packageName.equals(info.getPackageName())) {
375 rollback = r;
376 break;
377 }
378 }
379 }
380
381 if (rollback == null) {
382 pw.println("No available rollbacks for: " + packageName);
383 return 1;
384 }
385
386 rm.commitRollback(rollback.getRollbackId(),
387 ParceledListSlice.<VersionedPackage>emptyList(),
388 "com.android.shell", receiver.getIntentSender());
389 } catch (RemoteException re) {
390 // Cannot happen.
391 }
392
393 final Intent result = receiver.getResult();
394 final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
395 RollbackManager.STATUS_FAILURE);
396 if (status == RollbackManager.STATUS_SUCCESS) {
397 pw.println("Success");
398 return 0;
399 } else {
400 pw.println("Failure ["
401 + result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE) + "]");
402 return 1;
403 }
404 }
405
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700406 private void setParamsSize(InstallParams params, String inPath) {
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700407 if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700408 final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");
409 if (fd == null) {
410 getErrPrintWriter().println("Error: Can't open file: " + inPath);
411 throw new IllegalArgumentException("Error: Can't open file: " + inPath);
412 }
413 try {
414 ApkLite baseApk = PackageParser.parseApkLite(fd.getFileDescriptor(), inPath, 0);
415 PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
416 null, null);
417 params.sessionParams.setSize(PackageHelper.calculateInstalledSize(
Dianne Hackborn1704e3c2017-10-31 19:55:42 +0000418 pkgLite, params.sessionParams.abiOverride, fd.getFileDescriptor()));
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700419 } catch (PackageParserException | IOException e) {
420 getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath);
421 throw new IllegalArgumentException(
422 "Error: Failed to parse APK file: " + inPath, e);
423 } finally {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900424 try {
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700425 fd.close();
426 } catch (IOException e) {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900427 }
428 }
429 }
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700430 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700431 /**
432 * Displays the package file for a package.
433 * @param pckg
434 */
435 private int displayPackageFilePath(String pckg, int userId) throws RemoteException {
436 PackageInfo info = mInterface.getPackageInfo(pckg, 0, userId);
437 if (info != null && info.applicationInfo != null) {
438 final PrintWriter pw = getOutPrintWriter();
439 pw.print("package:");
440 pw.println(info.applicationInfo.sourceDir);
441 if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
442 for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
443 pw.print("package:");
444 pw.println(splitSourceDir);
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800445 }
446 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700447 return 0;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800448 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700449 return 1;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800450 }
451
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700452 private int runPath() throws RemoteException {
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000453 int userId = UserHandle.USER_SYSTEM;
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700454 String option = getNextOption();
455 if (option != null && option.equals("--user")) {
456 userId = UserHandle.parseUserArg(getNextArgRequired());
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000457 }
458
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700459 String pkg = getNextArgRequired();
460 if (pkg == null) {
461 getErrPrintWriter().println("Error: no package specified");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000462 return 1;
463 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700464 return displayPackageFilePath(pkg, userId);
David Sehra8777082016-05-24 15:25:23 -0700465 }
466
Todd Kennedy60459ab2015-10-30 11:32:16 -0700467 private int runList() throws RemoteException {
468 final PrintWriter pw = getOutPrintWriter();
469 final String type = getNextArg();
470 if (type == null) {
471 pw.println("Error: didn't specify type of data to list");
472 return -1;
473 }
474 switch(type) {
475 case "features":
476 return runListFeatures();
477 case "instrumentation":
478 return runListInstrumentation();
479 case "libraries":
480 return runListLibraries();
481 case "package":
482 case "packages":
483 return runListPackages(false /*showSourceDir*/);
484 case "permission-groups":
485 return runListPermissionGroups();
486 case "permissions":
487 return runListPermissions();
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700488 case "users":
489 ServiceManager.getService("user").shellCommand(
490 getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
491 new String[] { "list" }, getShellCallback(), adoptResultReceiver());
492 return 0;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700493 }
494 pw.println("Error: unknown list type '" + type + "'");
495 return -1;
496 }
497
498 private int runListFeatures() throws RemoteException {
499 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700500 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700501
502 // sort by name
503 Collections.sort(list, new Comparator<FeatureInfo>() {
504 public int compare(FeatureInfo o1, FeatureInfo o2) {
505 if (o1.name == o2.name) return 0;
506 if (o1.name == null) return -1;
507 if (o2.name == null) return 1;
508 return o1.name.compareTo(o2.name);
509 }
510 });
511
512 final int count = (list != null) ? list.size() : 0;
513 for (int p = 0; p < count; p++) {
514 FeatureInfo fi = list.get(p);
515 pw.print("feature:");
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700516 if (fi.name != null) {
517 pw.print(fi.name);
518 if (fi.version > 0) {
519 pw.print("=");
520 pw.print(fi.version);
521 }
522 pw.println();
523 } else {
524 pw.println("reqGlEsVersion=0x"
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700525 + Integer.toHexString(fi.reqGlEsVersion));
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700526 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700527 }
528 return 0;
529 }
530
531 private int runListInstrumentation() throws RemoteException {
532 final PrintWriter pw = getOutPrintWriter();
533 boolean showSourceDir = false;
534 String targetPackage = null;
535
536 try {
537 String opt;
538 while ((opt = getNextArg()) != null) {
539 switch (opt) {
540 case "-f":
541 showSourceDir = true;
542 break;
543 default:
544 if (opt.charAt(0) != '-') {
545 targetPackage = opt;
546 } else {
547 pw.println("Error: Unknown option: " + opt);
548 return -1;
549 }
550 break;
551 }
552 }
553 } catch (RuntimeException ex) {
554 pw.println("Error: " + ex.toString());
555 return -1;
556 }
557
558 final List<InstrumentationInfo> list =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700559 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700560
561 // sort by target package
562 Collections.sort(list, new Comparator<InstrumentationInfo>() {
563 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
564 return o1.targetPackage.compareTo(o2.targetPackage);
565 }
566 });
567
568 final int count = (list != null) ? list.size() : 0;
569 for (int p = 0; p < count; p++) {
570 final InstrumentationInfo ii = list.get(p);
571 pw.print("instrumentation:");
572 if (showSourceDir) {
573 pw.print(ii.sourceDir);
574 pw.print("=");
575 }
576 final ComponentName cn = new ComponentName(ii.packageName, ii.name);
577 pw.print(cn.flattenToShortString());
578 pw.print(" (target=");
579 pw.print(ii.targetPackage);
580 pw.println(")");
581 }
582 return 0;
583 }
584
585 private int runListLibraries() throws RemoteException {
586 final PrintWriter pw = getOutPrintWriter();
587 final List<String> list = new ArrayList<String>();
588 final String[] rawList = mInterface.getSystemSharedLibraryNames();
589 for (int i = 0; i < rawList.length; i++) {
590 list.add(rawList[i]);
591 }
592
593 // sort by name
594 Collections.sort(list, new Comparator<String>() {
595 public int compare(String o1, String o2) {
596 if (o1 == o2) return 0;
597 if (o1 == null) return -1;
598 if (o2 == null) return 1;
599 return o1.compareTo(o2);
600 }
601 });
602
603 final int count = (list != null) ? list.size() : 0;
604 for (int p = 0; p < count; p++) {
605 String lib = list.get(p);
606 pw.print("library:");
607 pw.println(lib);
608 }
609 return 0;
610 }
611
612 private int runListPackages(boolean showSourceDir) throws RemoteException {
613 final PrintWriter pw = getOutPrintWriter();
614 int getFlags = 0;
615 boolean listDisabled = false, listEnabled = false;
616 boolean listSystem = false, listThirdParty = false;
617 boolean listInstaller = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700618 boolean showUid = false;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800619 boolean showVersionCode = false;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900620 boolean listApexOnly = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700621 int uid = -1;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700622 int userId = UserHandle.USER_SYSTEM;
623 try {
624 String opt;
625 while ((opt = getNextOption()) != null) {
626 switch (opt) {
627 case "-d":
628 listDisabled = true;
629 break;
630 case "-e":
631 listEnabled = true;
632 break;
Andreas Gampe1f110452018-06-04 11:47:48 -0700633 case "-a":
634 getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
635 getFlags |= PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS;
636 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700637 case "-f":
638 showSourceDir = true;
639 break;
640 case "-i":
641 listInstaller = true;
642 break;
643 case "-l":
644 // old compat
645 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700646 case "-s":
647 listSystem = true;
648 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700649 case "-U":
650 showUid = true;
651 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700652 case "-u":
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700653 getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700654 break;
655 case "-3":
656 listThirdParty = true;
657 break;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800658 case "--show-versioncode":
659 showVersionCode = true;
660 break;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900661 case "--apex-only":
662 getFlags |= PackageManager.MATCH_APEX;
663 listApexOnly = true;
664 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700665 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800666 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy60459ab2015-10-30 11:32:16 -0700667 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700668 case "--uid":
669 showUid = true;
670 uid = Integer.parseInt(getNextArgRequired());
671 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700672 default:
673 pw.println("Error: Unknown option: " + opt);
674 return -1;
675 }
676 }
677 } catch (RuntimeException ex) {
678 pw.println("Error: " + ex.toString());
679 return -1;
680 }
681
682 final String filter = getNextArg();
683
684 @SuppressWarnings("unchecked")
685 final ParceledListSlice<PackageInfo> slice =
686 mInterface.getInstalledPackages(getFlags, userId);
687 final List<PackageInfo> packages = slice.getList();
688
689 final int count = packages.size();
690 for (int p = 0; p < count; p++) {
691 final PackageInfo info = packages.get(p);
692 if (filter != null && !info.packageName.contains(filter)) {
693 continue;
694 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900695 final boolean isApex = info.isApex;
696 if (uid != -1 && !isApex && info.applicationInfo.uid != uid) {
Felipe Lemeeece9862016-06-29 11:45:03 -0700697 continue;
698 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900699
700 final boolean isSystem = !isApex &&
Todd Kennedy60459ab2015-10-30 11:32:16 -0700701 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
Jiyong Park4f49abe2018-12-11 13:37:17 +0900702 final boolean isEnabled = !isApex && info.applicationInfo.enabled;
703 if ((!listDisabled || !isEnabled) &&
704 (!listEnabled || isEnabled) &&
Todd Kennedy60459ab2015-10-30 11:32:16 -0700705 (!listSystem || isSystem) &&
Jiyong Park4f49abe2018-12-11 13:37:17 +0900706 (!listThirdParty || !isSystem) &&
707 (!listApexOnly || isApex)) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700708 pw.print("package:");
Jiyong Park4f49abe2018-12-11 13:37:17 +0900709 if (showSourceDir && !isApex) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700710 pw.print(info.applicationInfo.sourceDir);
711 pw.print("=");
712 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800713 pw.print(info.packageName);
Jiyong Parkf50a2932018-12-17 13:54:40 +0900714 if (showVersionCode) {
Todd Kennedybadc69a2017-01-24 11:05:47 -0800715 pw.print(" versionCode:");
Jiyong Parkf50a2932018-12-17 13:54:40 +0900716 if (info.applicationInfo != null) {
Dario Freni788ecb12019-01-23 18:49:32 +0000717 pw.print(info.applicationInfo.longVersionCode);
Jiyong Parkf50a2932018-12-17 13:54:40 +0900718 } else {
Dario Freni788ecb12019-01-23 18:49:32 +0000719 pw.print(info.getLongVersionCode());
Jiyong Parkf50a2932018-12-17 13:54:40 +0900720 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800721 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900722 if (listInstaller && !isApex) {
Todd Kennedy60459ab2015-10-30 11:32:16 -0700723 pw.print(" installer=");
724 pw.print(mInterface.getInstallerPackageName(info.packageName));
725 }
Jiyong Park4f49abe2018-12-11 13:37:17 +0900726 if (showUid && !isApex) {
Felipe Lemeeece9862016-06-29 11:45:03 -0700727 pw.print(" uid:");
728 pw.print(info.applicationInfo.uid);
729 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700730 pw.println();
731 }
732 }
733 return 0;
734 }
735
736 private int runListPermissionGroups() throws RemoteException {
737 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700738 final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700739
740 final int count = pgs.size();
741 for (int p = 0; p < count ; p++) {
742 final PermissionGroupInfo pgi = pgs.get(p);
743 pw.print("permission group:");
744 pw.println(pgi.name);
745 }
746 return 0;
747 }
748
749 private int runListPermissions() throws RemoteException {
750 final PrintWriter pw = getOutPrintWriter();
751 boolean labels = false;
752 boolean groups = false;
753 boolean userOnly = false;
754 boolean summary = false;
755 boolean dangerousOnly = false;
756 String opt;
757 while ((opt = getNextOption()) != null) {
758 switch (opt) {
759 case "-d":
760 dangerousOnly = true;
761 break;
762 case "-f":
763 labels = true;
764 break;
765 case "-g":
766 groups = true;
767 break;
768 case "-s":
769 groups = true;
770 labels = true;
771 summary = true;
772 break;
773 case "-u":
774 userOnly = true;
775 break;
776 default:
777 pw.println("Error: Unknown option: " + opt);
778 return 1;
779 }
780 }
781
782 final ArrayList<String> groupList = new ArrayList<String>();
783 if (groups) {
784 final List<PermissionGroupInfo> infos =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700785 mInterface.getAllPermissionGroups(0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700786 final int count = infos.size();
787 for (int i = 0; i < count; i++) {
788 groupList.add(infos.get(i).name);
789 }
790 groupList.add(null);
791 } else {
792 final String grp = getNextArg();
793 groupList.add(grp);
794 }
795
796 if (dangerousOnly) {
797 pw.println("Dangerous Permissions:");
798 pw.println("");
799 doListPermissions(groupList, groups, labels, summary,
800 PermissionInfo.PROTECTION_DANGEROUS,
801 PermissionInfo.PROTECTION_DANGEROUS);
802 if (userOnly) {
803 pw.println("Normal Permissions:");
804 pw.println("");
805 doListPermissions(groupList, groups, labels, summary,
806 PermissionInfo.PROTECTION_NORMAL,
807 PermissionInfo.PROTECTION_NORMAL);
808 }
809 } else if (userOnly) {
810 pw.println("Dangerous and Normal Permissions:");
811 pw.println("");
812 doListPermissions(groupList, groups, labels, summary,
813 PermissionInfo.PROTECTION_NORMAL,
814 PermissionInfo.PROTECTION_DANGEROUS);
815 } else {
816 pw.println("All Permissions:");
817 pw.println("");
818 doListPermissions(groupList, groups, labels, summary,
819 -10000, 10000);
820 }
821 return 0;
822 }
823
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800824 private Intent parseIntentAndUser() throws URISyntaxException {
825 mTargetUser = UserHandle.USER_CURRENT;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700826 mBrief = false;
827 mComponents = false;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800828 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
829 @Override
830 public boolean handleOption(String opt, ShellCommand cmd) {
831 if ("--user".equals(opt)) {
832 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
833 return true;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700834 } else if ("--brief".equals(opt)) {
835 mBrief = true;
836 return true;
837 } else if ("--components".equals(opt)) {
838 mComponents = true;
839 return true;
Ng Zhi An73971312018-09-11 21:39:14 -0700840 } else if ("--query-flags".equals(opt)) {
841 mQueryFlags = Integer.decode(cmd.getNextArgRequired());
842 return true;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800843 }
844 return false;
845 }
846 });
847 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
848 Binder.getCallingUid(), mTargetUser, false, false, null, null);
849 return intent;
850 }
851
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700852 private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri,
853 boolean brief, boolean components) {
854 if (brief || components) {
855 final ComponentName comp;
856 if (ri.activityInfo != null) {
857 comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
858 } else if (ri.serviceInfo != null) {
859 comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
860 } else if (ri.providerInfo != null) {
861 comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name);
862 } else {
863 comp = null;
864 }
865 if (comp != null) {
866 if (!components) {
867 pr.println(prefix + "priority=" + ri.priority
868 + " preferredOrder=" + ri.preferredOrder
869 + " match=0x" + Integer.toHexString(ri.match)
870 + " specificIndex=" + ri.specificIndex
871 + " isDefault=" + ri.isDefault);
872 }
873 pr.println(prefix + comp.flattenToShortString());
874 return;
875 }
876 }
877 ri.dump(pr, prefix);
878 }
879
Dianne Hackborn99878e92015-12-02 16:27:41 -0800880 private int runResolveActivity() {
881 Intent intent;
882 try {
883 intent = parseIntentAndUser();
884 } catch (URISyntaxException e) {
885 throw new RuntimeException(e.getMessage(), e);
886 }
887 try {
Ng Zhi An73971312018-09-11 21:39:14 -0700888 ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), mQueryFlags,
889 mTargetUser);
Dianne Hackborn99878e92015-12-02 16:27:41 -0800890 PrintWriter pw = getOutPrintWriter();
891 if (ri == null) {
892 pw.println("No activity found");
893 } else {
894 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700895 printResolveInfo(pr, "", ri, mBrief, mComponents);
Dianne Hackborn99878e92015-12-02 16:27:41 -0800896 }
897 } catch (RemoteException e) {
898 throw new RuntimeException("Failed calling service", e);
899 }
900 return 0;
901 }
902
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800903 private int runQueryIntentActivities() {
904 Intent intent;
905 try {
906 intent = parseIntentAndUser();
907 } catch (URISyntaxException e) {
908 throw new RuntimeException(e.getMessage(), e);
909 }
910 try {
Ng Zhi An73971312018-09-11 21:39:14 -0700911 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(),
912 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800913 PrintWriter pw = getOutPrintWriter();
914 if (result == null || result.size() <= 0) {
915 pw.println("No activities found");
916 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700917 if (!mComponents) {
918 pw.print(result.size()); pw.println(" activities found:");
919 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
920 for (int i = 0; i < result.size(); i++) {
921 pw.print(" Activity #"); pw.print(i); pw.println(":");
922 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
923 }
924 } else {
925 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
926 for (int i = 0; i < result.size(); i++) {
927 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
928 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800929 }
930 }
931 } catch (RemoteException e) {
932 throw new RuntimeException("Failed calling service", e);
933 }
934 return 0;
935 }
936
937 private int runQueryIntentServices() {
938 Intent intent;
939 try {
940 intent = parseIntentAndUser();
941 } catch (URISyntaxException e) {
942 throw new RuntimeException(e.getMessage(), e);
943 }
944 try {
Ng Zhi An73971312018-09-11 21:39:14 -0700945 List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(),
946 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800947 PrintWriter pw = getOutPrintWriter();
948 if (result == null || result.size() <= 0) {
949 pw.println("No services found");
950 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700951 if (!mComponents) {
952 pw.print(result.size()); pw.println(" services found:");
953 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
954 for (int i = 0; i < result.size(); i++) {
955 pw.print(" Service #"); pw.print(i); pw.println(":");
956 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
957 }
958 } else {
959 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
960 for (int i = 0; i < result.size(); i++) {
961 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
962 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800963 }
964 }
965 } catch (RemoteException e) {
966 throw new RuntimeException("Failed calling service", e);
967 }
968 return 0;
969 }
970
971 private int runQueryIntentReceivers() {
972 Intent intent;
973 try {
974 intent = parseIntentAndUser();
975 } catch (URISyntaxException e) {
976 throw new RuntimeException(e.getMessage(), e);
977 }
978 try {
Ng Zhi An73971312018-09-11 21:39:14 -0700979 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(),
980 mQueryFlags, mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800981 PrintWriter pw = getOutPrintWriter();
982 if (result == null || result.size() <= 0) {
983 pw.println("No receivers found");
984 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700985 if (!mComponents) {
986 pw.print(result.size()); pw.println(" receivers found:");
987 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
988 for (int i = 0; i < result.size(); i++) {
989 pw.print(" Receiver #"); pw.print(i); pw.println(":");
990 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
991 }
992 } else {
993 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
994 for (int i = 0; i < result.size(); i++) {
995 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
996 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800997 }
998 }
999 } catch (RemoteException e) {
1000 throw new RuntimeException("Failed calling service", e);
1001 }
1002 return 0;
1003 }
1004
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001005 private int runInstall() throws RemoteException {
1006 final PrintWriter pw = getOutPrintWriter();
1007 final InstallParams params = makeInstallParams();
1008 final String inPath = getNextArg();
1009
1010 setParamsSize(params, inPath);
1011 final int sessionId = doCreateSession(params.sessionParams,
1012 params.installerPackageName, params.userId);
1013 boolean abandonSession = true;
1014 try {
1015 if (inPath == null && params.sessionParams.sizeBytes == -1) {
1016 pw.println("Error: must either specify a package size or an APK file");
1017 return 1;
1018 }
Dario Frenid8bf22e2018-08-31 14:18:04 +01001019 final boolean isApex =
1020 (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0;
1021 String splitName = "base." + (isApex ? "apex" : "apk");
1022 if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName,
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001023 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
1024 return 1;
1025 }
1026 if (doCommitSession(sessionId, false /*logSuccess*/)
1027 != PackageInstaller.STATUS_SUCCESS) {
1028 return 1;
1029 }
1030 abandonSession = false;
1031 pw.println("Success");
1032 return 0;
1033 } finally {
1034 if (abandonSession) {
1035 try {
1036 doAbandonSession(sessionId, false /*logSuccess*/);
1037 } catch (Exception ignore) {
1038 }
1039 }
1040 }
1041 }
1042
1043 private int runInstallAbandon() throws RemoteException {
1044 final int sessionId = Integer.parseInt(getNextArg());
1045 return doAbandonSession(sessionId, true /*logSuccess*/);
1046 }
1047
1048 private int runInstallCommit() throws RemoteException {
1049 final int sessionId = Integer.parseInt(getNextArg());
1050 return doCommitSession(sessionId, true /*logSuccess*/);
1051 }
1052
1053 private int runInstallCreate() throws RemoteException {
1054 final PrintWriter pw = getOutPrintWriter();
1055 final InstallParams installParams = makeInstallParams();
1056 final int sessionId = doCreateSession(installParams.sessionParams,
1057 installParams.installerPackageName, installParams.userId);
1058
1059 // NOTE: adb depends on parsing this string
1060 pw.println("Success: created install session [" + sessionId + "]");
1061 return 0;
1062 }
1063
1064 private int runInstallWrite() throws RemoteException {
1065 long sizeBytes = -1;
1066
1067 String opt;
1068 while ((opt = getNextOption()) != null) {
1069 if (opt.equals("-S")) {
1070 sizeBytes = Long.parseLong(getNextArg());
1071 } else {
1072 throw new IllegalArgumentException("Unknown option: " + opt);
1073 }
1074 }
1075
1076 final int sessionId = Integer.parseInt(getNextArg());
1077 final String splitName = getNextArg();
1078 final String path = getNextArg();
1079 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
1080 }
1081
Patrick Baumann0aff9b12018-11-08 14:05:08 +00001082 private int runInstallAddSession() throws RemoteException {
1083 final PrintWriter pw = getOutPrintWriter();
1084 final int parentSessionId = Integer.parseInt(getNextArg());
1085
1086 List<Integer> otherSessionIds = new ArrayList<>();
1087 String opt;
1088 while ((opt = getNextArg()) != null) {
1089 otherSessionIds.add(Integer.parseInt(opt));
1090 }
1091 if (otherSessionIds.size() == 0) {
1092 pw.println("Error: At least two sessions are required.");
1093 return 1;
1094 }
1095 return doInstallAddSession(parentSessionId, ArrayUtils.convertToIntArray(otherSessionIds),
1096 true /*logSuccess*/);
1097 }
1098
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001099 private int runInstallRemove() throws RemoteException {
1100 final PrintWriter pw = getOutPrintWriter();
1101
1102 final int sessionId = Integer.parseInt(getNextArg());
1103
1104 final String splitName = getNextArg();
1105 if (splitName == null) {
1106 pw.println("Error: split name not specified");
1107 return 1;
1108 }
1109 return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
1110 }
1111
1112 private int runInstallExisting() throws RemoteException {
1113 final PrintWriter pw = getOutPrintWriter();
1114 int userId = UserHandle.USER_SYSTEM;
1115 int installFlags = 0;
1116 String opt;
Chandan Nathe8e463b2019-01-28 15:23:38 +00001117 boolean waitTillComplete = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001118 while ((opt = getNextOption()) != null) {
1119 switch (opt) {
1120 case "--user":
1121 userId = UserHandle.parseUserArg(getNextArgRequired());
1122 break;
1123 case "--ephemeral":
1124 case "--instant":
1125 installFlags |= PackageManager.INSTALL_INSTANT_APP;
1126 installFlags &= ~PackageManager.INSTALL_FULL_APP;
1127 break;
1128 case "--full":
1129 installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1130 installFlags |= PackageManager.INSTALL_FULL_APP;
1131 break;
Chandan Nathe8e463b2019-01-28 15:23:38 +00001132 case "--wait":
1133 waitTillComplete = true;
1134 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001135 default:
1136 pw.println("Error: Unknown option: " + opt);
1137 return 1;
1138 }
1139 }
1140
1141 final String packageName = getNextArg();
1142 if (packageName == null) {
1143 pw.println("Error: package name not specified");
1144 return 1;
1145 }
1146
Chandan Nathe8e463b2019-01-28 15:23:38 +00001147 int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001148 try {
Chandan Nathe8e463b2019-01-28 15:23:38 +00001149 if (waitTillComplete) {
1150 final LocalIntentReceiver receiver = new LocalIntentReceiver();
1151 final IPackageInstaller installer = mInterface.getPackageInstaller();
1152 pw.println("Installing package " + packageName + " for user: " + userId);
1153 installer.installExistingPackage(packageName, installFlags, installReason,
1154 receiver.getIntentSender(), userId);
1155 final Intent result = receiver.getResult();
1156 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1157 PackageInstaller.STATUS_FAILURE);
1158 pw.println("Received intent for package install");
1159 return status == PackageInstaller.STATUS_SUCCESS ? 0 : 1;
1160 }
1161
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001162 final int res = mInterface.installExistingPackageAsUser(packageName, userId,
Chandan Nathe8e463b2019-01-28 15:23:38 +00001163 installFlags, installReason);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001164 if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
1165 throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1166 }
1167 pw.println("Package " + packageName + " installed for user: " + userId);
1168 return 0;
1169 } catch (RemoteException | NameNotFoundException e) {
1170 pw.println(e.toString());
1171 return 1;
1172 }
1173 }
1174
1175 private int runSetInstallLocation() throws RemoteException {
1176 int loc;
1177
1178 String arg = getNextArg();
1179 if (arg == null) {
1180 getErrPrintWriter().println("Error: no install location specified.");
1181 return 1;
1182 }
1183 try {
1184 loc = Integer.parseInt(arg);
1185 } catch (NumberFormatException e) {
1186 getErrPrintWriter().println("Error: install location has to be a number.");
1187 return 1;
1188 }
1189 if (!mInterface.setInstallLocation(loc)) {
1190 getErrPrintWriter().println("Error: install location has to be a number.");
1191 return 1;
1192 }
1193 return 0;
1194 }
1195
1196 private int runGetInstallLocation() throws RemoteException {
1197 int loc = mInterface.getInstallLocation();
1198 String locStr = "invalid";
1199 if (loc == PackageHelper.APP_INSTALL_AUTO) {
1200 locStr = "auto";
1201 } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
1202 locStr = "internal";
1203 } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
1204 locStr = "external";
1205 }
1206 getOutPrintWriter().println(loc + "[" + locStr + "]");
1207 return 0;
1208 }
1209
1210 public int runMovePackage() throws RemoteException {
1211 final String packageName = getNextArg();
1212 if (packageName == null) {
1213 getErrPrintWriter().println("Error: package name not specified");
1214 return 1;
1215 }
1216 String volumeUuid = getNextArg();
1217 if ("internal".equals(volumeUuid)) {
1218 volumeUuid = null;
1219 }
1220
1221 final int moveId = mInterface.movePackage(packageName, volumeUuid);
1222
1223 int status = mInterface.getMoveStatus(moveId);
1224 while (!PackageManager.isMoveStatusFinished(status)) {
1225 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1226 status = mInterface.getMoveStatus(moveId);
1227 }
1228
1229 if (status == PackageManager.MOVE_SUCCEEDED) {
1230 getOutPrintWriter().println("Success");
1231 return 0;
1232 } else {
1233 getErrPrintWriter().println("Failure [" + status + "]");
1234 return 1;
1235 }
1236 }
1237
1238 public int runMovePrimaryStorage() throws RemoteException {
1239 String volumeUuid = getNextArg();
1240 if ("internal".equals(volumeUuid)) {
1241 volumeUuid = null;
1242 }
1243
1244 final int moveId = mInterface.movePrimaryStorage(volumeUuid);
1245
1246 int status = mInterface.getMoveStatus(moveId);
1247 while (!PackageManager.isMoveStatusFinished(status)) {
1248 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1249 status = mInterface.getMoveStatus(moveId);
1250 }
1251
1252 if (status == PackageManager.MOVE_SUCCEEDED) {
1253 getOutPrintWriter().println("Success");
1254 return 0;
1255 } else {
1256 getErrPrintWriter().println("Failure [" + status + "]");
1257 return 1;
1258 }
1259 }
1260
1261 private int runCompile() throws RemoteException {
1262 final PrintWriter pw = getOutPrintWriter();
1263 boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
1264 boolean forceCompilation = false;
1265 boolean allPackages = false;
1266 boolean clearProfileData = false;
1267 String compilerFilter = null;
1268 String compilationReason = null;
1269 String checkProfilesRaw = null;
1270 boolean secondaryDex = false;
1271 String split = null;
Eric Holka1485f62019-01-07 13:58:25 -08001272 boolean compileLayouts = false;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001273
1274 String opt;
1275 while ((opt = getNextOption()) != null) {
1276 switch (opt) {
1277 case "-a":
1278 allPackages = true;
1279 break;
1280 case "-c":
1281 clearProfileData = true;
1282 break;
1283 case "-f":
1284 forceCompilation = true;
1285 break;
1286 case "-m":
1287 compilerFilter = getNextArgRequired();
1288 break;
1289 case "-r":
1290 compilationReason = getNextArgRequired();
1291 break;
Eric Holka1485f62019-01-07 13:58:25 -08001292 case "--compile-layouts":
1293 compileLayouts = true;
1294 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001295 case "--check-prof":
1296 checkProfilesRaw = getNextArgRequired();
1297 break;
1298 case "--reset":
1299 forceCompilation = true;
1300 clearProfileData = true;
1301 compilationReason = "install";
1302 break;
1303 case "--secondary-dex":
1304 secondaryDex = true;
1305 break;
1306 case "--split":
1307 split = getNextArgRequired();
1308 break;
1309 default:
1310 pw.println("Error: Unknown option: " + opt);
1311 return 1;
1312 }
1313 }
1314
1315 if (checkProfilesRaw != null) {
1316 if ("true".equals(checkProfilesRaw)) {
1317 checkProfiles = true;
1318 } else if ("false".equals(checkProfilesRaw)) {
1319 checkProfiles = false;
1320 } else {
1321 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
1322 return 1;
1323 }
1324 }
1325
Eric Holka1485f62019-01-07 13:58:25 -08001326 final boolean compilerFilterGiven = compilerFilter != null;
1327 final boolean compilationReasonGiven = compilationReason != null;
1328 // Make sure exactly one of -m, -r, or --compile-layouts is given.
1329 if ((!compilerFilterGiven && !compilationReasonGiven && !compileLayouts)
1330 || (!compilerFilterGiven && compilationReasonGiven && compileLayouts)
1331 || (compilerFilterGiven && !compilationReasonGiven && compileLayouts)
1332 || (compilerFilterGiven && compilationReasonGiven && !compileLayouts)
1333 || (compilerFilterGiven && compilationReasonGiven && compileLayouts)) {
1334 pw.println("Must specify exactly one of compilation filter (\"-m\"), compilation " +
1335 "reason (\"-r\"), or compile layouts (\"--compile-layouts\")");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001336 return 1;
1337 }
1338
1339 if (allPackages && split != null) {
1340 pw.println("-a cannot be specified together with --split");
1341 return 1;
1342 }
1343
1344 if (secondaryDex && split != null) {
1345 pw.println("--secondary-dex cannot be specified together with --split");
1346 return 1;
1347 }
1348
Eric Holka1485f62019-01-07 13:58:25 -08001349 String targetCompilerFilter = null;
1350 if (compilerFilterGiven) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001351 if (!DexFile.isValidCompilerFilter(compilerFilter)) {
1352 pw.println("Error: \"" + compilerFilter +
1353 "\" is not a valid compilation filter.");
1354 return 1;
1355 }
1356 targetCompilerFilter = compilerFilter;
Eric Holka1485f62019-01-07 13:58:25 -08001357 }
1358 if (compilationReasonGiven) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001359 int reason = -1;
1360 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
1361 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
1362 compilationReason)) {
1363 reason = i;
1364 break;
1365 }
1366 }
1367 if (reason == -1) {
1368 pw.println("Error: Unknown compilation reason: " + compilationReason);
1369 return 1;
1370 }
1371 targetCompilerFilter =
1372 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
1373 }
1374
1375
1376 List<String> packageNames = null;
1377 if (allPackages) {
1378 packageNames = mInterface.getAllPackages();
1379 } else {
1380 String packageName = getNextArg();
1381 if (packageName == null) {
1382 pw.println("Error: package name not specified");
1383 return 1;
1384 }
1385 packageNames = Collections.singletonList(packageName);
1386 }
1387
1388 List<String> failedPackages = new ArrayList<>();
Andreas Gampecbd08d42017-11-20 17:03:17 -08001389 int index = 0;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001390 for (String packageName : packageNames) {
1391 if (clearProfileData) {
1392 mInterface.clearApplicationProfileData(packageName);
1393 }
1394
Andreas Gampecbd08d42017-11-20 17:03:17 -08001395 if (allPackages) {
1396 pw.println(++index + "/" + packageNames.size() + ": " + packageName);
1397 pw.flush();
1398 }
1399
Eric Holka1485f62019-01-07 13:58:25 -08001400 boolean result = true;
1401 if (compileLayouts) {
1402 PackageManagerInternal internal = LocalServices.getService(
1403 PackageManagerInternal.class);
1404 result = internal.compileLayouts(packageName);
1405 } else {
1406 result = secondaryDex
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001407 ? mInterface.performDexOptSecondary(packageName,
1408 targetCompilerFilter, forceCompilation)
1409 : mInterface.performDexOptMode(packageName,
1410 checkProfiles, targetCompilerFilter, forceCompilation,
1411 true /* bootComplete */, split);
Eric Holka1485f62019-01-07 13:58:25 -08001412 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001413 if (!result) {
1414 failedPackages.add(packageName);
1415 }
1416 }
1417
1418 if (failedPackages.isEmpty()) {
1419 pw.println("Success");
1420 return 0;
1421 } else if (failedPackages.size() == 1) {
1422 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
1423 return 1;
1424 } else {
1425 pw.print("Failure: the following packages could not be compiled: ");
1426 boolean is_first = true;
1427 for (String packageName : failedPackages) {
1428 if (is_first) {
1429 is_first = false;
1430 } else {
1431 pw.print(", ");
1432 }
1433 pw.print(packageName);
1434 }
1435 pw.println();
1436 return 1;
1437 }
1438 }
1439
1440 private int runreconcileSecondaryDexFiles() throws RemoteException {
1441 String packageName = getNextArg();
1442 mInterface.reconcileSecondaryDexFiles(packageName);
1443 return 0;
1444 }
1445
1446 public int runForceDexOpt() throws RemoteException {
1447 mInterface.forceDexOpt(getNextArgRequired());
1448 return 0;
1449 }
1450
1451 private int runDexoptJob() throws RemoteException {
Arthur Eubanks09dd1ec2017-09-15 09:28:51 -07001452 String arg;
1453 List<String> packageNames = new ArrayList<>();
1454 while ((arg = getNextArg()) != null) {
1455 packageNames.add(arg);
1456 }
1457 boolean result = mInterface.runBackgroundDexoptJob(packageNames.isEmpty() ? null :
1458 packageNames);
Andreas Gampefa8b57d2018-08-31 15:47:01 -07001459 getOutPrintWriter().println(result ? "Success" : "Failure");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001460 return result ? 0 : -1;
1461 }
1462
1463 private int runDumpProfiles() throws RemoteException {
1464 String packageName = getNextArg();
1465 mInterface.dumpProfiles(packageName);
1466 return 0;
1467 }
1468
Calin Juravle21216c62018-05-04 17:35:29 -07001469 private int runSnapshotProfile() throws RemoteException {
1470 PrintWriter pw = getOutPrintWriter();
1471
1472 // Parse the arguments
1473 final String packageName = getNextArg();
1474 final boolean isBootImage = "android".equals(packageName);
1475
1476 String codePath = null;
1477 String opt;
1478 while ((opt = getNextArg()) != null) {
1479 switch (opt) {
1480 case "--code-path":
1481 if (isBootImage) {
1482 pw.write("--code-path cannot be used for the boot image.");
1483 return -1;
1484 }
1485 codePath = getNextArg();
1486 break;
1487 default:
1488 pw.write("Unknown arg: " + opt);
1489 return -1;
1490 }
1491 }
1492
1493 // If no code path was explicitly requested, select the base code path.
1494 String baseCodePath = null;
1495 if (!isBootImage) {
1496 PackageInfo packageInfo = mInterface.getPackageInfo(packageName, /* flags */ 0,
1497 /* userId */0);
1498 if (packageInfo == null) {
1499 pw.write("Package not found " + packageName);
1500 return -1;
1501 }
1502 baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
1503 if (codePath == null) {
1504 codePath = baseCodePath;
1505 }
1506 }
1507
1508 // Create the profile snapshot.
1509 final SnapshotRuntimeProfileCallback callback = new SnapshotRuntimeProfileCallback();
1510 // The calling package is needed to debug permission access.
1511 final String callingPackage = (Binder.getCallingUid() == Process.ROOT_UID)
1512 ? "root" : "com.android.shell";
1513 final int profileType = isBootImage
1514 ? ArtManager.PROFILE_BOOT_IMAGE : ArtManager.PROFILE_APPS;
1515 if (!mInterface.getArtManager().isRuntimeProfilingEnabled(profileType, callingPackage)) {
1516 pw.println("Error: Runtime profiling is not enabled");
1517 return -1;
1518 }
1519 mInterface.getArtManager().snapshotRuntimeProfile(profileType, packageName,
1520 codePath, callback, callingPackage);
1521 if (!callback.waitTillDone()) {
1522 pw.println("Error: callback not called");
1523 return callback.mErrCode;
1524 }
1525
1526 // Copy the snapshot profile to the output profile file.
1527 try (InputStream inStream = new AutoCloseInputStream(callback.mProfileReadFd)) {
1528 final String outputFileSuffix = isBootImage || Objects.equals(baseCodePath, codePath)
1529 ? "" : ("-" + new File(codePath).getName());
1530 final String outputProfilePath =
1531 ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + packageName + outputFileSuffix + ".prof";
1532 try (OutputStream outStream = new FileOutputStream(outputProfilePath)) {
1533 Streams.copy(inStream, outStream);
1534 }
Calin Juravlebdd94d92018-05-17 01:23:15 -07001535 // Give read permissions to the other group.
1536 Os.chmod(outputProfilePath, /*mode*/ 0644 );
1537 } catch (IOException | ErrnoException e) {
Calin Juravle21216c62018-05-04 17:35:29 -07001538 pw.println("Error when reading the profile fd: " + e.getMessage());
1539 e.printStackTrace(pw);
1540 return -1;
1541 }
1542 return 0;
1543 }
1544
1545 private static class SnapshotRuntimeProfileCallback
1546 extends ISnapshotRuntimeProfileCallback.Stub {
1547 private boolean mSuccess = false;
1548 private int mErrCode = -1;
1549 private ParcelFileDescriptor mProfileReadFd = null;
1550 private CountDownLatch mDoneSignal = new CountDownLatch(1);
1551
1552 @Override
1553 public void onSuccess(ParcelFileDescriptor profileReadFd) {
1554 mSuccess = true;
1555 try {
1556 // We need to dup the descriptor. We are in the same process as system server
1557 // and we will be receiving the same object (which will be closed on the
1558 // server side).
1559 mProfileReadFd = profileReadFd.dup();
1560 } catch (IOException e) {
1561 e.printStackTrace();
1562 }
1563 mDoneSignal.countDown();
1564 }
1565
1566 @Override
1567 public void onError(int errCode) {
1568 mSuccess = false;
1569 mErrCode = errCode;
1570 mDoneSignal.countDown();
1571 }
1572
1573 boolean waitTillDone() {
1574 boolean done = false;
1575 try {
1576 // The time-out is an arbitrary large value. Since this is a local call the result
1577 // will come very fast.
1578 done = mDoneSignal.await(10000000, TimeUnit.MILLISECONDS);
1579 } catch (InterruptedException ignored) {
1580 }
1581 return done && mSuccess;
1582 }
1583 }
1584
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001585 private int runUninstall() throws RemoteException {
1586 final PrintWriter pw = getOutPrintWriter();
1587 int flags = 0;
1588 int userId = UserHandle.USER_ALL;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001589 long versionCode = PackageManager.VERSION_CODE_HIGHEST;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001590
1591 String opt;
1592 while ((opt = getNextOption()) != null) {
1593 switch (opt) {
1594 case "-k":
1595 flags |= PackageManager.DELETE_KEEP_DATA;
1596 break;
1597 case "--user":
1598 userId = UserHandle.parseUserArg(getNextArgRequired());
1599 break;
1600 case "--versionCode":
Dianne Hackborn3accca02013-09-20 09:32:11 -07001601 versionCode = Long.parseLong(getNextArgRequired());
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001602 break;
1603 default:
1604 pw.println("Error: Unknown option: " + opt);
1605 return 1;
1606 }
1607 }
1608
1609 final String packageName = getNextArg();
1610 if (packageName == null) {
1611 pw.println("Error: package name not specified");
1612 return 1;
1613 }
1614
1615 // if a split is specified, just remove it and not the whole package
1616 final String splitName = getNextArg();
1617 if (splitName != null) {
1618 return runRemoveSplit(packageName, splitName);
1619 }
1620
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08001621 userId = translateUserId(userId, true /*allowAll*/, "runUninstall");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001622 final LocalIntentReceiver receiver = new LocalIntentReceiver();
Nikita Ioffef012a222019-03-05 22:37:55 +00001623 PackageManagerInternal internal = LocalServices.getService(PackageManagerInternal.class);
1624
1625 if (internal.isApexPackage(packageName)) {
1626 internal.uninstallApex(packageName, versionCode, userId, receiver.getIntentSender());
1627 } else {
1628 if (userId == UserHandle.USER_ALL) {
1629 userId = UserHandle.USER_SYSTEM;
1630 flags |= PackageManager.DELETE_ALL_USERS;
1631 } else {
1632 final PackageInfo info = mInterface.getPackageInfo(packageName,
1633 PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId);
1634 if (info == null) {
1635 pw.println("Failure [not installed for " + userId + "]");
1636 return 1;
1637 }
1638 final boolean isSystem =
1639 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
1640 // If we are being asked to delete a system app for just one
1641 // user set flag so it disables rather than reverting to system
1642 // version of the app.
1643 if (isSystem) {
1644 flags |= PackageManager.DELETE_SYSTEM_APP;
1645 }
1646 }
1647
1648 mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
1649 versionCode), null /*callerPackageName*/, flags,
1650 receiver.getIntentSender(), userId);
1651 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001652
1653 final Intent result = receiver.getResult();
1654 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1655 PackageInstaller.STATUS_FAILURE);
1656 if (status == PackageInstaller.STATUS_SUCCESS) {
1657 pw.println("Success");
1658 return 0;
1659 } else {
1660 pw.println("Failure ["
1661 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
1662 return 1;
1663 }
1664 }
1665
1666 private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
1667 final PrintWriter pw = getOutPrintWriter();
1668 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
1669 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1670 sessionParams.appPackageName = packageName;
1671 final int sessionId =
1672 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
1673 boolean abandonSession = true;
1674 try {
1675 if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
1676 != PackageInstaller.STATUS_SUCCESS) {
1677 return 1;
1678 }
1679 if (doCommitSession(sessionId, false /*logSuccess*/)
1680 != PackageInstaller.STATUS_SUCCESS) {
1681 return 1;
1682 }
1683 abandonSession = false;
1684 pw.println("Success");
1685 return 0;
1686 } finally {
1687 if (abandonSession) {
1688 try {
1689 doAbandonSession(sessionId, false /*logSuccess*/);
1690 } catch (Exception ignore) {
1691 }
1692 }
1693 }
1694 }
1695
1696 static class ClearDataObserver extends IPackageDataObserver.Stub {
1697 boolean finished;
1698 boolean result;
1699
1700 @Override
1701 public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1702 synchronized (this) {
1703 finished = true;
1704 result = succeeded;
1705 notifyAll();
1706 }
1707 }
1708 }
1709
1710 private int runClear() throws RemoteException {
1711 int userId = UserHandle.USER_SYSTEM;
1712 String option = getNextOption();
1713 if (option != null && option.equals("--user")) {
1714 userId = UserHandle.parseUserArg(getNextArgRequired());
1715 }
1716
1717 String pkg = getNextArg();
1718 if (pkg == null) {
1719 getErrPrintWriter().println("Error: no package specified");
1720 return 1;
1721 }
1722
1723 ClearDataObserver obs = new ClearDataObserver();
Christopher Tate1d99c392017-12-07 16:54:04 -08001724 ActivityManager.getService().clearApplicationUserData(pkg, false, obs, userId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001725 synchronized (obs) {
1726 while (!obs.finished) {
1727 try {
1728 obs.wait();
1729 } catch (InterruptedException e) {
1730 }
1731 }
1732 }
1733
1734 if (obs.result) {
1735 getOutPrintWriter().println("Success");
1736 return 0;
1737 } else {
1738 getErrPrintWriter().println("Failed");
1739 return 1;
1740 }
1741 }
1742
1743 private static String enabledSettingToString(int state) {
1744 switch (state) {
1745 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
1746 return "default";
1747 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
1748 return "enabled";
1749 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
1750 return "disabled";
1751 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
1752 return "disabled-user";
1753 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
1754 return "disabled-until-used";
1755 }
1756 return "unknown";
1757 }
1758
1759 private int runSetEnabledSetting(int state) throws RemoteException {
1760 int userId = UserHandle.USER_SYSTEM;
1761 String option = getNextOption();
1762 if (option != null && option.equals("--user")) {
1763 userId = UserHandle.parseUserArg(getNextArgRequired());
1764 }
1765
1766 String pkg = getNextArg();
1767 if (pkg == null) {
1768 getErrPrintWriter().println("Error: no package or component specified");
1769 return 1;
1770 }
1771 ComponentName cn = ComponentName.unflattenFromString(pkg);
1772 if (cn == null) {
1773 mInterface.setApplicationEnabledSetting(pkg, state, 0, userId,
1774 "shell:" + android.os.Process.myUid());
1775 getOutPrintWriter().println("Package " + pkg + " new state: "
1776 + enabledSettingToString(
1777 mInterface.getApplicationEnabledSetting(pkg, userId)));
1778 return 0;
1779 } else {
1780 mInterface.setComponentEnabledSetting(cn, state, 0, userId);
1781 getOutPrintWriter().println("Component " + cn.toShortString() + " new state: "
1782 + enabledSettingToString(
1783 mInterface.getComponentEnabledSetting(cn, userId)));
1784 return 0;
1785 }
1786 }
1787
1788 private int runSetHiddenSetting(boolean state) throws RemoteException {
1789 int userId = UserHandle.USER_SYSTEM;
1790 String option = getNextOption();
1791 if (option != null && option.equals("--user")) {
1792 userId = UserHandle.parseUserArg(getNextArgRequired());
1793 }
1794
1795 String pkg = getNextArg();
1796 if (pkg == null) {
1797 getErrPrintWriter().println("Error: no package or component specified");
1798 return 1;
1799 }
1800 mInterface.setApplicationHiddenSettingAsUser(pkg, state, userId);
1801 getOutPrintWriter().println("Package " + pkg + " new hidden state: "
1802 + mInterface.getApplicationHiddenSettingAsUser(pkg, userId));
1803 return 0;
1804 }
1805
1806 private int runSuspend(boolean suspendedState) {
1807 final PrintWriter pw = getOutPrintWriter();
1808 int userId = UserHandle.USER_SYSTEM;
Suprabh Shukla3c3af142018-03-30 00:28:37 -07001809 String dialogMessage = null;
Suprabh Shukla021b57a2018-03-08 18:21:50 -08001810 final PersistableBundle appExtras = new PersistableBundle();
1811 final PersistableBundle launcherExtras = new PersistableBundle();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001812 String opt;
1813 while ((opt = getNextOption()) != null) {
1814 switch (opt) {
1815 case "--user":
1816 userId = UserHandle.parseUserArg(getNextArgRequired());
1817 break;
Suprabh Shukla3c3af142018-03-30 00:28:37 -07001818 case "--dialogMessage":
1819 dialogMessage = getNextArgRequired();
1820 break;
Suprabh Shukla021b57a2018-03-08 18:21:50 -08001821 case "--ael":
1822 case "--aes":
1823 case "--aed":
1824 case "--lel":
1825 case "--les":
1826 case "--led":
1827 final String key = getNextArgRequired();
1828 final String val = getNextArgRequired();
1829 if (!suspendedState) {
1830 break;
1831 }
1832 final PersistableBundle bundleToInsert =
1833 opt.startsWith("--a") ? appExtras : launcherExtras;
1834 switch (opt.charAt(4)) {
1835 case 'l':
1836 bundleToInsert.putLong(key, Long.valueOf(val));
1837 break;
1838 case 'd':
1839 bundleToInsert.putDouble(key, Double.valueOf(val));
1840 break;
1841 case 's':
1842 bundleToInsert.putString(key, val);
1843 break;
1844 }
1845 break;
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001846 default:
1847 pw.println("Error: Unknown option: " + opt);
1848 return 1;
1849 }
1850 }
1851
Suprabh Shukla021b57a2018-03-08 18:21:50 -08001852 final String packageName = getNextArg();
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001853 if (packageName == null) {
1854 pw.println("Error: package name not specified");
1855 return 1;
1856 }
Suprabh Shukla021b57a2018-03-08 18:21:50 -08001857 final String callingPackage =
1858 (Binder.getCallingUid() == Process.ROOT_UID) ? "root" : "com.android.shell";
Suprabh Shukla389cb6f2018-10-01 18:20:39 -07001859
1860 final SuspendDialogInfo info;
1861 if (!TextUtils.isEmpty(dialogMessage)) {
1862 info = new SuspendDialogInfo.Builder()
1863 .setMessage(dialogMessage)
1864 .build();
1865 } else {
1866 info = null;
1867 }
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001868 try {
1869 mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
Suprabh Shukla389cb6f2018-10-01 18:20:39 -07001870 appExtras, launcherExtras, info, callingPackage, userId);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001871 pw.println("Package " + packageName + " new suspended state: "
1872 + mInterface.isPackageSuspendedForUser(packageName, userId));
1873 return 0;
1874 } catch (RemoteException | IllegalArgumentException e) {
1875 pw.println(e.toString());
1876 return 1;
1877 }
1878 }
1879
1880 private int runGrantRevokePermission(boolean grant) throws RemoteException {
1881 int userId = UserHandle.USER_SYSTEM;
1882
1883 String opt = null;
1884 while ((opt = getNextOption()) != null) {
1885 if (opt.equals("--user")) {
1886 userId = UserHandle.parseUserArg(getNextArgRequired());
1887 }
1888 }
1889
1890 String pkg = getNextArg();
1891 if (pkg == null) {
1892 getErrPrintWriter().println("Error: no package specified");
1893 return 1;
1894 }
1895 String perm = getNextArg();
1896 if (perm == null) {
1897 getErrPrintWriter().println("Error: no permission specified");
1898 return 1;
1899 }
1900
1901 if (grant) {
1902 mInterface.grantRuntimePermission(pkg, perm, userId);
1903 } else {
1904 mInterface.revokeRuntimePermission(pkg, perm, userId);
1905 }
1906 return 0;
1907 }
1908
1909 private int runResetPermissions() throws RemoteException {
1910 mInterface.resetRuntimePermissions();
1911 return 0;
1912 }
1913
1914 private int runSetPermissionEnforced() throws RemoteException {
1915 final String permission = getNextArg();
1916 if (permission == null) {
1917 getErrPrintWriter().println("Error: no permission specified");
1918 return 1;
1919 }
1920 final String enforcedRaw = getNextArg();
1921 if (enforcedRaw == null) {
1922 getErrPrintWriter().println("Error: no enforcement specified");
1923 return 1;
1924 }
1925 mInterface.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw));
1926 return 0;
1927 }
1928
Jiyong Park002fdbd2017-02-13 20:50:31 +09001929 private boolean isVendorApp(String pkg) {
1930 try {
1931 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
1932 return info != null && info.applicationInfo.isVendor();
1933 } catch (RemoteException e) {
1934 return false;
1935 }
1936 }
1937
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09001938 private boolean isProductApp(String pkg) {
1939 try {
1940 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
1941 return info != null && info.applicationInfo.isProduct();
1942 } catch (RemoteException e) {
1943 return false;
1944 }
1945 }
1946
Dario Freni2bef1762018-06-01 14:02:08 +01001947 private boolean isProductServicesApp(String pkg) {
1948 try {
1949 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
1950 return info != null && info.applicationInfo.isProductServices();
1951 } catch (RemoteException e) {
1952 return false;
1953 }
1954 }
1955
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001956 private int runGetPrivappPermissions() {
1957 final String pkg = getNextArg();
1958 if (pkg == null) {
1959 getErrPrintWriter().println("Error: no package specified.");
1960 return 1;
1961 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001962
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09001963 ArraySet<String> privAppPermissions = null;
1964 if (isVendorApp(pkg)) {
1965 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
1966 } else if (isProductApp(pkg)) {
1967 privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
Dario Freni2bef1762018-06-01 14:02:08 +01001968 } else if (isProductServicesApp(pkg)) {
1969 privAppPermissions = SystemConfig.getInstance()
1970 .getProductServicesPrivAppPermissions(pkg);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09001971 } else {
1972 privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
1973 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001974
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001975 getOutPrintWriter().println(privAppPermissions == null
1976 ? "{}" : privAppPermissions.toString());
1977 return 0;
1978 }
1979
1980 private int runGetPrivappDenyPermissions() {
1981 final String pkg = getNextArg();
1982 if (pkg == null) {
1983 getErrPrintWriter().println("Error: no package specified.");
1984 return 1;
1985 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001986
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09001987 ArraySet<String> privAppPermissions = null;
1988 if (isVendorApp(pkg)) {
1989 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
1990 } else if (isProductApp(pkg)) {
1991 privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
Dario Freni2bef1762018-06-01 14:02:08 +01001992 } else if (isProductServicesApp(pkg)) {
1993 privAppPermissions = SystemConfig.getInstance()
1994 .getProductServicesPrivAppDenyPermissions(pkg);
Jaekyun Seok1713d9e2018-01-12 21:47:26 +09001995 } else {
1996 privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
1997 }
Jiyong Park002fdbd2017-02-13 20:50:31 +09001998
1999 getOutPrintWriter().println(privAppPermissions == null
2000 ? "{}" : privAppPermissions.toString());
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002001 return 0;
2002 }
2003
2004 private int runGetOemPermissions() {
2005 final String pkg = getNextArg();
2006 if (pkg == null) {
2007 getErrPrintWriter().println("Error: no package specified.");
2008 return 1;
2009 }
2010 final Map<String, Boolean> oemPermissions = SystemConfig.getInstance()
2011 .getOemPermissions(pkg);
2012 if (oemPermissions == null || oemPermissions.isEmpty()) {
2013 getOutPrintWriter().println("{}");
2014 } else {
2015 oemPermissions.forEach((permission, granted) ->
2016 getOutPrintWriter().println(permission + " granted:" + granted)
2017 );
2018 }
2019 return 0;
2020 }
2021
2022 private String linkStateToString(int state) {
2023 switch (state) {
2024 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
2025 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
2026 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
2027 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
2028 case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
2029 }
2030 return "Unknown link state: " + state;
2031 }
2032
2033 // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
2034 private int runSetAppLink() throws RemoteException {
2035 int userId = UserHandle.USER_SYSTEM;
2036
2037 String opt;
2038 while ((opt = getNextOption()) != null) {
2039 if (opt.equals("--user")) {
2040 userId = UserHandle.parseUserArg(getNextArgRequired());
2041 } else {
2042 getErrPrintWriter().println("Error: unknown option: " + opt);
2043 return 1;
2044 }
2045 }
2046
2047 // Package name to act on; required
2048 final String pkg = getNextArg();
2049 if (pkg == null) {
2050 getErrPrintWriter().println("Error: no package specified.");
2051 return 1;
2052 }
2053
2054 // State to apply; {always|ask|never|undefined}, required
2055 final String modeString = getNextArg();
2056 if (modeString == null) {
2057 getErrPrintWriter().println("Error: no app link state specified.");
2058 return 1;
2059 }
2060
2061 final int newMode;
2062 switch (modeString.toLowerCase()) {
2063 case "undefined":
2064 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
2065 break;
2066
2067 case "always":
2068 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
2069 break;
2070
2071 case "ask":
2072 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
2073 break;
2074
2075 case "always-ask":
2076 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
2077 break;
2078
2079 case "never":
2080 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
2081 break;
2082
2083 default:
2084 getErrPrintWriter().println("Error: unknown app link state '" + modeString + "'");
2085 return 1;
2086 }
2087
2088 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, userId);
2089 if (info == null) {
2090 getErrPrintWriter().println("Error: package " + pkg + " not found.");
2091 return 1;
2092 }
2093
2094 if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2095 getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2096 return 1;
2097 }
2098
2099 if (!mInterface.updateIntentVerificationStatus(pkg, newMode, userId)) {
2100 getErrPrintWriter().println("Error: unable to update app link status for " + pkg);
2101 return 1;
2102 }
2103
2104 return 0;
2105 }
2106
2107 // pm get-app-link [--user USER_ID] PACKAGE
2108 private int runGetAppLink() throws RemoteException {
2109 int userId = UserHandle.USER_SYSTEM;
2110
2111 String opt;
2112 while ((opt = getNextOption()) != null) {
2113 if (opt.equals("--user")) {
2114 userId = UserHandle.parseUserArg(getNextArgRequired());
2115 } else {
2116 getErrPrintWriter().println("Error: unknown option: " + opt);
2117 return 1;
2118 }
2119 }
2120
2121 // Package name to act on; required
2122 final String pkg = getNextArg();
2123 if (pkg == null) {
2124 getErrPrintWriter().println("Error: no package specified.");
2125 return 1;
2126 }
2127
2128 final PackageInfo info = mInterface.getPackageInfo(pkg, 0, userId);
2129 if (info == null) {
2130 getErrPrintWriter().println("Error: package " + pkg + " not found.");
2131 return 1;
2132 }
2133
2134 if ((info.applicationInfo.privateFlags
2135 & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2136 getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2137 return 1;
2138 }
2139
2140 getOutPrintWriter().println(linkStateToString(
2141 mInterface.getIntentVerificationStatus(pkg, userId)));
2142
2143 return 0;
2144 }
2145
2146 private int runTrimCaches() throws RemoteException {
2147 String size = getNextArg();
2148 if (size == null) {
2149 getErrPrintWriter().println("Error: no size specified");
2150 return 1;
2151 }
2152 long multiplier = 1;
2153 int len = size.length();
2154 char c = size.charAt(len - 1);
2155 if (c < '0' || c > '9') {
2156 if (c == 'K' || c == 'k') {
2157 multiplier = 1024L;
2158 } else if (c == 'M' || c == 'm') {
2159 multiplier = 1024L*1024L;
2160 } else if (c == 'G' || c == 'g') {
2161 multiplier = 1024L*1024L*1024L;
2162 } else {
2163 getErrPrintWriter().println("Invalid suffix: " + c);
2164 return 1;
2165 }
2166 size = size.substring(0, len-1);
2167 }
2168 long sizeVal;
2169 try {
2170 sizeVal = Long.parseLong(size) * multiplier;
2171 } catch (NumberFormatException e) {
2172 getErrPrintWriter().println("Error: expected number at: " + size);
2173 return 1;
2174 }
2175 String volumeUuid = getNextArg();
2176 if ("internal".equals(volumeUuid)) {
2177 volumeUuid = null;
2178 }
2179 ClearDataObserver obs = new ClearDataObserver();
2180 mInterface.freeStorageAndNotify(volumeUuid, sizeVal,
2181 StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs);
2182 synchronized (obs) {
2183 while (!obs.finished) {
2184 try {
2185 obs.wait();
2186 } catch (InterruptedException e) {
2187 }
2188 }
2189 }
2190 return 0;
2191 }
2192
2193 private static boolean isNumber(String s) {
2194 try {
2195 Integer.parseInt(s);
2196 } catch (NumberFormatException nfe) {
2197 return false;
2198 }
2199 return true;
2200 }
2201
2202 public int runCreateUser() throws RemoteException {
2203 String name;
2204 int userId = -1;
2205 int flags = 0;
2206 String opt;
2207 while ((opt = getNextOption()) != null) {
2208 if ("--profileOf".equals(opt)) {
2209 userId = UserHandle.parseUserArg(getNextArgRequired());
2210 } else if ("--managed".equals(opt)) {
2211 flags |= UserInfo.FLAG_MANAGED_PROFILE;
2212 } else if ("--restricted".equals(opt)) {
2213 flags |= UserInfo.FLAG_RESTRICTED;
2214 } else if ("--ephemeral".equals(opt)) {
2215 flags |= UserInfo.FLAG_EPHEMERAL;
2216 } else if ("--guest".equals(opt)) {
2217 flags |= UserInfo.FLAG_GUEST;
2218 } else if ("--demo".equals(opt)) {
2219 flags |= UserInfo.FLAG_DEMO;
2220 } else {
2221 getErrPrintWriter().println("Error: unknown option " + opt);
2222 return 1;
2223 }
2224 }
2225 String arg = getNextArg();
2226 if (arg == null) {
2227 getErrPrintWriter().println("Error: no user name specified.");
2228 return 1;
2229 }
2230 name = arg;
2231 UserInfo info;
2232 IUserManager um = IUserManager.Stub.asInterface(
2233 ServiceManager.getService(Context.USER_SERVICE));
2234 IAccountManager accm = IAccountManager.Stub.asInterface(
2235 ServiceManager.getService(Context.ACCOUNT_SERVICE));
2236 if ((flags & UserInfo.FLAG_RESTRICTED) != 0) {
2237 // In non-split user mode, userId can only be SYSTEM
2238 int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
2239 info = um.createRestrictedProfile(name, parentUserId);
2240 accm.addSharedAccountsFromParentUser(parentUserId, userId,
2241 (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
2242 } else if (userId < 0) {
2243 info = um.createUser(name, flags);
2244 } else {
2245 info = um.createProfileForUser(name, flags, userId, null);
2246 }
2247
2248 if (info != null) {
2249 getOutPrintWriter().println("Success: created user id " + info.id);
2250 return 0;
2251 } else {
2252 getErrPrintWriter().println("Error: couldn't create User.");
2253 return 1;
2254 }
2255 }
2256
2257 public int runRemoveUser() throws RemoteException {
2258 int userId;
2259 String arg = getNextArg();
2260 if (arg == null) {
2261 getErrPrintWriter().println("Error: no user id specified.");
2262 return 1;
2263 }
2264 userId = UserHandle.parseUserArg(arg);
2265 IUserManager um = IUserManager.Stub.asInterface(
2266 ServiceManager.getService(Context.USER_SERVICE));
2267 if (um.removeUser(userId)) {
2268 getOutPrintWriter().println("Success: removed user");
2269 return 0;
2270 } else {
2271 getErrPrintWriter().println("Error: couldn't remove user id " + userId);
2272 return 1;
2273 }
2274 }
2275
2276 public int runSetUserRestriction() throws RemoteException {
2277 int userId = UserHandle.USER_SYSTEM;
2278 String opt = getNextOption();
2279 if (opt != null && "--user".equals(opt)) {
2280 userId = UserHandle.parseUserArg(getNextArgRequired());
2281 }
2282
2283 String restriction = getNextArg();
2284 String arg = getNextArg();
2285 boolean value;
2286 if ("1".equals(arg)) {
2287 value = true;
2288 } else if ("0".equals(arg)) {
2289 value = false;
2290 } else {
2291 getErrPrintWriter().println("Error: valid value not specified");
2292 return 1;
2293 }
2294 IUserManager um = IUserManager.Stub.asInterface(
2295 ServiceManager.getService(Context.USER_SERVICE));
2296 um.setUserRestriction(restriction, value, userId);
2297 return 0;
2298 }
2299
2300 public int runGetMaxUsers() {
2301 getOutPrintWriter().println("Maximum supported users: "
2302 + UserManager.getMaxSupportedUsers());
2303 return 0;
2304 }
2305
Alex Chauc12189b2018-01-16 15:01:15 +00002306 public int runGetMaxRunningUsers() {
2307 ActivityManagerInternal activityManagerInternal =
2308 LocalServices.getService(ActivityManagerInternal.class);
2309 getOutPrintWriter().println("Maximum supported running users: "
2310 + activityManagerInternal.getMaxRunningUsers());
2311 return 0;
2312 }
2313
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002314 private static class InstallParams {
2315 SessionParams sessionParams;
2316 String installerPackageName;
2317 int userId = UserHandle.USER_ALL;
2318 }
2319
2320 private InstallParams makeInstallParams() {
2321 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2322 final InstallParams params = new InstallParams();
2323 params.sessionParams = sessionParams;
2324 String opt;
Patrick Baumanna9333492017-11-28 15:23:49 -08002325 boolean replaceExisting = true;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002326 while ((opt = getNextOption()) != null) {
2327 switch (opt) {
Patrick Baumanna9333492017-11-28 15:23:49 -08002328 case "-r": // ignore
2329 break;
2330 case "-R":
2331 replaceExisting = false;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002332 break;
2333 case "-i":
2334 params.installerPackageName = getNextArg();
2335 if (params.installerPackageName == null) {
2336 throw new IllegalArgumentException("Missing installer package");
2337 }
2338 break;
2339 case "-t":
2340 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
2341 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002342 case "-f":
2343 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
2344 break;
2345 case "-d":
Nikita Ioffeb1d60f12019-03-06 18:56:49 +00002346 sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002347 break;
2348 case "-g":
2349 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
2350 break;
Todd Kennedyb1072712016-04-26 15:41:20 -07002351 case "--dont-kill":
2352 sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
2353 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002354 case "--originating-uri":
2355 sessionParams.originatingUri = Uri.parse(getNextArg());
2356 break;
2357 case "--referrer":
2358 sessionParams.referrerUri = Uri.parse(getNextArg());
2359 break;
2360 case "-p":
2361 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
2362 sessionParams.appPackageName = getNextArg();
2363 if (sessionParams.appPackageName == null) {
2364 throw new IllegalArgumentException("Missing inherit package name");
2365 }
2366 break;
Dianne Hackbornca3872c2017-10-30 14:19:32 -07002367 case "--pkg":
2368 sessionParams.appPackageName = getNextArg();
2369 if (sessionParams.appPackageName == null) {
2370 throw new IllegalArgumentException("Missing package name");
2371 }
2372 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002373 case "-S":
Todd Kennedy9caf94e2016-10-12 15:26:08 -07002374 final long sizeBytes = Long.parseLong(getNextArg());
2375 if (sizeBytes <= 0) {
2376 throw new IllegalArgumentException("Size must be positive");
2377 }
2378 sessionParams.setSize(sizeBytes);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002379 break;
2380 case "--abi":
2381 sessionParams.abiOverride = checkAbiArgument(getNextArg());
2382 break;
Todd Kennedy2699f062015-11-20 13:07:17 -08002383 case "--ephemeral":
Dianne Hackbornca3872c2017-10-30 14:19:32 -07002384 case "--instant":
Todd Kennedybe0b8892017-02-15 14:13:52 -08002385 case "--instantapp":
Todd Kennedyb7717682016-11-30 15:41:21 -08002386 sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
Todd Kennedy2699f062015-11-20 13:07:17 -08002387 break;
Todd Kennedybe0b8892017-02-15 14:13:52 -08002388 case "--full":
2389 sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
2390 break;
Todd Kennedy78a72502017-07-19 12:49:30 -07002391 case "--preload":
2392 sessionParams.setInstallAsVirtualPreload();
2393 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002394 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08002395 params.userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002396 break;
2397 case "--install-location":
2398 sessionParams.installLocation = Integer.parseInt(getNextArg());
2399 break;
Sunny Goyalabd4d442018-09-19 15:49:50 -07002400 case "--install-reason":
2401 sessionParams.installReason = Integer.parseInt(getNextArg());
2402 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002403 case "--force-uuid":
2404 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
2405 sessionParams.volumeUuid = getNextArg();
2406 if ("internal".equals(sessionParams.volumeUuid)) {
2407 sessionParams.volumeUuid = null;
2408 }
2409 break;
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +00002410 case "--force-sdk": // ignore
Todd Kennedyb1072712016-04-26 15:41:20 -07002411 break;
Dario Frenid8bf22e2018-08-31 14:18:04 +01002412 case "--apex":
Dario Freni3fa46d82019-01-23 19:31:47 +00002413 sessionParams.setInstallAsApex();
Dario Freni505b8152019-01-08 12:30:43 +00002414 sessionParams.setStaged();
Dario Frenid8bf22e2018-08-31 14:18:04 +01002415 break;
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002416 case "--multi-package":
2417 sessionParams.setMultiPackage();
2418 break;
Dario Freniaac4ba42018-12-06 15:47:16 +00002419 case "--staged":
2420 sessionParams.setStaged();
2421 break;
Richard Uhlerb29f1452018-09-12 16:38:15 +01002422 case "--enable-rollback":
2423 sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
2424 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002425 default:
2426 throw new IllegalArgumentException("Unknown option " + opt);
2427 }
Patrick Baumanna9333492017-11-28 15:23:49 -08002428 if (replaceExisting) {
2429 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
2430 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002431 }
2432 return params;
2433 }
2434
Makoto Onuki4828a592016-03-15 18:06:57 -07002435 private int runSetHomeActivity() {
2436 final PrintWriter pw = getOutPrintWriter();
2437 int userId = UserHandle.USER_SYSTEM;
2438 String opt;
2439 while ((opt = getNextOption()) != null) {
2440 switch (opt) {
2441 case "--user":
2442 userId = UserHandle.parseUserArg(getNextArgRequired());
2443 break;
2444 default:
2445 pw.println("Error: Unknown option: " + opt);
2446 return 1;
2447 }
2448 }
2449
2450 String component = getNextArg();
2451 ComponentName componentName =
2452 component != null ? ComponentName.unflattenFromString(component) : null;
2453
2454 if (componentName == null) {
2455 pw.println("Error: component name not specified or invalid");
2456 return 1;
2457 }
2458
2459 try {
2460 mInterface.setHomeActivity(componentName, userId);
Makoto Onuki3bdbf982016-06-23 16:56:35 -07002461 pw.println("Success");
Makoto Onuki4828a592016-03-15 18:06:57 -07002462 return 0;
Makoto Onuki3bdbf982016-06-23 16:56:35 -07002463 } catch (Exception e) {
Makoto Onuki4828a592016-03-15 18:06:57 -07002464 pw.println(e.toString());
2465 return 1;
2466 }
2467 }
2468
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002469 private int runSetInstaller() throws RemoteException {
2470 final String targetPackage = getNextArg();
2471 final String installerPackageName = getNextArg();
Fyodor Kupolov51245c72016-12-01 11:34:10 -08002472
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002473 if (targetPackage == null || installerPackageName == null) {
2474 getErrPrintWriter().println("Must provide both target and installer package names");
Todd Kennedy74629e32017-08-15 14:48:07 -07002475 return 1;
2476 }
Todd Kennedy74629e32017-08-15 14:48:07 -07002477
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002478 mInterface.setInstallerPackageName(targetPackage, installerPackageName);
2479 getOutPrintWriter().println("Success");
Svet Ganov087dce22017-09-07 15:42:16 -07002480 return 0;
2481 }
2482
Todd Kennedy0a3f0812017-05-08 14:43:15 -07002483 private int runGetInstantAppResolver() {
2484 final PrintWriter pw = getOutPrintWriter();
2485 try {
2486 final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent();
2487 if (instantAppsResolver == null) {
2488 return 1;
2489 }
2490 pw.println(instantAppsResolver.flattenToString());
2491 return 0;
2492 } catch (Exception e) {
2493 pw.println(e.toString());
2494 return 1;
2495 }
2496 }
2497
Tadashi G. Takaokabe5782f2017-02-14 16:41:49 +09002498 private int runHasFeature() {
2499 final PrintWriter err = getErrPrintWriter();
2500 final String featureName = getNextArg();
2501 if (featureName == null) {
2502 err.println("Error: expected FEATURE name");
2503 return 1;
2504 }
2505 final String versionString = getNextArg();
2506 try {
2507 final int version = (versionString == null) ? 0 : Integer.parseInt(versionString);
2508 final boolean hasFeature = mInterface.hasSystemFeature(featureName, version);
2509 getOutPrintWriter().println(hasFeature);
2510 return hasFeature ? 0 : 1;
2511 } catch (NumberFormatException e) {
2512 err.println("Error: illegal version number " + versionString);
2513 return 1;
2514 } catch (RemoteException e) {
2515 err.println(e.toString());
2516 return 1;
2517 }
2518 }
2519
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002520 private int runDump() {
2521 String pkg = getNextArg();
2522 if (pkg == null) {
2523 getErrPrintWriter().println("Error: no package specified");
2524 return 1;
2525 }
2526 ActivityManager.dumpPackageStateStatic(getOutFileDescriptor(), pkg);
2527 return 0;
2528 }
2529
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002530 private int runSetHarmfulAppWarning() throws RemoteException {
2531 int userId = UserHandle.USER_CURRENT;
2532
2533 String opt;
2534 while ((opt = getNextOption()) != null) {
2535 if (opt.equals("--user")) {
2536 userId = UserHandle.parseUserArg(getNextArgRequired());
2537 } else {
2538 getErrPrintWriter().println("Error: Unknown option: " + opt);
2539 return -1;
2540 }
2541 }
2542
2543 userId = translateUserId(userId, false /*allowAll*/, "runSetHarmfulAppWarning");
2544
2545 final String packageName = getNextArgRequired();
2546 final String warning = getNextArg();
2547
2548 mInterface.setHarmfulAppWarning(packageName, warning, userId);
2549
2550 return 0;
2551 }
2552
Ben Gruver9ef60092018-01-10 11:32:30 -08002553 private int runGetHarmfulAppWarning() throws RemoteException {
2554 int userId = UserHandle.USER_CURRENT;
2555
2556 String opt;
2557 while ((opt = getNextOption()) != null) {
2558 if (opt.equals("--user")) {
2559 userId = UserHandle.parseUserArg(getNextArgRequired());
2560 } else {
2561 getErrPrintWriter().println("Error: Unknown option: " + opt);
2562 return -1;
2563 }
2564 }
2565
2566 userId = translateUserId(userId, false /*allowAll*/, "runGetHarmfulAppWarning");
2567
2568 final String packageName = getNextArgRequired();
2569 final CharSequence warning = mInterface.getHarmfulAppWarning(packageName, userId);
2570 if (!TextUtils.isEmpty(warning)) {
2571 getOutPrintWriter().println(warning);
2572 return 0;
2573 } else {
2574 return 1;
2575 }
2576 }
2577
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002578 private static String checkAbiArgument(String abi) {
2579 if (TextUtils.isEmpty(abi)) {
2580 throw new IllegalArgumentException("Missing ABI argument");
2581 }
2582
2583 if ("-".equals(abi)) {
2584 return abi;
2585 }
2586
2587 final String[] supportedAbis = Build.SUPPORTED_ABIS;
2588 for (String supportedAbi : supportedAbis) {
2589 if (supportedAbi.equals(abi)) {
2590 return abi;
2591 }
2592 }
2593
2594 throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
2595 }
2596
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002597 private int translateUserId(int userId, boolean allowAll, String logContext) {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002598 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002599 userId, allowAll, true, logContext, "pm command");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002600 }
2601
2602 private int doCreateSession(SessionParams params, String installerPackageName, int userId)
2603 throws RemoteException {
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08002604 userId = translateUserId(userId, true /*allowAll*/, "runInstallCreate");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002605 if (userId == UserHandle.USER_ALL) {
2606 userId = UserHandle.USER_SYSTEM;
2607 params.installFlags |= PackageManager.INSTALL_ALL_USERS;
2608 }
2609
2610 final int sessionId = mInterface.getPackageInstaller()
2611 .createSession(params, installerPackageName, userId);
2612 return sessionId;
2613 }
2614
Todd Kennedyeb9b0532016-03-08 10:10:54 -08002615 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
Todd Kennedy8d9366c2015-12-16 13:47:14 -08002616 boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002617 PackageInstaller.Session session = null;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002618 try {
Jeff Sharkeya651b782018-07-23 13:45:28 -06002619 final PrintWriter pw = getOutPrintWriter();
2620 final ParcelFileDescriptor fd;
2621 if (STDIN_PATH.equals(inPath)) {
2622 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
2623 } else if (inPath != null) {
2624 fd = openFileForSystem(inPath, "r");
2625 if (fd == null) {
2626 return -1;
2627 }
2628 sizeBytes = fd.getStatSize();
2629 if (sizeBytes < 0) {
2630 getErrPrintWriter().println("Unable to get size of: " + inPath);
2631 return -1;
2632 }
2633 } else {
2634 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
2635 }
2636 if (sizeBytes <= 0) {
2637 getErrPrintWriter().println("Error: must specify a APK size");
2638 return 1;
2639 }
2640
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002641 session = new PackageInstaller.Session(
2642 mInterface.getPackageInstaller().openSession(sessionId));
Jeff Sharkey0451de62018-02-02 11:27:21 -07002643 session.write(splitName, 0, sizeBytes, fd);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002644
Todd Kennedy8d9366c2015-12-16 13:47:14 -08002645 if (logSuccess) {
Jeff Sharkey0451de62018-02-02 11:27:21 -07002646 pw.println("Success: streamed " + sizeBytes + " bytes");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08002647 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002648 return 0;
2649 } catch (IOException e) {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07002650 getErrPrintWriter().println("Error: failed to write; " + e.getMessage());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002651 return 1;
2652 } finally {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002653 IoUtils.closeQuietly(session);
2654 }
2655 }
2656
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002657 private int doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)
2658 throws RemoteException {
2659 final PrintWriter pw = getOutPrintWriter();
2660 PackageInstaller.Session session = null;
2661 try {
2662 session = new PackageInstaller.Session(
2663 mInterface.getPackageInstaller().openSession(parentId));
2664 if (!session.isMultiPackage()) {
2665 getErrPrintWriter().println(
2666 "Error: parent session ID is not a multi-package session");
2667 return 1;
2668 }
2669 for (int i = 0; i < sessionIds.length; i++) {
2670 session.addChildSessionId(sessionIds[i]);
2671 }
2672 if (logSuccess) {
2673 pw.println("Success");
2674 }
2675 return 0;
2676 } finally {
2677 IoUtils.closeQuietly(session);
2678 }
2679 }
2680
Todd Kennedyeb9b0532016-03-08 10:10:54 -08002681 private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
2682 throws RemoteException {
2683 final PrintWriter pw = getOutPrintWriter();
2684 PackageInstaller.Session session = null;
2685 try {
2686 session = new PackageInstaller.Session(
2687 mInterface.getPackageInstaller().openSession(sessionId));
2688 session.removeSplit(splitName);
2689
2690 if (logSuccess) {
2691 pw.println("Success");
2692 }
2693 return 0;
2694 } catch (IOException e) {
2695 pw.println("Error: failed to remove split; " + e.getMessage());
2696 return 1;
2697 } finally {
2698 IoUtils.closeQuietly(session);
2699 }
2700 }
2701
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002702 private int doCommitSession(int sessionId, boolean logSuccess)
2703 throws RemoteException {
2704
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002705 final PrintWriter pw = getOutPrintWriter();
2706 PackageInstaller.Session session = null;
2707 try {
2708 session = new PackageInstaller.Session(
2709 mInterface.getPackageInstaller().openSession(sessionId));
Dario Frenia8f4b132018-12-30 00:36:49 +00002710 if (!session.isMultiPackage() && !session.isStaged()) {
Patrick Baumann0aff9b12018-11-08 14:05:08 +00002711 // Sanity check that all .dm files match an apk.
2712 // (The installer does not support standalone .dm files and will not process them.)
2713 try {
2714 DexMetadataHelper.validateDexPaths(session.getNames());
2715 } catch (IllegalStateException | IOException e) {
2716 pw.println(
2717 "Warning [Could not validate the dex paths: " + e.getMessage() + "]");
2718 }
Calin Juravle3fc56c32017-12-11 18:26:13 -08002719 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002720 final LocalIntentReceiver receiver = new LocalIntentReceiver();
2721 session.commit(receiver.getIntentSender());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002722 final Intent result = receiver.getResult();
2723 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
2724 PackageInstaller.STATUS_FAILURE);
2725 if (status == PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -08002726 if (logSuccess) {
Todd Kennedyb6e96e52016-07-20 16:27:39 -07002727 pw.println("Success");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08002728 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002729 } else {
2730 pw.println("Failure ["
2731 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002732 }
2733 return status;
2734 } finally {
2735 IoUtils.closeQuietly(session);
2736 }
2737 }
2738
Todd Kennedy8d9366c2015-12-16 13:47:14 -08002739 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002740 final PrintWriter pw = getOutPrintWriter();
2741 PackageInstaller.Session session = null;
2742 try {
2743 session = new PackageInstaller.Session(
2744 mInterface.getPackageInstaller().openSession(sessionId));
2745 session.abandon();
Todd Kennedy8d9366c2015-12-16 13:47:14 -08002746 if (logSuccess) {
2747 pw.println("Success");
2748 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08002749 return 0;
2750 } finally {
2751 IoUtils.closeQuietly(session);
2752 }
2753 }
2754
Todd Kennedy60459ab2015-10-30 11:32:16 -07002755 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
2756 boolean summary, int startProtectionLevel, int endProtectionLevel)
2757 throws RemoteException {
2758 final PrintWriter pw = getOutPrintWriter();
2759 final int groupCount = groupList.size();
2760 for (int i = 0; i < groupCount; i++) {
2761 String groupName = groupList.get(i);
2762 String prefix = "";
2763 if (groups) {
2764 if (i > 0) {
2765 pw.println("");
2766 }
2767 if (groupName != null) {
2768 PermissionGroupInfo pgi =
2769 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
2770 if (summary) {
2771 Resources res = getResources(pgi);
2772 if (res != null) {
2773 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
2774 } else {
2775 pw.print(pgi.name + ": ");
2776
2777 }
2778 } else {
2779 pw.println((labels ? "+ " : "") + "group:" + pgi.name);
2780 if (labels) {
2781 pw.println(" package:" + pgi.packageName);
2782 Resources res = getResources(pgi);
2783 if (res != null) {
2784 pw.println(" label:"
2785 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
2786 pw.println(" description:"
2787 + loadText(pgi, pgi.descriptionRes,
2788 pgi.nonLocalizedDescription));
2789 }
2790 }
2791 }
2792 } else {
2793 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
2794 }
2795 prefix = " ";
2796 }
2797 List<PermissionInfo> ps =
Jeff Sharkeyd5896632016-03-04 16:16:00 -07002798 mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -07002799 final int count = ps.size();
2800 boolean first = true;
2801 for (int p = 0 ; p < count ; p++) {
2802 PermissionInfo pi = ps.get(p);
2803 if (groups && groupName == null && pi.group != null) {
2804 continue;
2805 }
2806 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
2807 if (base < startProtectionLevel
2808 || base > endProtectionLevel) {
2809 continue;
2810 }
2811 if (summary) {
2812 if (first) {
2813 first = false;
2814 } else {
2815 pw.print(", ");
2816 }
2817 Resources res = getResources(pi);
2818 if (res != null) {
2819 pw.print(loadText(pi, pi.labelRes,
2820 pi.nonLocalizedLabel));
2821 } else {
2822 pw.print(pi.name);
2823 }
2824 } else {
2825 pw.println(prefix + (labels ? "+ " : "")
2826 + "permission:" + pi.name);
2827 if (labels) {
2828 pw.println(prefix + " package:" + pi.packageName);
2829 Resources res = getResources(pi);
2830 if (res != null) {
2831 pw.println(prefix + " label:"
2832 + loadText(pi, pi.labelRes,
2833 pi.nonLocalizedLabel));
2834 pw.println(prefix + " description:"
2835 + loadText(pi, pi.descriptionRes,
2836 pi.nonLocalizedDescription));
2837 }
2838 pw.println(prefix + " protectionLevel:"
2839 + PermissionInfo.protectionToString(pi.protectionLevel));
2840 }
2841 }
2842 }
2843
2844 if (summary) {
2845 pw.println("");
2846 }
2847 }
2848 }
2849
2850 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
2851 throws RemoteException {
2852 if (nonLocalized != null) {
2853 return nonLocalized.toString();
2854 }
2855 if (res != 0) {
2856 Resources r = getResources(pii);
2857 if (r != null) {
2858 try {
2859 return r.getString(res);
2860 } catch (Resources.NotFoundException e) {
2861 }
2862 }
2863 }
2864 return null;
2865 }
2866
2867 private Resources getResources(PackageItemInfo pii) throws RemoteException {
2868 Resources res = mResourceCache.get(pii.packageName);
2869 if (res != null) return res;
2870
2871 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0);
2872 AssetManager am = new AssetManager();
2873 am.addAssetPath(ai.publicSourceDir);
2874 res = new Resources(am, null, null);
2875 mResourceCache.put(pii.packageName, res);
2876 return res;
2877 }
2878
2879 @Override
2880 public void onHelp() {
2881 final PrintWriter pw = getOutPrintWriter();
2882 pw.println("Package manager (package) commands:");
2883 pw.println(" help");
2884 pw.println(" Print this help text.");
2885 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002886 pw.println(" path [--user USER_ID] PACKAGE");
2887 pw.println(" Print the path to the .apk of the given PACKAGE.");
2888 pw.println("");
2889 pw.println(" dump PACKAGE");
2890 pw.println(" Print various system state associated with the given PACKAGE.");
2891 pw.println("");
2892 pw.println(" list features");
2893 pw.println(" Prints all features of the system.");
2894 pw.println("");
2895 pw.println(" has-feature FEATURE_NAME [version]");
2896 pw.println(" Prints true and returns exit status 0 when system has a FEATURE_NAME,");
2897 pw.println(" otherwise prints false and returns exit status 1");
2898 pw.println("");
2899 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
2900 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE");
2901 pw.println(" Options:");
2902 pw.println(" -f: dump the name of the .apk file containing the test package");
2903 pw.println("");
2904 pw.println(" list libraries");
2905 pw.println(" Prints all system libraries.");
2906 pw.println("");
2907 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
Jiyong Parkf50a2932018-12-17 13:54:40 +09002908 pw.println(" [--show-versioncode] [--apex-only] [--uid UID] [--user USER_ID] [FILTER]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002909 pw.println(" Prints all packages; optionally only those whose name contains");
2910 pw.println(" the text in FILTER. Options are:");
2911 pw.println(" -f: see their associated file");
Jiyong Park4f49abe2018-12-11 13:37:17 +09002912 pw.println(" -a: all known packages (but excluding APEXes)");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002913 pw.println(" -d: filter to only show disabled packages");
2914 pw.println(" -e: filter to only show enabled packages");
2915 pw.println(" -s: filter to only show system packages");
2916 pw.println(" -3: filter to only show third party packages");
2917 pw.println(" -i: see the installer for the packages");
2918 pw.println(" -l: ignored (used for compatibility with older releases)");
2919 pw.println(" -U: also show the package UID");
2920 pw.println(" -u: also include uninstalled packages");
Jiyong Parkf50a2932018-12-17 13:54:40 +09002921 pw.println(" --show-versioncode: also show the version code");
Jiyong Park4f49abe2018-12-11 13:37:17 +09002922 pw.println(" --apex-only: only show APEX packages");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002923 pw.println(" --uid UID: filter to only show packages with the given UID");
2924 pw.println(" --user USER_ID: only list packages belonging to the given user");
2925 pw.println("");
2926 pw.println(" list permission-groups");
2927 pw.println(" Prints all known permission groups.");
2928 pw.println("");
2929 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
2930 pw.println(" Prints all known permissions; optionally only those in GROUP. Options are:");
2931 pw.println(" -g: organize by group");
2932 pw.println(" -f: print all information");
2933 pw.println(" -s: short summary");
2934 pw.println(" -d: only list dangerous permissions");
2935 pw.println(" -u: list only the permissions users will see");
2936 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07002937 pw.println(" resolve-activity [--brief] [--components] [--query-flags FLAGS]");
2938 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002939 pw.println(" Prints the activity that resolves to the given INTENT.");
2940 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07002941 pw.println(" query-activities [--brief] [--components] [--query-flags FLAGS]");
2942 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002943 pw.println(" Prints all activities that can handle the given INTENT.");
2944 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07002945 pw.println(" query-services [--brief] [--components] [--query-flags FLAGS]");
2946 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002947 pw.println(" Prints all services that can handle the given INTENT.");
2948 pw.println("");
Ng Zhi An73971312018-09-11 21:39:14 -07002949 pw.println(" query-receivers [--brief] [--components] [--query-flags FLAGS]");
2950 pw.println(" [--user USER_ID] INTENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002951 pw.println(" Prints all broadcast receivers that can handle the given INTENT.");
2952 pw.println("");
2953 pw.println(" install [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
2954 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
Sunny Goyalabd4d442018-09-19 15:49:50 -07002955 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
2956 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002957 pw.println(" [--preload] [--instantapp] [--full] [--dont-kill]");
Richard Uhlerb29f1452018-09-12 16:38:15 +01002958 pw.println(" [--enable-rollback]");
MÃ¥rten Kongstad2a5989342018-11-16 15:04:44 +01002959 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES] [--apex]");
2960 pw.println(" [PATH|-]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002961 pw.println(" Install an application. Must provide the apk data to install, either as a");
2962 pw.println(" file path or '-' to read from stdin. Options are:");
2963 pw.println(" -l: forward lock application");
Patrick Baumanna9333492017-11-28 15:23:49 -08002964 pw.println(" -R: disallow replacement of existing application");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002965 pw.println(" -t: allow test packages");
2966 pw.println(" -i: specify package name of installer owning the app");
2967 pw.println(" -s: install application on sdcard");
2968 pw.println(" -f: install application on internal flash");
2969 pw.println(" -d: allow version code downgrade (debuggable packages only)");
2970 pw.println(" -p: partial application install (new split on top of existing pkg)");
2971 pw.println(" -g: grant all runtime permissions");
2972 pw.println(" -S: size in bytes of package, required for stdin");
2973 pw.println(" --user: install under the given user.");
2974 pw.println(" --dont-kill: installing a new feature split, don't kill running app");
2975 pw.println(" --originating-uri: set URI where app was downloaded from");
2976 pw.println(" --referrer: set URI that instigated the install of the app");
2977 pw.println(" --pkg: specify expected package name of app being installed");
2978 pw.println(" --abi: override the default ABI of the platform");
2979 pw.println(" --instantapp: cause the app to be installed as an ephemeral install app");
2980 pw.println(" --full: cause the app to be installed as a non-ephemeral full app");
2981 pw.println(" --install-location: force the install location:");
2982 pw.println(" 0=auto, 1=internal only, 2=prefer external");
Sunny Goyalabd4d442018-09-19 15:49:50 -07002983 pw.println(" --install-reason: indicates why the app is being installed:");
2984 pw.println(" 0=unknown, 1=admin policy, 2=device restore,");
2985 pw.println(" 3=device setup, 4=user request");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002986 pw.println(" --force-uuid: force install on to disk volume with given UUID");
MÃ¥rten Kongstad2a5989342018-11-16 15:04:44 +01002987 pw.println(" --apex: install an .apex file, not an .apk");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002988 pw.println("");
2989 pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
2990 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
Sunny Goyalabd4d442018-09-19 15:49:50 -07002991 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]");
2992 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002993 pw.println(" [--preload] [--instantapp] [--full] [--dont-kill]");
MÃ¥rten Kongstad2a5989342018-11-16 15:04:44 +01002994 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [--apex] [-S BYTES]");
Dario Freniaac4ba42018-12-06 15:47:16 +00002995 pw.println(" [--multi-package] [--staged]");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07002996 pw.println(" Like \"install\", but starts an install session. Use \"install-write\"");
2997 pw.println(" to push data into the session, and \"install-commit\" to finish.");
2998 pw.println("");
2999 pw.println(" install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]");
3000 pw.println(" Write an apk into the given install session. If the path is '-', data");
3001 pw.println(" will be read from stdin. Options are:");
3002 pw.println(" -S: size in bytes of package, required for stdin");
3003 pw.println("");
Patrick Baumann0aff9b12018-11-08 14:05:08 +00003004 pw.println(" install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs");
3005 pw.println(" Add one or more session IDs to a multi-package session.");
3006 pw.println("");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003007 pw.println(" install-commit SESSION_ID");
3008 pw.println(" Commit the given active install session, installing the app.");
3009 pw.println("");
3010 pw.println(" install-abandon SESSION_ID");
3011 pw.println(" Delete the given active install session.");
3012 pw.println("");
3013 pw.println(" set-install-location LOCATION");
3014 pw.println(" Changes the default install location. NOTE this is only intended for debugging;");
3015 pw.println(" using this can cause applications to break and other undersireable behavior.");
3016 pw.println(" LOCATION is one of:");
3017 pw.println(" 0 [auto]: Let system decide the best location");
3018 pw.println(" 1 [internal]: Install on internal device storage");
3019 pw.println(" 2 [external]: Install on external media");
3020 pw.println("");
3021 pw.println(" get-install-location");
3022 pw.println(" Returns the current install location: 0, 1 or 2 as per set-install-location.");
3023 pw.println("");
3024 pw.println(" move-package PACKAGE [internal|UUID]");
3025 pw.println("");
3026 pw.println(" move-primary-storage [internal|UUID]");
3027 pw.println("");
3028 pw.println(" pm uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE] PACKAGE [SPLIT]");
3029 pw.println(" Remove the given package name from the system. May remove an entire app");
3030 pw.println(" if no SPLIT name is specified, otherwise will remove only the split of the");
3031 pw.println(" given app. Options are:");
3032 pw.println(" -k: keep the data and cache directories around after package removal.");
3033 pw.println(" --user: remove the app from the given user.");
3034 pw.println(" --versionCode: only uninstall if the app has the given version code.");
3035 pw.println("");
3036 pw.println(" clear [--user USER_ID] PACKAGE");
3037 pw.println(" Deletes all data associated with a package.");
3038 pw.println("");
3039 pw.println(" enable [--user USER_ID] PACKAGE_OR_COMPONENT");
3040 pw.println(" disable [--user USER_ID] PACKAGE_OR_COMPONENT");
3041 pw.println(" disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
3042 pw.println(" disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
3043 pw.println(" default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
3044 pw.println(" These commands change the enabled state of a given package or");
3045 pw.println(" component (written as \"package/class\").");
3046 pw.println("");
3047 pw.println(" hide [--user USER_ID] PACKAGE_OR_COMPONENT");
3048 pw.println(" unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
3049 pw.println("");
3050 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE");
3051 pw.println(" Suspends the specified package (as user).");
3052 pw.println("");
3053 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE");
3054 pw.println(" Unsuspends the specified package (as user).");
3055 pw.println("");
3056 pw.println(" grant [--user USER_ID] PACKAGE PERMISSION");
3057 pw.println(" revoke [--user USER_ID] PACKAGE PERMISSION");
3058 pw.println(" These commands either grant or revoke permissions to apps. The permissions");
3059 pw.println(" must be declared as used in the app's manifest, be runtime permissions");
3060 pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
3061 pw.println("");
3062 pw.println(" reset-permissions");
3063 pw.println(" Revert all runtime permissions to their default state.");
3064 pw.println("");
3065 pw.println(" set-permission-enforced PERMISSION [true|false]");
3066 pw.println("");
3067 pw.println(" get-privapp-permissions TARGET-PACKAGE");
3068 pw.println(" Prints all privileged permissions for a package.");
3069 pw.println("");
3070 pw.println(" get-privapp-deny-permissions TARGET-PACKAGE");
3071 pw.println(" Prints all privileged permissions that are denied for a package.");
3072 pw.println("");
3073 pw.println(" get-oem-permissions TARGET-PACKAGE");
3074 pw.println(" Prints all OEM permissions for a package.");
3075 pw.println("");
3076 pw.println(" set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
3077 pw.println(" get-app-link [--user USER_ID] PACKAGE");
3078 pw.println("");
3079 pw.println(" trim-caches DESIRED_FREE_SPACE [internal|UUID]");
3080 pw.println(" Trim cache files to reach the given free space.");
3081 pw.println("");
3082 pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
3083 pw.println(" [--guest] USER_NAME");
3084 pw.println(" Create a new user with the given USER_NAME, printing the new user identifier");
3085 pw.println(" of the user.");
3086 pw.println("");
3087 pw.println(" remove-user USER_ID");
3088 pw.println(" Remove the user with the given USER_IDENTIFIER, deleting all data");
3089 pw.println(" associated with that user");
3090 pw.println("");
3091 pw.println(" set-user-restriction [--user USER_ID] RESTRICTION VALUE");
3092 pw.println("");
3093 pw.println(" get-max-users");
3094 pw.println("");
Alex Chauc12189b2018-01-16 15:01:15 +00003095 pw.println(" get-max-running-users");
3096 pw.println("");
Calin Juravleb6f844d2017-07-17 15:23:21 -07003097 pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
Richard Uhler568a9692016-05-03 16:02:52 -07003098 pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003099 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\". Options are:");
David Brazdil990fb6b2016-03-01 10:02:27 +00003100 pw.println(" -a: compile all packages");
David Brazdil9aa6db02016-03-08 12:57:12 +00003101 pw.println(" -c: clear profile data before compiling");
3102 pw.println(" -f: force compilation even if not needed");
David Brazdil493411a2016-02-01 13:48:46 +00003103 pw.println(" -m: select compilation mode");
Richard Uhler568a9692016-05-03 16:02:52 -07003104 pw.println(" MODE is one of the dex2oat compiler filters:");
Nicolas Geoffrayd1326522017-04-25 12:29:07 +01003105 pw.println(" assume-verified");
3106 pw.println(" extract");
3107 pw.println(" verify");
3108 pw.println(" quicken");
Richard Uhler568a9692016-05-03 16:02:52 -07003109 pw.println(" space-profile");
3110 pw.println(" space");
3111 pw.println(" speed-profile");
3112 pw.println(" speed");
3113 pw.println(" everything");
3114 pw.println(" -r: select compilation reason");
3115 pw.println(" REASON is one of:");
3116 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
3117 pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
3118 }
David Brazdilcf046952016-03-08 16:40:20 +00003119 pw.println(" --reset: restore package to its post-install state");
Richard Uhler568a9692016-05-03 16:02:52 -07003120 pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
Calin Juravlecb5f41e2017-01-25 17:16:08 -08003121 pw.println(" --secondary-dex: compile app secondary dex files");
Calin Juravleb6f844d2017-07-17 15:23:21 -07003122 pw.println(" --split SPLIT: compile only the given split name");
Eric Holka1485f62019-01-07 13:58:25 -08003123 pw.println(" --compile-layouts: compile layout resources for faster inflation");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003124 pw.println("");
3125 pw.println(" force-dex-opt PACKAGE");
3126 pw.println(" Force immediate execution of dex opt for the given PACKAGE.");
3127 pw.println("");
Calin Juravlecb5f41e2017-01-25 17:16:08 -08003128 pw.println(" bg-dexopt-job");
3129 pw.println(" Execute the background optimizations immediately.");
3130 pw.println(" Note that the command only runs the background optimizer logic. It may");
3131 pw.println(" overlap with the actual job but the job scheduler will not be able to");
3132 pw.println(" cancel it. It will also run even if the device is not in the idle");
3133 pw.println(" maintenance mode.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003134 pw.println("");
Calin Juravle1aa5f882017-01-25 01:05:50 -08003135 pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE");
3136 pw.println(" Reconciles the package secondary dex files with the generated oat files.");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003137 pw.println("");
David Sehrcae13b02016-06-07 09:11:27 -07003138 pw.println(" dump-profiles TARGET-PACKAGE");
3139 pw.println(" Dumps method/class profile files to");
Calin Juravle21216c62018-05-04 17:35:29 -07003140 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + "TARGET-PACKAGE.txt");
3141 pw.println("");
3142 pw.println(" snapshot-profile TARGET-PACKAGE [--code-path path]");
3143 pw.println(" Take a snapshot of the package profiles to");
3144 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION
3145 + "TARGET-PACKAGE[-code-path].prof");
3146 pw.println(" If TARGET-PACKAGE=android it will take a snapshot of the boot image");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003147 pw.println("");
Makoto Onuki4828a592016-03-15 18:06:57 -07003148 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
Dianne Hackbornc81983a2017-10-20 16:16:32 -07003149 pw.println(" Set the default home activity (aka launcher).");
3150 pw.println("");
3151 pw.println(" set-installer PACKAGE INSTALLER");
3152 pw.println(" Set installer package name");
3153 pw.println("");
3154 pw.println(" get-instantapp-resolver");
3155 pw.println(" Return the name of the component that is the current instant app installer.");
Ben Gruver1ab3d6e2017-12-07 13:45:08 -08003156 pw.println("");
3157 pw.println(" set-harmful-app-warning [--user <USER_ID>] <PACKAGE> [<WARNING>]");
3158 pw.println(" Mark the app as harmful with the given warning message.");
Ben Gruver9ef60092018-01-10 11:32:30 -08003159 pw.println("");
3160 pw.println(" get-harmful-app-warning [--user <USER_ID>] <PACKAGE>");
3161 pw.println(" Return the harmful app warning message for the given app, if present");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08003162 pw.println();
Patrick Baumanna980e142018-02-12 11:45:23 -08003163 pw.println(" uninstall-system-updates");
3164 pw.println(" Remove updates to all system applications and fall back to their /system " +
3165 "version.");
3166 pw.println();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08003167 Intent.printIntentArgsHelp(pw , "");
Todd Kennedy60459ab2015-10-30 11:32:16 -07003168 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003169
3170 private static class LocalIntentReceiver {
wangmingming155414292018-04-10 09:35:25 +08003171 private final LinkedBlockingQueue<Intent> mResult = new LinkedBlockingQueue<>();
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003172
3173 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
3174 @Override
Dianne Hackborn98305522017-05-05 17:53:53 -07003175 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003176 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
3177 try {
3178 mResult.offer(intent, 5, TimeUnit.SECONDS);
3179 } catch (InterruptedException e) {
3180 throw new RuntimeException(e);
3181 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08003182 }
3183 };
3184
3185 public IntentSender getIntentSender() {
3186 return new IntentSender((IIntentSender) mLocalSender);
3187 }
3188
3189 public Intent getResult() {
3190 try {
3191 return mResult.take();
3192 } catch (InterruptedException e) {
3193 throw new RuntimeException(e);
3194 }
3195 }
3196 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07003197}