blob: 1203e4d58c004647ae41255cfdaded1dcc76c1a0 [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
Todd Kennedy72cfcd02015-11-03 17:08:55 -080019import android.app.ActivityManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -070020import android.content.ComponentName;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080021import android.content.IIntentReceiver;
22import android.content.IIntentSender;
23import android.content.Intent;
24import android.content.IntentSender;
Todd Kennedy60459ab2015-10-30 11:32:16 -070025import android.content.pm.ApplicationInfo;
26import android.content.pm.FeatureInfo;
27import android.content.pm.IPackageManager;
28import android.content.pm.InstrumentationInfo;
29import android.content.pm.PackageInfo;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080030import android.content.pm.PackageInstaller;
Todd Kennedy60459ab2015-10-30 11:32:16 -070031import android.content.pm.PackageItemInfo;
32import android.content.pm.PackageManager;
Shunta Sato4f26cb52016-06-28 09:29:19 +090033import android.content.pm.PackageParser;
34import android.content.pm.PackageParser.ApkLite;
35import android.content.pm.PackageParser.PackageLite;
36import android.content.pm.PackageParser.PackageParserException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070037import android.content.pm.ParceledListSlice;
38import android.content.pm.PermissionGroupInfo;
39import android.content.pm.PermissionInfo;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080040import android.content.pm.PackageInstaller.SessionInfo;
41import android.content.pm.PackageInstaller.SessionParams;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080042import android.content.pm.ResolveInfo;
Svet Ganov67882122016-12-11 16:36:34 -080043import android.content.pm.VersionedPackage;
Todd Kennedy60459ab2015-10-30 11:32:16 -070044import android.content.res.AssetManager;
45import android.content.res.Resources;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080046import android.net.Uri;
47import android.os.Binder;
48import android.os.Build;
49import android.os.Bundle;
Todd Kennedy60459ab2015-10-30 11:32:16 -070050import android.os.RemoteException;
51import android.os.ShellCommand;
Calin Juravle8bc758b2016-03-28 12:31:52 +010052import android.os.SystemProperties;
Todd Kennedy60459ab2015-10-30 11:32:16 -070053import android.os.UserHandle;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080054import android.text.TextUtils;
Fyodor Kupolov51245c72016-12-01 11:34:10 -080055import android.util.ArraySet;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080056import android.util.PrintWriterPrinter;
Shunta Sato4f26cb52016-06-28 09:29:19 +090057import com.android.internal.content.PackageHelper;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080058import com.android.internal.util.SizedInputStream;
Fyodor Kupolov51245c72016-12-01 11:34:10 -080059import com.android.server.SystemConfig;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080060
Andreas Gampebdd30d82016-03-20 11:32:11 -070061import dalvik.system.DexFile;
62
Todd Kennedy72cfcd02015-11-03 17:08:55 -080063import libcore.io.IoUtils;
64
65import java.io.File;
66import java.io.FileInputStream;
67import java.io.IOException;
68import java.io.InputStream;
69import java.io.OutputStream;
Todd Kennedy60459ab2015-10-30 11:32:16 -070070import java.io.PrintWriter;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080071import java.net.URISyntaxException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070072import java.util.ArrayList;
73import java.util.Collections;
74import java.util.Comparator;
75import java.util.List;
76import java.util.WeakHashMap;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080077import java.util.concurrent.SynchronousQueue;
78import java.util.concurrent.TimeUnit;
Todd Kennedy60459ab2015-10-30 11:32:16 -070079
80class PackageManagerShellCommand extends ShellCommand {
Todd Kennedy9caf94e2016-10-12 15:26:08 -070081 /** Path for streaming APK content */
82 private static final String STDIN_PATH = "-";
83 /** Whether or not APK content must be streamed from stdin */
84 private static final boolean FORCE_STREAM_INSTALL = true;
85
Todd Kennedy60459ab2015-10-30 11:32:16 -070086 final IPackageManager mInterface;
87 final private WeakHashMap<String, Resources> mResourceCache =
88 new WeakHashMap<String, Resources>();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080089 int mTargetUser;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -070090 boolean mBrief;
91 boolean mComponents;
Todd Kennedy60459ab2015-10-30 11:32:16 -070092
93 PackageManagerShellCommand(PackageManagerService service) {
94 mInterface = service;
95 }
96
97 @Override
98 public int onCommand(String cmd) {
99 if (cmd == null) {
100 return handleDefaultCommands(cmd);
101 }
102
103 final PrintWriter pw = getOutPrintWriter();
104 try {
105 switch(cmd) {
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800106 case "install":
107 return runInstall();
108 case "install-abandon":
109 case "install-destroy":
110 return runInstallAbandon();
111 case "install-commit":
112 return runInstallCommit();
113 case "install-create":
114 return runInstallCreate();
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800115 case "install-remove":
116 return runInstallRemove();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800117 case "install-write":
118 return runInstallWrite();
David Brazdil493411a2016-02-01 13:48:46 +0000119 case "compile":
120 return runCompile();
Calin Juravle1aa5f882017-01-25 01:05:50 -0800121 case "reconcile-secondary-dex-files":
122 return runreconcileSecondaryDexFiles();
Calin Juravlecb5f41e2017-01-25 17:16:08 -0800123 case "bg-dexopt-job":
124 return runDexoptJob();
David Sehra8777082016-05-24 15:25:23 -0700125 case "dump-profiles":
126 return runDumpProfiles();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700127 case "list":
128 return runList();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800129 case "uninstall":
130 return runUninstall();
Dianne Hackborn99878e92015-12-02 16:27:41 -0800131 case "resolve-activity":
132 return runResolveActivity();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800133 case "query-activities":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800134 return runQueryIntentActivities();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800135 case "query-services":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800136 return runQueryIntentServices();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800137 case "query-receivers":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800138 return runQueryIntentReceivers();
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000139 case "suspend":
140 return runSuspend(true);
141 case "unsuspend":
142 return runSuspend(false);
Makoto Onuki4828a592016-03-15 18:06:57 -0700143 case "set-home-activity":
144 return runSetHomeActivity();
Fyodor Kupolov51245c72016-12-01 11:34:10 -0800145 case "get-privapp-permissions":
146 return runGetPrivappPermissions();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700147 default:
148 return handleDefaultCommands(cmd);
149 }
150 } catch (RemoteException e) {
151 pw.println("Remote exception: " + e);
152 }
153 return -1;
154 }
155
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700156 private void setParamsSize(InstallParams params, String inPath) {
157 // If we're forced to stream the package, the params size
158 // must be set via command-line argument. There's nothing
159 // to do here.
160 if (FORCE_STREAM_INSTALL) {
161 return;
162 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800163 final PrintWriter pw = getOutPrintWriter();
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700164 if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900165 File file = new File(inPath);
166 if (file.isFile()) {
167 try {
168 ApkLite baseApk = PackageParser.parseApkLite(file, 0);
Adam Lesinski4e862812016-11-21 16:02:24 -0800169 PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null);
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700170 params.sessionParams.setSize(PackageHelper.calculateInstalledSize(
171 pkgLite, false, params.sessionParams.abiOverride));
Shunta Sato4f26cb52016-06-28 09:29:19 +0900172 } catch (PackageParserException | IOException e) {
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700173 pw.println("Error: Failed to parse APK file: " + file);
174 throw new IllegalArgumentException(
175 "Error: Failed to parse APK file: " + file, e);
Shunta Sato4f26cb52016-06-28 09:29:19 +0900176 }
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700177 } else {
178 pw.println("Error: Can't open non-file: " + inPath);
179 throw new IllegalArgumentException("Error: Can't open non-file: " + inPath);
Shunta Sato4f26cb52016-06-28 09:29:19 +0900180 }
181 }
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700182 }
Shunta Sato4f26cb52016-06-28 09:29:19 +0900183
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700184 private int runInstall() throws RemoteException {
185 final PrintWriter pw = getOutPrintWriter();
186 final InstallParams params = makeInstallParams();
187 final String inPath = getNextArg();
188
189 setParamsSize(params, inPath);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800190 final int sessionId = doCreateSession(params.sessionParams,
191 params.installerPackageName, params.userId);
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800192 boolean abandonSession = true;
193 try {
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700194 if (inPath == null && params.sessionParams.sizeBytes == -1) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800195 pw.println("Error: must either specify a package size or an APK file");
196 return 1;
197 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800198 if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800199 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
200 return 1;
201 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800202 if (doCommitSession(sessionId, false /*logSuccess*/)
203 != PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800204 return 1;
205 }
206 abandonSession = false;
Todd Kennedy50ea35f2015-12-17 14:46:39 -0800207 pw.println("Success");
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800208 return 0;
209 } finally {
210 if (abandonSession) {
211 try {
212 doAbandonSession(sessionId, false /*logSuccess*/);
213 } catch (Exception ignore) {
214 }
215 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800216 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800217 }
218
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000219 private int runSuspend(boolean suspendedState) {
220 final PrintWriter pw = getOutPrintWriter();
221 int userId = UserHandle.USER_SYSTEM;
222 String opt;
223 while ((opt = getNextOption()) != null) {
224 switch (opt) {
225 case "--user":
226 userId = UserHandle.parseUserArg(getNextArgRequired());
227 break;
228 default:
229 pw.println("Error: Unknown option: " + opt);
230 return 1;
231 }
232 }
233
234 String packageName = getNextArg();
235 if (packageName == null) {
236 pw.println("Error: package name not specified");
237 return 1;
238 }
239
240 try {
Andrei Stingaceanueb84b182016-01-26 18:39:55 +0000241 mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
242 userId);
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000243 pw.println("Package " + packageName + " new suspended state: "
Andrei Stingaceanu355b2322016-02-12 16:43:51 +0000244 + mInterface.isPackageSuspendedForUser(packageName, userId));
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000245 return 0;
Andrei Stingaceanuefc4a342016-03-22 14:43:01 +0000246 } catch (RemoteException | IllegalArgumentException e) {
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000247 pw.println(e.toString());
248 return 1;
249 }
250 }
251
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800252 private int runInstallAbandon() throws RemoteException {
253 final int sessionId = Integer.parseInt(getNextArg());
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800254 return doAbandonSession(sessionId, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800255 }
256
257 private int runInstallCommit() throws RemoteException {
258 final int sessionId = Integer.parseInt(getNextArg());
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800259 return doCommitSession(sessionId, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800260 }
261
262 private int runInstallCreate() throws RemoteException {
263 final PrintWriter pw = getOutPrintWriter();
264 final InstallParams installParams = makeInstallParams();
265 final int sessionId = doCreateSession(installParams.sessionParams,
266 installParams.installerPackageName, installParams.userId);
267
268 // NOTE: adb depends on parsing this string
269 pw.println("Success: created install session [" + sessionId + "]");
270 return 0;
271 }
272
273 private int runInstallWrite() throws RemoteException {
274 long sizeBytes = -1;
275
276 String opt;
277 while ((opt = getNextOption()) != null) {
278 if (opt.equals("-S")) {
279 sizeBytes = Long.parseLong(getNextArg());
280 } else {
281 throw new IllegalArgumentException("Unknown option: " + opt);
282 }
283 }
284
285 final int sessionId = Integer.parseInt(getNextArg());
286 final String splitName = getNextArg();
287 final String path = getNextArg();
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800288 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
289 }
290
291 private int runInstallRemove() throws RemoteException {
292 final PrintWriter pw = getOutPrintWriter();
293
294 final int sessionId = Integer.parseInt(getNextArg());
295
296 final String splitName = getNextArg();
297 if (splitName == null) {
298 pw.println("Error: split name not specified");
299 return 1;
300 }
301 return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800302 }
303
David Brazdil493411a2016-02-01 13:48:46 +0000304 private int runCompile() throws RemoteException {
305 final PrintWriter pw = getOutPrintWriter();
Calin Juravle8bc758b2016-03-28 12:31:52 +0100306 boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
David Brazdil493411a2016-02-01 13:48:46 +0000307 boolean forceCompilation = false;
David Brazdil990fb6b2016-03-01 10:02:27 +0000308 boolean allPackages = false;
David Brazdil9aa6db02016-03-08 12:57:12 +0000309 boolean clearProfileData = false;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700310 String compilerFilter = null;
311 String compilationReason = null;
Calin Juravle8bc758b2016-03-28 12:31:52 +0100312 String checkProfilesRaw = null;
Calin Juravlec22c30e2017-01-16 19:18:48 -0800313 boolean secondaryDex = false;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700314
David Brazdil493411a2016-02-01 13:48:46 +0000315 String opt;
316 while ((opt = getNextOption()) != null) {
317 switch (opt) {
David Brazdil990fb6b2016-03-01 10:02:27 +0000318 case "-a":
319 allPackages = true;
320 break;
David Brazdil9aa6db02016-03-08 12:57:12 +0000321 case "-c":
322 clearProfileData = true;
David Brazdil493411a2016-02-01 13:48:46 +0000323 break;
324 case "-f":
325 forceCompilation = true;
326 break;
David Brazdil9aa6db02016-03-08 12:57:12 +0000327 case "-m":
Andreas Gampebdd30d82016-03-20 11:32:11 -0700328 compilerFilter = getNextArgRequired();
329 break;
330 case "-r":
331 compilationReason = getNextArgRequired();
David Brazdil9aa6db02016-03-08 12:57:12 +0000332 break;
Richard Uhler568a9692016-05-03 16:02:52 -0700333 case "--check-prof":
Calin Juravle8bc758b2016-03-28 12:31:52 +0100334 checkProfilesRaw = getNextArgRequired();
335 break;
David Brazdil9aa6db02016-03-08 12:57:12 +0000336 case "--reset":
337 forceCompilation = true;
338 clearProfileData = true;
Richard Uhler5f201e62016-05-11 13:38:27 -0700339 compilationReason = "install";
David Brazdil9aa6db02016-03-08 12:57:12 +0000340 break;
Calin Juravlec22c30e2017-01-16 19:18:48 -0800341 case "--secondary-dex":
342 secondaryDex = true;
343 break;
David Brazdil493411a2016-02-01 13:48:46 +0000344 default:
345 pw.println("Error: Unknown option: " + opt);
346 return 1;
347 }
348 }
349
Calin Juravle8bc758b2016-03-28 12:31:52 +0100350 if (checkProfilesRaw != null) {
351 if ("true".equals(checkProfilesRaw)) {
352 checkProfiles = true;
353 } else if ("false".equals(checkProfilesRaw)) {
354 checkProfiles = false;
355 } else {
356 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
357 return 1;
358 }
359 }
360
Andreas Gampebdd30d82016-03-20 11:32:11 -0700361 if (compilerFilter != null && compilationReason != null) {
362 pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " +
363 "at the same time");
364 return 1;
David Brazdil493411a2016-02-01 13:48:46 +0000365 }
Andreas Gampebdd30d82016-03-20 11:32:11 -0700366 if (compilerFilter == null && compilationReason == null) {
367 pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " +
368 "reason (\"-r\") at the same time");
369 return 1;
370 }
371
372 String targetCompilerFilter;
373 if (compilerFilter != null) {
Richard Uhler568a9692016-05-03 16:02:52 -0700374 if (!DexFile.isValidCompilerFilter(compilerFilter)) {
375 pw.println("Error: \"" + compilerFilter +
376 "\" is not a valid compilation filter.");
377 return 1;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700378 }
Richard Uhler568a9692016-05-03 16:02:52 -0700379 targetCompilerFilter = compilerFilter;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700380 } else {
381 int reason = -1;
382 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
383 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
384 compilationReason)) {
385 reason = i;
386 break;
387 }
388 }
389 if (reason == -1) {
390 pw.println("Error: Unknown compilation reason: " + compilationReason);
391 return 1;
392 }
393 targetCompilerFilter =
394 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
395 }
396
David Brazdil493411a2016-02-01 13:48:46 +0000397
David Brazdil990fb6b2016-03-01 10:02:27 +0000398 List<String> packageNames = null;
399 if (allPackages) {
400 packageNames = mInterface.getAllPackages();
401 } else {
402 String packageName = getNextArg();
403 if (packageName == null) {
404 pw.println("Error: package name not specified");
405 return 1;
406 }
407 packageNames = Collections.singletonList(packageName);
David Brazdil493411a2016-02-01 13:48:46 +0000408 }
409
David Brazdil990fb6b2016-03-01 10:02:27 +0000410 List<String> failedPackages = new ArrayList<>();
411 for (String packageName : packageNames) {
David Brazdil9aa6db02016-03-08 12:57:12 +0000412 if (clearProfileData) {
413 mInterface.clearApplicationProfileData(packageName);
414 }
415
Calin Juravlec22c30e2017-01-16 19:18:48 -0800416 boolean result = secondaryDex
417 ? mInterface.performDexOptSecondary(packageName,
418 targetCompilerFilter, forceCompilation)
419 : mInterface.performDexOptMode(packageName,
420 checkProfiles, targetCompilerFilter, forceCompilation);
David Brazdil990fb6b2016-03-01 10:02:27 +0000421 if (!result) {
422 failedPackages.add(packageName);
423 }
424 }
425
426 if (failedPackages.isEmpty()) {
David Brazdil493411a2016-02-01 13:48:46 +0000427 pw.println("Success");
428 return 0;
David Brazdil990fb6b2016-03-01 10:02:27 +0000429 } else if (failedPackages.size() == 1) {
430 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
431 return 1;
David Brazdil493411a2016-02-01 13:48:46 +0000432 } else {
David Brazdil990fb6b2016-03-01 10:02:27 +0000433 pw.print("Failure: the following packages could not be compiled: ");
434 boolean is_first = true;
435 for (String packageName : failedPackages) {
436 if (is_first) {
437 is_first = false;
438 } else {
439 pw.print(", ");
440 }
441 pw.print(packageName);
442 }
443 pw.println();
David Brazdil493411a2016-02-01 13:48:46 +0000444 return 1;
445 }
446 }
447
Calin Juravle1aa5f882017-01-25 01:05:50 -0800448 private int runreconcileSecondaryDexFiles() throws RemoteException {
449 String packageName = getNextArg();
450 mInterface.reconcileSecondaryDexFiles(packageName);
451 return 0;
452 }
453
Calin Juravlecb5f41e2017-01-25 17:16:08 -0800454 private int runDexoptJob() throws RemoteException {
455 boolean result = mInterface.runBackgroundDexoptJob();
456 return result ? 0 : -1;
457 }
458
David Sehra8777082016-05-24 15:25:23 -0700459 private int runDumpProfiles() throws RemoteException {
460 String packageName = getNextArg();
461 mInterface.dumpProfiles(packageName);
462 return 0;
463 }
464
Todd Kennedy60459ab2015-10-30 11:32:16 -0700465 private int runList() throws RemoteException {
466 final PrintWriter pw = getOutPrintWriter();
467 final String type = getNextArg();
468 if (type == null) {
469 pw.println("Error: didn't specify type of data to list");
470 return -1;
471 }
472 switch(type) {
473 case "features":
474 return runListFeatures();
475 case "instrumentation":
476 return runListInstrumentation();
477 case "libraries":
478 return runListLibraries();
479 case "package":
480 case "packages":
481 return runListPackages(false /*showSourceDir*/);
482 case "permission-groups":
483 return runListPermissionGroups();
484 case "permissions":
485 return runListPermissions();
486 }
487 pw.println("Error: unknown list type '" + type + "'");
488 return -1;
489 }
490
491 private int runListFeatures() throws RemoteException {
492 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700493 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700494
495 // sort by name
496 Collections.sort(list, new Comparator<FeatureInfo>() {
497 public int compare(FeatureInfo o1, FeatureInfo o2) {
498 if (o1.name == o2.name) return 0;
499 if (o1.name == null) return -1;
500 if (o2.name == null) return 1;
501 return o1.name.compareTo(o2.name);
502 }
503 });
504
505 final int count = (list != null) ? list.size() : 0;
506 for (int p = 0; p < count; p++) {
507 FeatureInfo fi = list.get(p);
508 pw.print("feature:");
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700509 if (fi.name != null) {
510 pw.print(fi.name);
511 if (fi.version > 0) {
512 pw.print("=");
513 pw.print(fi.version);
514 }
515 pw.println();
516 } else {
517 pw.println("reqGlEsVersion=0x"
Todd Kennedy60459ab2015-10-30 11:32:16 -0700518 + Integer.toHexString(fi.reqGlEsVersion));
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700519 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700520 }
521 return 0;
522 }
523
524 private int runListInstrumentation() throws RemoteException {
525 final PrintWriter pw = getOutPrintWriter();
526 boolean showSourceDir = false;
527 String targetPackage = null;
528
529 try {
530 String opt;
531 while ((opt = getNextArg()) != null) {
532 switch (opt) {
533 case "-f":
534 showSourceDir = true;
535 break;
536 default:
537 if (opt.charAt(0) != '-') {
538 targetPackage = opt;
539 } else {
540 pw.println("Error: Unknown option: " + opt);
541 return -1;
542 }
543 break;
544 }
545 }
546 } catch (RuntimeException ex) {
547 pw.println("Error: " + ex.toString());
548 return -1;
549 }
550
551 final List<InstrumentationInfo> list =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700552 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700553
554 // sort by target package
555 Collections.sort(list, new Comparator<InstrumentationInfo>() {
556 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
557 return o1.targetPackage.compareTo(o2.targetPackage);
558 }
559 });
560
561 final int count = (list != null) ? list.size() : 0;
562 for (int p = 0; p < count; p++) {
563 final InstrumentationInfo ii = list.get(p);
564 pw.print("instrumentation:");
565 if (showSourceDir) {
566 pw.print(ii.sourceDir);
567 pw.print("=");
568 }
569 final ComponentName cn = new ComponentName(ii.packageName, ii.name);
570 pw.print(cn.flattenToShortString());
571 pw.print(" (target=");
572 pw.print(ii.targetPackage);
573 pw.println(")");
574 }
575 return 0;
576 }
577
578 private int runListLibraries() throws RemoteException {
579 final PrintWriter pw = getOutPrintWriter();
580 final List<String> list = new ArrayList<String>();
581 final String[] rawList = mInterface.getSystemSharedLibraryNames();
582 for (int i = 0; i < rawList.length; i++) {
583 list.add(rawList[i]);
584 }
585
586 // sort by name
587 Collections.sort(list, new Comparator<String>() {
588 public int compare(String o1, String o2) {
589 if (o1 == o2) return 0;
590 if (o1 == null) return -1;
591 if (o2 == null) return 1;
592 return o1.compareTo(o2);
593 }
594 });
595
596 final int count = (list != null) ? list.size() : 0;
597 for (int p = 0; p < count; p++) {
598 String lib = list.get(p);
599 pw.print("library:");
600 pw.println(lib);
601 }
602 return 0;
603 }
604
605 private int runListPackages(boolean showSourceDir) throws RemoteException {
606 final PrintWriter pw = getOutPrintWriter();
607 int getFlags = 0;
608 boolean listDisabled = false, listEnabled = false;
609 boolean listSystem = false, listThirdParty = false;
610 boolean listInstaller = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700611 boolean showUid = false;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800612 boolean showVersionCode = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700613 int uid = -1;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700614 int userId = UserHandle.USER_SYSTEM;
615 try {
616 String opt;
617 while ((opt = getNextOption()) != null) {
618 switch (opt) {
619 case "-d":
620 listDisabled = true;
621 break;
622 case "-e":
623 listEnabled = true;
624 break;
625 case "-f":
626 showSourceDir = true;
627 break;
628 case "-i":
629 listInstaller = true;
630 break;
631 case "-l":
632 // old compat
633 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700634 case "-s":
635 listSystem = true;
636 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700637 case "-U":
638 showUid = true;
639 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700640 case "-u":
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700641 getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700642 break;
643 case "-3":
644 listThirdParty = true;
645 break;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800646 case "--show-versioncode":
647 showVersionCode = true;
648 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700649 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800650 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy60459ab2015-10-30 11:32:16 -0700651 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700652 case "--uid":
653 showUid = true;
654 uid = Integer.parseInt(getNextArgRequired());
655 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700656 default:
657 pw.println("Error: Unknown option: " + opt);
658 return -1;
659 }
660 }
661 } catch (RuntimeException ex) {
662 pw.println("Error: " + ex.toString());
663 return -1;
664 }
665
666 final String filter = getNextArg();
667
668 @SuppressWarnings("unchecked")
669 final ParceledListSlice<PackageInfo> slice =
670 mInterface.getInstalledPackages(getFlags, userId);
671 final List<PackageInfo> packages = slice.getList();
672
673 final int count = packages.size();
674 for (int p = 0; p < count; p++) {
675 final PackageInfo info = packages.get(p);
676 if (filter != null && !info.packageName.contains(filter)) {
677 continue;
678 }
Felipe Lemeeece9862016-06-29 11:45:03 -0700679 if (uid != -1 && info.applicationInfo.uid != uid) {
680 continue;
681 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700682 final boolean isSystem =
683 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
684 if ((!listDisabled || !info.applicationInfo.enabled) &&
685 (!listEnabled || info.applicationInfo.enabled) &&
686 (!listSystem || isSystem) &&
687 (!listThirdParty || !isSystem)) {
688 pw.print("package:");
689 if (showSourceDir) {
690 pw.print(info.applicationInfo.sourceDir);
691 pw.print("=");
692 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800693 pw.print(info.packageName);
694 if (showVersionCode) {
695 pw.print(" versionCode:");
696 pw.print(info.applicationInfo.versionCode);
697 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700698 if (listInstaller) {
699 pw.print(" installer=");
700 pw.print(mInterface.getInstallerPackageName(info.packageName));
701 }
Felipe Lemeeece9862016-06-29 11:45:03 -0700702 if (showUid) {
703 pw.print(" uid:");
704 pw.print(info.applicationInfo.uid);
705 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700706 pw.println();
707 }
708 }
709 return 0;
710 }
711
712 private int runListPermissionGroups() throws RemoteException {
713 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700714 final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700715
716 final int count = pgs.size();
717 for (int p = 0; p < count ; p++) {
718 final PermissionGroupInfo pgi = pgs.get(p);
719 pw.print("permission group:");
720 pw.println(pgi.name);
721 }
722 return 0;
723 }
724
725 private int runListPermissions() throws RemoteException {
726 final PrintWriter pw = getOutPrintWriter();
727 boolean labels = false;
728 boolean groups = false;
729 boolean userOnly = false;
730 boolean summary = false;
731 boolean dangerousOnly = false;
732 String opt;
733 while ((opt = getNextOption()) != null) {
734 switch (opt) {
735 case "-d":
736 dangerousOnly = true;
737 break;
738 case "-f":
739 labels = true;
740 break;
741 case "-g":
742 groups = true;
743 break;
744 case "-s":
745 groups = true;
746 labels = true;
747 summary = true;
748 break;
749 case "-u":
750 userOnly = true;
751 break;
752 default:
753 pw.println("Error: Unknown option: " + opt);
754 return 1;
755 }
756 }
757
758 final ArrayList<String> groupList = new ArrayList<String>();
759 if (groups) {
760 final List<PermissionGroupInfo> infos =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700761 mInterface.getAllPermissionGroups(0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700762 final int count = infos.size();
763 for (int i = 0; i < count; i++) {
764 groupList.add(infos.get(i).name);
765 }
766 groupList.add(null);
767 } else {
768 final String grp = getNextArg();
769 groupList.add(grp);
770 }
771
772 if (dangerousOnly) {
773 pw.println("Dangerous Permissions:");
774 pw.println("");
775 doListPermissions(groupList, groups, labels, summary,
776 PermissionInfo.PROTECTION_DANGEROUS,
777 PermissionInfo.PROTECTION_DANGEROUS);
778 if (userOnly) {
779 pw.println("Normal Permissions:");
780 pw.println("");
781 doListPermissions(groupList, groups, labels, summary,
782 PermissionInfo.PROTECTION_NORMAL,
783 PermissionInfo.PROTECTION_NORMAL);
784 }
785 } else if (userOnly) {
786 pw.println("Dangerous and Normal Permissions:");
787 pw.println("");
788 doListPermissions(groupList, groups, labels, summary,
789 PermissionInfo.PROTECTION_NORMAL,
790 PermissionInfo.PROTECTION_DANGEROUS);
791 } else {
792 pw.println("All Permissions:");
793 pw.println("");
794 doListPermissions(groupList, groups, labels, summary,
795 -10000, 10000);
796 }
797 return 0;
798 }
799
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800800 private int runUninstall() throws RemoteException {
801 final PrintWriter pw = getOutPrintWriter();
802 int flags = 0;
803 int userId = UserHandle.USER_ALL;
Svet Ganov67882122016-12-11 16:36:34 -0800804 int versionCode = PackageManager.VERSION_CODE_HIGHEST;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800805
806 String opt;
807 while ((opt = getNextOption()) != null) {
808 switch (opt) {
809 case "-k":
810 flags |= PackageManager.DELETE_KEEP_DATA;
811 break;
812 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800813 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800814 break;
Svet Ganov67882122016-12-11 16:36:34 -0800815 case "--versionCode":
816 versionCode = Integer.parseInt(getNextArgRequired());
817 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800818 default:
819 pw.println("Error: Unknown option: " + opt);
820 return 1;
821 }
822 }
823
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800824 final String packageName = getNextArg();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800825 if (packageName == null) {
826 pw.println("Error: package name not specified");
827 return 1;
828 }
829
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800830 // if a split is specified, just remove it and not the whole package
831 final String splitName = getNextArg();
832 if (splitName != null) {
833 return runRemoveSplit(packageName, splitName);
834 }
835
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800836 userId = translateUserId(userId, "runUninstall");
837 if (userId == UserHandle.USER_ALL) {
838 userId = UserHandle.USER_SYSTEM;
839 flags |= PackageManager.DELETE_ALL_USERS;
840 } else {
841 final PackageInfo info = mInterface.getPackageInfo(packageName, 0, userId);
842 if (info == null) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800843 pw.println("Failure [not installed for " + userId + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800844 return 1;
845 }
846 final boolean isSystem =
847 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
848 // If we are being asked to delete a system app for just one
849 // user set flag so it disables rather than reverting to system
850 // version of the app.
851 if (isSystem) {
852 flags |= PackageManager.DELETE_SYSTEM_APP;
853 }
854 }
855
856 final LocalIntentReceiver receiver = new LocalIntentReceiver();
Svet Ganov67882122016-12-11 16:36:34 -0800857 mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
858 versionCode), null /*callerPackageName*/, flags,
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800859 receiver.getIntentSender(), userId);
860
861 final Intent result = receiver.getResult();
862 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
863 PackageInstaller.STATUS_FAILURE);
864 if (status == PackageInstaller.STATUS_SUCCESS) {
865 pw.println("Success");
866 return 0;
867 } else {
868 pw.println("Failure ["
869 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
870 return 1;
871 }
872 }
873
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800874 private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
875 final PrintWriter pw = getOutPrintWriter();
876 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
877 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
878 sessionParams.appPackageName = packageName;
879 final int sessionId =
880 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
881 boolean abandonSession = true;
882 try {
883 if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
884 != PackageInstaller.STATUS_SUCCESS) {
885 return 1;
886 }
887 if (doCommitSession(sessionId, false /*logSuccess*/)
888 != PackageInstaller.STATUS_SUCCESS) {
889 return 1;
890 }
891 abandonSession = false;
892 pw.println("Success");
893 return 0;
894 } finally {
895 if (abandonSession) {
896 try {
897 doAbandonSession(sessionId, false /*logSuccess*/);
898 } catch (Exception ignore) {
899 }
900 }
901 }
902 }
903
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800904 private Intent parseIntentAndUser() throws URISyntaxException {
905 mTargetUser = UserHandle.USER_CURRENT;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700906 mBrief = false;
907 mComponents = false;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800908 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
909 @Override
910 public boolean handleOption(String opt, ShellCommand cmd) {
911 if ("--user".equals(opt)) {
912 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
913 return true;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700914 } else if ("--brief".equals(opt)) {
915 mBrief = true;
916 return true;
917 } else if ("--components".equals(opt)) {
918 mComponents = true;
919 return true;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800920 }
921 return false;
922 }
923 });
924 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
925 Binder.getCallingUid(), mTargetUser, false, false, null, null);
926 return intent;
927 }
928
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700929 private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri,
930 boolean brief, boolean components) {
931 if (brief || components) {
932 final ComponentName comp;
933 if (ri.activityInfo != null) {
934 comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
935 } else if (ri.serviceInfo != null) {
936 comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
937 } else if (ri.providerInfo != null) {
938 comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name);
939 } else {
940 comp = null;
941 }
942 if (comp != null) {
943 if (!components) {
944 pr.println(prefix + "priority=" + ri.priority
945 + " preferredOrder=" + ri.preferredOrder
946 + " match=0x" + Integer.toHexString(ri.match)
947 + " specificIndex=" + ri.specificIndex
948 + " isDefault=" + ri.isDefault);
949 }
950 pr.println(prefix + comp.flattenToShortString());
951 return;
952 }
953 }
954 ri.dump(pr, prefix);
955 }
956
Dianne Hackborn99878e92015-12-02 16:27:41 -0800957 private int runResolveActivity() {
958 Intent intent;
959 try {
960 intent = parseIntentAndUser();
961 } catch (URISyntaxException e) {
962 throw new RuntimeException(e.getMessage(), e);
963 }
964 try {
965 ResolveInfo ri = mInterface.resolveIntent(intent, null, 0, mTargetUser);
966 PrintWriter pw = getOutPrintWriter();
967 if (ri == null) {
968 pw.println("No activity found");
969 } else {
970 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700971 printResolveInfo(pr, "", ri, mBrief, mComponents);
Dianne Hackborn99878e92015-12-02 16:27:41 -0800972 }
973 } catch (RemoteException e) {
974 throw new RuntimeException("Failed calling service", e);
975 }
976 return 0;
977 }
978
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800979 private int runQueryIntentActivities() {
980 Intent intent;
981 try {
982 intent = parseIntentAndUser();
983 } catch (URISyntaxException e) {
984 throw new RuntimeException(e.getMessage(), e);
985 }
986 try {
987 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700988 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800989 PrintWriter pw = getOutPrintWriter();
990 if (result == null || result.size() <= 0) {
991 pw.println("No activities found");
992 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700993 if (!mComponents) {
994 pw.print(result.size()); pw.println(" activities found:");
995 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
996 for (int i = 0; i < result.size(); i++) {
997 pw.print(" Activity #"); pw.print(i); pw.println(":");
998 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
999 }
1000 } else {
1001 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1002 for (int i = 0; i < result.size(); i++) {
1003 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1004 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001005 }
1006 }
1007 } catch (RemoteException e) {
1008 throw new RuntimeException("Failed calling service", e);
1009 }
1010 return 0;
1011 }
1012
1013 private int runQueryIntentServices() {
1014 Intent intent;
1015 try {
1016 intent = parseIntentAndUser();
1017 } catch (URISyntaxException e) {
1018 throw new RuntimeException(e.getMessage(), e);
1019 }
1020 try {
1021 List<ResolveInfo> result = mInterface.queryIntentServices(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -07001022 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001023 PrintWriter pw = getOutPrintWriter();
1024 if (result == null || result.size() <= 0) {
1025 pw.println("No services found");
1026 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001027 if (!mComponents) {
1028 pw.print(result.size()); pw.println(" services found:");
1029 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1030 for (int i = 0; i < result.size(); i++) {
1031 pw.print(" Service #"); pw.print(i); pw.println(":");
1032 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1033 }
1034 } else {
1035 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1036 for (int i = 0; i < result.size(); i++) {
1037 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1038 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001039 }
1040 }
1041 } catch (RemoteException e) {
1042 throw new RuntimeException("Failed calling service", e);
1043 }
1044 return 0;
1045 }
1046
1047 private int runQueryIntentReceivers() {
1048 Intent intent;
1049 try {
1050 intent = parseIntentAndUser();
1051 } catch (URISyntaxException e) {
1052 throw new RuntimeException(e.getMessage(), e);
1053 }
1054 try {
1055 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -07001056 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001057 PrintWriter pw = getOutPrintWriter();
1058 if (result == null || result.size() <= 0) {
1059 pw.println("No receivers found");
1060 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001061 if (!mComponents) {
1062 pw.print(result.size()); pw.println(" receivers found:");
1063 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1064 for (int i = 0; i < result.size(); i++) {
1065 pw.print(" Receiver #"); pw.print(i); pw.println(":");
1066 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1067 }
1068 } else {
1069 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1070 for (int i = 0; i < result.size(); i++) {
1071 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1072 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001073 }
1074 }
1075 } catch (RemoteException e) {
1076 throw new RuntimeException("Failed calling service", e);
1077 }
1078 return 0;
1079 }
1080
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001081 private static class InstallParams {
1082 SessionParams sessionParams;
1083 String installerPackageName;
1084 int userId = UserHandle.USER_ALL;
1085 }
1086
1087 private InstallParams makeInstallParams() {
1088 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
1089 final InstallParams params = new InstallParams();
1090 params.sessionParams = sessionParams;
1091 String opt;
1092 while ((opt = getNextOption()) != null) {
1093 switch (opt) {
1094 case "-l":
1095 sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
1096 break;
1097 case "-r":
1098 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1099 break;
1100 case "-i":
1101 params.installerPackageName = getNextArg();
1102 if (params.installerPackageName == null) {
1103 throw new IllegalArgumentException("Missing installer package");
1104 }
1105 break;
1106 case "-t":
1107 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
1108 break;
1109 case "-s":
1110 sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL;
1111 break;
1112 case "-f":
1113 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
1114 break;
1115 case "-d":
1116 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
1117 break;
1118 case "-g":
1119 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1120 break;
Todd Kennedyb1072712016-04-26 15:41:20 -07001121 case "--dont-kill":
1122 sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
1123 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001124 case "--originating-uri":
1125 sessionParams.originatingUri = Uri.parse(getNextArg());
1126 break;
1127 case "--referrer":
1128 sessionParams.referrerUri = Uri.parse(getNextArg());
1129 break;
1130 case "-p":
1131 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
1132 sessionParams.appPackageName = getNextArg();
1133 if (sessionParams.appPackageName == null) {
1134 throw new IllegalArgumentException("Missing inherit package name");
1135 }
1136 break;
1137 case "-S":
Todd Kennedy9caf94e2016-10-12 15:26:08 -07001138 final long sizeBytes = Long.parseLong(getNextArg());
1139 if (sizeBytes <= 0) {
1140 throw new IllegalArgumentException("Size must be positive");
1141 }
1142 sessionParams.setSize(sizeBytes);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001143 break;
1144 case "--abi":
1145 sessionParams.abiOverride = checkAbiArgument(getNextArg());
1146 break;
Todd Kennedy2699f062015-11-20 13:07:17 -08001147 case "--ephemeral":
Todd Kennedyb7717682016-11-30 15:41:21 -08001148 sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
Todd Kennedy2699f062015-11-20 13:07:17 -08001149 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001150 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001151 params.userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001152 break;
1153 case "--install-location":
1154 sessionParams.installLocation = Integer.parseInt(getNextArg());
1155 break;
1156 case "--force-uuid":
1157 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
1158 sessionParams.volumeUuid = getNextArg();
1159 if ("internal".equals(sessionParams.volumeUuid)) {
1160 sessionParams.volumeUuid = null;
1161 }
1162 break;
Todd Kennedyb1072712016-04-26 15:41:20 -07001163 case "--force-sdk":
1164 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK;
1165 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001166 default:
1167 throw new IllegalArgumentException("Unknown option " + opt);
1168 }
1169 }
1170 return params;
1171 }
1172
Makoto Onuki4828a592016-03-15 18:06:57 -07001173 private int runSetHomeActivity() {
1174 final PrintWriter pw = getOutPrintWriter();
1175 int userId = UserHandle.USER_SYSTEM;
1176 String opt;
1177 while ((opt = getNextOption()) != null) {
1178 switch (opt) {
1179 case "--user":
1180 userId = UserHandle.parseUserArg(getNextArgRequired());
1181 break;
1182 default:
1183 pw.println("Error: Unknown option: " + opt);
1184 return 1;
1185 }
1186 }
1187
1188 String component = getNextArg();
1189 ComponentName componentName =
1190 component != null ? ComponentName.unflattenFromString(component) : null;
1191
1192 if (componentName == null) {
1193 pw.println("Error: component name not specified or invalid");
1194 return 1;
1195 }
1196
1197 try {
1198 mInterface.setHomeActivity(componentName, userId);
Makoto Onuki3bdbf982016-06-23 16:56:35 -07001199 pw.println("Success");
Makoto Onuki4828a592016-03-15 18:06:57 -07001200 return 0;
Makoto Onuki3bdbf982016-06-23 16:56:35 -07001201 } catch (Exception e) {
Makoto Onuki4828a592016-03-15 18:06:57 -07001202 pw.println(e.toString());
1203 return 1;
1204 }
1205 }
1206
Fyodor Kupolov51245c72016-12-01 11:34:10 -08001207 private int runGetPrivappPermissions() {
1208 final String pkg = getNextArg();
1209 if (pkg == null) {
1210 System.err.println("Error: no package specified.");
1211 return 1;
1212 }
1213 ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
1214 getOutPrintWriter().println(privAppPermissions == null
1215 ? "{}" : privAppPermissions.toString());
1216 return 0;
1217 }
1218
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001219 private static String checkAbiArgument(String abi) {
1220 if (TextUtils.isEmpty(abi)) {
1221 throw new IllegalArgumentException("Missing ABI argument");
1222 }
1223
1224 if ("-".equals(abi)) {
1225 return abi;
1226 }
1227
1228 final String[] supportedAbis = Build.SUPPORTED_ABIS;
1229 for (String supportedAbi : supportedAbis) {
1230 if (supportedAbi.equals(abi)) {
1231 return abi;
1232 }
1233 }
1234
1235 throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
1236 }
1237
1238 private int translateUserId(int userId, String logContext) {
1239 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
1240 userId, true, true, logContext, "pm command");
1241 }
1242
1243 private int doCreateSession(SessionParams params, String installerPackageName, int userId)
1244 throws RemoteException {
1245 userId = translateUserId(userId, "runInstallCreate");
1246 if (userId == UserHandle.USER_ALL) {
1247 userId = UserHandle.USER_SYSTEM;
1248 params.installFlags |= PackageManager.INSTALL_ALL_USERS;
1249 }
1250
1251 final int sessionId = mInterface.getPackageInstaller()
1252 .createSession(params, installerPackageName, userId);
1253 return sessionId;
1254 }
1255
Todd Kennedyeb9b0532016-03-08 10:10:54 -08001256 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001257 boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001258 final PrintWriter pw = getOutPrintWriter();
Todd Kennedy9caf94e2016-10-12 15:26:08 -07001259 if (FORCE_STREAM_INSTALL && inPath != null && !STDIN_PATH.equals(inPath)) {
1260 pw.println("Error: APK content must be streamed");
1261 return 1;
1262 }
1263 if (STDIN_PATH.equals(inPath)) {
1264 inPath = null;
1265 } else if (inPath != null) {
1266 final File file = new File(inPath);
1267 if (file.isFile()) {
1268 sizeBytes = file.length();
1269 }
1270 }
Todd Kennedy63cc8b02016-09-22 13:25:46 -07001271 if (sizeBytes <= 0) {
1272 pw.println("Error: must specify a APK size");
1273 return 1;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001274 }
1275
1276 final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId);
1277
1278 PackageInstaller.Session session = null;
1279 InputStream in = null;
1280 OutputStream out = null;
1281 try {
1282 session = new PackageInstaller.Session(
1283 mInterface.getPackageInstaller().openSession(sessionId));
1284
1285 if (inPath != null) {
1286 in = new FileInputStream(inPath);
1287 } else {
Dianne Hackborn2e931f52016-01-28 12:21:17 -08001288 in = new SizedInputStream(getRawInputStream(), sizeBytes);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001289 }
1290 out = session.openWrite(splitName, 0, sizeBytes);
1291
1292 int total = 0;
1293 byte[] buffer = new byte[65536];
1294 int c;
1295 while ((c = in.read(buffer)) != -1) {
1296 total += c;
1297 out.write(buffer, 0, c);
1298
1299 if (info.sizeBytes > 0) {
1300 final float fraction = ((float) c / (float) info.sizeBytes);
1301 session.addProgress(fraction);
1302 }
1303 }
1304 session.fsync(out);
1305
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001306 if (logSuccess) {
1307 pw.println("Success: streamed " + total + " bytes");
1308 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001309 return 0;
1310 } catch (IOException e) {
1311 pw.println("Error: failed to write; " + e.getMessage());
1312 return 1;
1313 } finally {
1314 IoUtils.closeQuietly(out);
1315 IoUtils.closeQuietly(in);
1316 IoUtils.closeQuietly(session);
1317 }
1318 }
1319
Todd Kennedyeb9b0532016-03-08 10:10:54 -08001320 private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
1321 throws RemoteException {
1322 final PrintWriter pw = getOutPrintWriter();
1323 PackageInstaller.Session session = null;
1324 try {
1325 session = new PackageInstaller.Session(
1326 mInterface.getPackageInstaller().openSession(sessionId));
1327 session.removeSplit(splitName);
1328
1329 if (logSuccess) {
1330 pw.println("Success");
1331 }
1332 return 0;
1333 } catch (IOException e) {
1334 pw.println("Error: failed to remove split; " + e.getMessage());
1335 return 1;
1336 } finally {
1337 IoUtils.closeQuietly(session);
1338 }
1339 }
1340
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001341 private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001342 final PrintWriter pw = getOutPrintWriter();
1343 PackageInstaller.Session session = null;
1344 try {
1345 session = new PackageInstaller.Session(
1346 mInterface.getPackageInstaller().openSession(sessionId));
1347
1348 final LocalIntentReceiver receiver = new LocalIntentReceiver();
1349 session.commit(receiver.getIntentSender());
1350
1351 final Intent result = receiver.getResult();
1352 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1353 PackageInstaller.STATUS_FAILURE);
1354 if (status == PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001355 if (logSuccess) {
Todd Kennedyb6e96e52016-07-20 16:27:39 -07001356 pw.println("Success");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001357 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001358 } else {
1359 pw.println("Failure ["
1360 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001361 }
1362 return status;
1363 } finally {
1364 IoUtils.closeQuietly(session);
1365 }
1366 }
1367
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001368 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001369 final PrintWriter pw = getOutPrintWriter();
1370 PackageInstaller.Session session = null;
1371 try {
1372 session = new PackageInstaller.Session(
1373 mInterface.getPackageInstaller().openSession(sessionId));
1374 session.abandon();
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001375 if (logSuccess) {
1376 pw.println("Success");
1377 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001378 return 0;
1379 } finally {
1380 IoUtils.closeQuietly(session);
1381 }
1382 }
1383
Todd Kennedy60459ab2015-10-30 11:32:16 -07001384 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
1385 boolean summary, int startProtectionLevel, int endProtectionLevel)
1386 throws RemoteException {
1387 final PrintWriter pw = getOutPrintWriter();
1388 final int groupCount = groupList.size();
1389 for (int i = 0; i < groupCount; i++) {
1390 String groupName = groupList.get(i);
1391 String prefix = "";
1392 if (groups) {
1393 if (i > 0) {
1394 pw.println("");
1395 }
1396 if (groupName != null) {
1397 PermissionGroupInfo pgi =
1398 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
1399 if (summary) {
1400 Resources res = getResources(pgi);
1401 if (res != null) {
1402 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
1403 } else {
1404 pw.print(pgi.name + ": ");
1405
1406 }
1407 } else {
1408 pw.println((labels ? "+ " : "") + "group:" + pgi.name);
1409 if (labels) {
1410 pw.println(" package:" + pgi.packageName);
1411 Resources res = getResources(pgi);
1412 if (res != null) {
1413 pw.println(" label:"
1414 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
1415 pw.println(" description:"
1416 + loadText(pgi, pgi.descriptionRes,
1417 pgi.nonLocalizedDescription));
1418 }
1419 }
1420 }
1421 } else {
1422 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
1423 }
1424 prefix = " ";
1425 }
1426 List<PermissionInfo> ps =
Jeff Sharkeyd5896632016-03-04 16:16:00 -07001427 mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -07001428 final int count = ps.size();
1429 boolean first = true;
1430 for (int p = 0 ; p < count ; p++) {
1431 PermissionInfo pi = ps.get(p);
1432 if (groups && groupName == null && pi.group != null) {
1433 continue;
1434 }
1435 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
1436 if (base < startProtectionLevel
1437 || base > endProtectionLevel) {
1438 continue;
1439 }
1440 if (summary) {
1441 if (first) {
1442 first = false;
1443 } else {
1444 pw.print(", ");
1445 }
1446 Resources res = getResources(pi);
1447 if (res != null) {
1448 pw.print(loadText(pi, pi.labelRes,
1449 pi.nonLocalizedLabel));
1450 } else {
1451 pw.print(pi.name);
1452 }
1453 } else {
1454 pw.println(prefix + (labels ? "+ " : "")
1455 + "permission:" + pi.name);
1456 if (labels) {
1457 pw.println(prefix + " package:" + pi.packageName);
1458 Resources res = getResources(pi);
1459 if (res != null) {
1460 pw.println(prefix + " label:"
1461 + loadText(pi, pi.labelRes,
1462 pi.nonLocalizedLabel));
1463 pw.println(prefix + " description:"
1464 + loadText(pi, pi.descriptionRes,
1465 pi.nonLocalizedDescription));
1466 }
1467 pw.println(prefix + " protectionLevel:"
1468 + PermissionInfo.protectionToString(pi.protectionLevel));
1469 }
1470 }
1471 }
1472
1473 if (summary) {
1474 pw.println("");
1475 }
1476 }
1477 }
1478
1479 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
1480 throws RemoteException {
1481 if (nonLocalized != null) {
1482 return nonLocalized.toString();
1483 }
1484 if (res != 0) {
1485 Resources r = getResources(pii);
1486 if (r != null) {
1487 try {
1488 return r.getString(res);
1489 } catch (Resources.NotFoundException e) {
1490 }
1491 }
1492 }
1493 return null;
1494 }
1495
1496 private Resources getResources(PackageItemInfo pii) throws RemoteException {
1497 Resources res = mResourceCache.get(pii.packageName);
1498 if (res != null) return res;
1499
1500 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0);
1501 AssetManager am = new AssetManager();
1502 am.addAssetPath(ai.publicSourceDir);
1503 res = new Resources(am, null, null);
1504 mResourceCache.put(pii.packageName, res);
1505 return res;
1506 }
1507
1508 @Override
1509 public void onHelp() {
1510 final PrintWriter pw = getOutPrintWriter();
1511 pw.println("Package manager (package) commands:");
1512 pw.println(" help");
1513 pw.println(" Print this help text.");
1514 pw.println("");
Richard Uhler568a9692016-05-03 16:02:52 -07001515 pw.println(" compile [-m MODE | -r REASON] [-f] [-c]");
1516 pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
David Brazdil990fb6b2016-03-01 10:02:27 +00001517 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".");
David Brazdil493411a2016-02-01 13:48:46 +00001518 pw.println(" Options:");
David Brazdil990fb6b2016-03-01 10:02:27 +00001519 pw.println(" -a: compile all packages");
David Brazdil9aa6db02016-03-08 12:57:12 +00001520 pw.println(" -c: clear profile data before compiling");
1521 pw.println(" -f: force compilation even if not needed");
David Brazdil493411a2016-02-01 13:48:46 +00001522 pw.println(" -m: select compilation mode");
Richard Uhler568a9692016-05-03 16:02:52 -07001523 pw.println(" MODE is one of the dex2oat compiler filters:");
1524 pw.println(" verify-none");
1525 pw.println(" verify-at-runtime");
1526 pw.println(" verify-profile");
1527 pw.println(" interpret-only");
1528 pw.println(" space-profile");
1529 pw.println(" space");
1530 pw.println(" speed-profile");
1531 pw.println(" speed");
1532 pw.println(" everything");
1533 pw.println(" -r: select compilation reason");
1534 pw.println(" REASON is one of:");
1535 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
1536 pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
1537 }
David Brazdilcf046952016-03-08 16:40:20 +00001538 pw.println(" --reset: restore package to its post-install state");
Richard Uhler568a9692016-05-03 16:02:52 -07001539 pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
Calin Juravlecb5f41e2017-01-25 17:16:08 -08001540 pw.println(" --secondary-dex: compile app secondary dex files");
1541 pw.println(" bg-dexopt-job");
1542 pw.println(" Execute the background optimizations immediately.");
1543 pw.println(" Note that the command only runs the background optimizer logic. It may");
1544 pw.println(" overlap with the actual job but the job scheduler will not be able to");
1545 pw.println(" cancel it. It will also run even if the device is not in the idle");
1546 pw.println(" maintenance mode.");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001547 pw.println(" list features");
1548 pw.println(" Prints all features of the system.");
1549 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00001550 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001551 pw.println(" Options:");
1552 pw.println(" -f: dump the name of the .apk file containing the test package");
1553 pw.println(" list libraries");
1554 pw.println(" Prints all system libraries.");
Felipe Lemeeece9862016-06-29 11:45:03 -07001555 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] "
1556 + "[--uid UID] [--user USER_ID] [FILTER]");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001557 pw.println(" Prints all packages; optionally only those whose name contains");
1558 pw.println(" the text in FILTER.");
1559 pw.println(" Options:");
1560 pw.println(" -f: see their associated file");
Felipe Leme3f24edf2015-11-18 15:04:13 -08001561 pw.println(" -d: filter to only show disabled packages");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001562 pw.println(" -e: filter to only show enabled packages");
1563 pw.println(" -s: filter to only show system packages");
1564 pw.println(" -3: filter to only show third party packages");
1565 pw.println(" -i: see the installer for the packages");
Felipe Lemeeece9862016-06-29 11:45:03 -07001566 pw.println(" -l: ignored (used for compatibility with older releases)");
1567 pw.println(" -U: also show the package UID");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001568 pw.println(" -u: also include uninstalled packages");
Felipe Lemeeece9862016-06-29 11:45:03 -07001569 pw.println(" --uid UID: filter to only show packages with the given UID");
1570 pw.println(" --user USER_ID: only list packages belonging to the given user");
Calin Juravle1aa5f882017-01-25 01:05:50 -08001571 pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE");
1572 pw.println(" Reconciles the package secondary dex files with the generated oat files.");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001573 pw.println(" list permission-groups");
1574 pw.println(" Prints all known permission groups.");
1575 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
1576 pw.println(" Prints all known permissions; optionally only those in GROUP.");
1577 pw.println(" Options:");
1578 pw.println(" -g: organize by group");
1579 pw.println(" -f: print all information");
1580 pw.println(" -s: short summary");
1581 pw.println(" -d: only list dangerous permissions");
1582 pw.println(" -u: list only the permissions users will see");
David Sehrcae13b02016-06-07 09:11:27 -07001583 pw.println(" dump-profiles TARGET-PACKAGE");
1584 pw.println(" Dumps method/class profile files to");
1585 pw.println(" /data/misc/profman/TARGET-PACKAGE.txt");
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001586 pw.println(" resolve-activity [--brief] [--components] [--user USER_ID] INTENT");
Dianne Hackborn99878e92015-12-02 16:27:41 -08001587 pw.println(" Prints the activity that resolves to the given Intent.");
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001588 pw.println(" query-activities [--brief] [--components] [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001589 pw.println(" Prints all activities that can handle the given Intent.");
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001590 pw.println(" query-services [--brief] [--components] [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001591 pw.println(" Prints all services that can handle the given Intent.");
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001592 pw.println(" query-receivers [--brief] [--components] [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001593 pw.println(" Prints all broadcast receivers that can handle the given Intent.");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00001594 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE");
1595 pw.println(" Suspends the specified package (as user).");
1596 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE");
1597 pw.println(" Unsuspends the specified package (as user).");
Makoto Onuki4828a592016-03-15 18:06:57 -07001598 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
1599 pw.println(" set the default home activity (aka launcher).");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001600 pw.println();
1601 Intent.printIntentArgsHelp(pw , "");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001602 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001603
1604 private static class LocalIntentReceiver {
1605 private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
1606
1607 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
1608 @Override
Dianne Hackborn0c4e6a82016-05-13 17:37:08 -07001609 public void send(int code, Intent intent, String resolvedType,
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001610 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
1611 try {
1612 mResult.offer(intent, 5, TimeUnit.SECONDS);
1613 } catch (InterruptedException e) {
1614 throw new RuntimeException(e);
1615 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001616 }
1617 };
1618
1619 public IntentSender getIntentSender() {
1620 return new IntentSender((IIntentSender) mLocalSender);
1621 }
1622
1623 public Intent getResult() {
1624 try {
1625 return mResult.take();
1626 } catch (InterruptedException e) {
1627 throw new RuntimeException(e);
1628 }
1629 }
1630 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07001631}