blob: 2f8d74925df131ae576ab574f11d6d3b3bf85d57 [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();
David Sehra8777082016-05-24 15:25:23 -0700121 case "dump-profiles":
122 return runDumpProfiles();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700123 case "list":
124 return runList();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800125 case "uninstall":
126 return runUninstall();
Dianne Hackborn99878e92015-12-02 16:27:41 -0800127 case "resolve-activity":
128 return runResolveActivity();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800129 case "query-activities":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800130 return runQueryIntentActivities();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800131 case "query-services":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800132 return runQueryIntentServices();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800133 case "query-receivers":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800134 return runQueryIntentReceivers();
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000135 case "suspend":
136 return runSuspend(true);
137 case "unsuspend":
138 return runSuspend(false);
Makoto Onuki4828a592016-03-15 18:06:57 -0700139 case "set-home-activity":
140 return runSetHomeActivity();
Fyodor Kupolov51245c72016-12-01 11:34:10 -0800141 case "get-privapp-permissions":
142 return runGetPrivappPermissions();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700143 default:
144 return handleDefaultCommands(cmd);
145 }
146 } catch (RemoteException e) {
147 pw.println("Remote exception: " + e);
148 }
149 return -1;
150 }
151
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700152 private void setParamsSize(InstallParams params, String inPath) {
153 // If we're forced to stream the package, the params size
154 // must be set via command-line argument. There's nothing
155 // to do here.
156 if (FORCE_STREAM_INSTALL) {
157 return;
158 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800159 final PrintWriter pw = getOutPrintWriter();
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700160 if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
Shunta Sato4f26cb52016-06-28 09:29:19 +0900161 File file = new File(inPath);
162 if (file.isFile()) {
163 try {
164 ApkLite baseApk = PackageParser.parseApkLite(file, 0);
Adam Lesinski4e862812016-11-21 16:02:24 -0800165 PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null);
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700166 params.sessionParams.setSize(PackageHelper.calculateInstalledSize(
167 pkgLite, false, params.sessionParams.abiOverride));
Shunta Sato4f26cb52016-06-28 09:29:19 +0900168 } catch (PackageParserException | IOException e) {
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700169 pw.println("Error: Failed to parse APK file: " + file);
170 throw new IllegalArgumentException(
171 "Error: Failed to parse APK file: " + file, e);
Shunta Sato4f26cb52016-06-28 09:29:19 +0900172 }
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700173 } else {
174 pw.println("Error: Can't open non-file: " + inPath);
175 throw new IllegalArgumentException("Error: Can't open non-file: " + inPath);
Shunta Sato4f26cb52016-06-28 09:29:19 +0900176 }
177 }
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700178 }
Shunta Sato4f26cb52016-06-28 09:29:19 +0900179
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700180 private int runInstall() throws RemoteException {
181 final PrintWriter pw = getOutPrintWriter();
182 final InstallParams params = makeInstallParams();
183 final String inPath = getNextArg();
184
185 setParamsSize(params, inPath);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800186 final int sessionId = doCreateSession(params.sessionParams,
187 params.installerPackageName, params.userId);
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800188 boolean abandonSession = true;
189 try {
Todd Kennedy9caf94e2016-10-12 15:26:08 -0700190 if (inPath == null && params.sessionParams.sizeBytes == -1) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800191 pw.println("Error: must either specify a package size or an APK file");
192 return 1;
193 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800194 if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800195 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
196 return 1;
197 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800198 if (doCommitSession(sessionId, false /*logSuccess*/)
199 != PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800200 return 1;
201 }
202 abandonSession = false;
Todd Kennedy50ea35f2015-12-17 14:46:39 -0800203 pw.println("Success");
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800204 return 0;
205 } finally {
206 if (abandonSession) {
207 try {
208 doAbandonSession(sessionId, false /*logSuccess*/);
209 } catch (Exception ignore) {
210 }
211 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800212 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800213 }
214
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000215 private int runSuspend(boolean suspendedState) {
216 final PrintWriter pw = getOutPrintWriter();
217 int userId = UserHandle.USER_SYSTEM;
218 String opt;
219 while ((opt = getNextOption()) != null) {
220 switch (opt) {
221 case "--user":
222 userId = UserHandle.parseUserArg(getNextArgRequired());
223 break;
224 default:
225 pw.println("Error: Unknown option: " + opt);
226 return 1;
227 }
228 }
229
230 String packageName = getNextArg();
231 if (packageName == null) {
232 pw.println("Error: package name not specified");
233 return 1;
234 }
235
236 try {
Andrei Stingaceanueb84b182016-01-26 18:39:55 +0000237 mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
238 userId);
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000239 pw.println("Package " + packageName + " new suspended state: "
Andrei Stingaceanu355b2322016-02-12 16:43:51 +0000240 + mInterface.isPackageSuspendedForUser(packageName, userId));
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000241 return 0;
Andrei Stingaceanuefc4a342016-03-22 14:43:01 +0000242 } catch (RemoteException | IllegalArgumentException e) {
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000243 pw.println(e.toString());
244 return 1;
245 }
246 }
247
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800248 private int runInstallAbandon() throws RemoteException {
249 final int sessionId = Integer.parseInt(getNextArg());
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800250 return doAbandonSession(sessionId, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800251 }
252
253 private int runInstallCommit() throws RemoteException {
254 final int sessionId = Integer.parseInt(getNextArg());
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800255 return doCommitSession(sessionId, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800256 }
257
258 private int runInstallCreate() throws RemoteException {
259 final PrintWriter pw = getOutPrintWriter();
260 final InstallParams installParams = makeInstallParams();
261 final int sessionId = doCreateSession(installParams.sessionParams,
262 installParams.installerPackageName, installParams.userId);
263
264 // NOTE: adb depends on parsing this string
265 pw.println("Success: created install session [" + sessionId + "]");
266 return 0;
267 }
268
269 private int runInstallWrite() throws RemoteException {
270 long sizeBytes = -1;
271
272 String opt;
273 while ((opt = getNextOption()) != null) {
274 if (opt.equals("-S")) {
275 sizeBytes = Long.parseLong(getNextArg());
276 } else {
277 throw new IllegalArgumentException("Unknown option: " + opt);
278 }
279 }
280
281 final int sessionId = Integer.parseInt(getNextArg());
282 final String splitName = getNextArg();
283 final String path = getNextArg();
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800284 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
285 }
286
287 private int runInstallRemove() throws RemoteException {
288 final PrintWriter pw = getOutPrintWriter();
289
290 final int sessionId = Integer.parseInt(getNextArg());
291
292 final String splitName = getNextArg();
293 if (splitName == null) {
294 pw.println("Error: split name not specified");
295 return 1;
296 }
297 return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800298 }
299
David Brazdil493411a2016-02-01 13:48:46 +0000300 private int runCompile() throws RemoteException {
301 final PrintWriter pw = getOutPrintWriter();
Calin Juravle8bc758b2016-03-28 12:31:52 +0100302 boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
David Brazdil493411a2016-02-01 13:48:46 +0000303 boolean forceCompilation = false;
David Brazdil990fb6b2016-03-01 10:02:27 +0000304 boolean allPackages = false;
David Brazdil9aa6db02016-03-08 12:57:12 +0000305 boolean clearProfileData = false;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700306 String compilerFilter = null;
307 String compilationReason = null;
Calin Juravle8bc758b2016-03-28 12:31:52 +0100308 String checkProfilesRaw = null;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700309
David Brazdil493411a2016-02-01 13:48:46 +0000310 String opt;
311 while ((opt = getNextOption()) != null) {
312 switch (opt) {
David Brazdil990fb6b2016-03-01 10:02:27 +0000313 case "-a":
314 allPackages = true;
315 break;
David Brazdil9aa6db02016-03-08 12:57:12 +0000316 case "-c":
317 clearProfileData = true;
David Brazdil493411a2016-02-01 13:48:46 +0000318 break;
319 case "-f":
320 forceCompilation = true;
321 break;
David Brazdil9aa6db02016-03-08 12:57:12 +0000322 case "-m":
Andreas Gampebdd30d82016-03-20 11:32:11 -0700323 compilerFilter = getNextArgRequired();
324 break;
325 case "-r":
326 compilationReason = getNextArgRequired();
David Brazdil9aa6db02016-03-08 12:57:12 +0000327 break;
Richard Uhler568a9692016-05-03 16:02:52 -0700328 case "--check-prof":
Calin Juravle8bc758b2016-03-28 12:31:52 +0100329 checkProfilesRaw = getNextArgRequired();
330 break;
David Brazdil9aa6db02016-03-08 12:57:12 +0000331 case "--reset":
332 forceCompilation = true;
333 clearProfileData = true;
Richard Uhler5f201e62016-05-11 13:38:27 -0700334 compilationReason = "install";
David Brazdil9aa6db02016-03-08 12:57:12 +0000335 break;
David Brazdil493411a2016-02-01 13:48:46 +0000336 default:
337 pw.println("Error: Unknown option: " + opt);
338 return 1;
339 }
340 }
341
Calin Juravle8bc758b2016-03-28 12:31:52 +0100342 if (checkProfilesRaw != null) {
343 if ("true".equals(checkProfilesRaw)) {
344 checkProfiles = true;
345 } else if ("false".equals(checkProfilesRaw)) {
346 checkProfiles = false;
347 } else {
348 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
349 return 1;
350 }
351 }
352
Andreas Gampebdd30d82016-03-20 11:32:11 -0700353 if (compilerFilter != null && compilationReason != null) {
354 pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " +
355 "at the same time");
356 return 1;
David Brazdil493411a2016-02-01 13:48:46 +0000357 }
Andreas Gampebdd30d82016-03-20 11:32:11 -0700358 if (compilerFilter == null && compilationReason == null) {
359 pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " +
360 "reason (\"-r\") at the same time");
361 return 1;
362 }
363
364 String targetCompilerFilter;
365 if (compilerFilter != null) {
Richard Uhler568a9692016-05-03 16:02:52 -0700366 if (!DexFile.isValidCompilerFilter(compilerFilter)) {
367 pw.println("Error: \"" + compilerFilter +
368 "\" is not a valid compilation filter.");
369 return 1;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700370 }
Richard Uhler568a9692016-05-03 16:02:52 -0700371 targetCompilerFilter = compilerFilter;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700372 } else {
373 int reason = -1;
374 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
375 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
376 compilationReason)) {
377 reason = i;
378 break;
379 }
380 }
381 if (reason == -1) {
382 pw.println("Error: Unknown compilation reason: " + compilationReason);
383 return 1;
384 }
385 targetCompilerFilter =
386 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
387 }
388
David Brazdil493411a2016-02-01 13:48:46 +0000389
David Brazdil990fb6b2016-03-01 10:02:27 +0000390 List<String> packageNames = null;
391 if (allPackages) {
392 packageNames = mInterface.getAllPackages();
393 } else {
394 String packageName = getNextArg();
395 if (packageName == null) {
396 pw.println("Error: package name not specified");
397 return 1;
398 }
399 packageNames = Collections.singletonList(packageName);
David Brazdil493411a2016-02-01 13:48:46 +0000400 }
401
David Brazdil990fb6b2016-03-01 10:02:27 +0000402 List<String> failedPackages = new ArrayList<>();
403 for (String packageName : packageNames) {
David Brazdil9aa6db02016-03-08 12:57:12 +0000404 if (clearProfileData) {
405 mInterface.clearApplicationProfileData(packageName);
406 }
407
Nicolas Geoffrayfb6cf772016-05-27 13:09:19 +0100408 boolean result = mInterface.performDexOptMode(packageName,
Calin Juravle8bc758b2016-03-28 12:31:52 +0100409 checkProfiles, targetCompilerFilter, forceCompilation);
David Brazdil990fb6b2016-03-01 10:02:27 +0000410 if (!result) {
411 failedPackages.add(packageName);
412 }
413 }
414
415 if (failedPackages.isEmpty()) {
David Brazdil493411a2016-02-01 13:48:46 +0000416 pw.println("Success");
417 return 0;
David Brazdil990fb6b2016-03-01 10:02:27 +0000418 } else if (failedPackages.size() == 1) {
419 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
420 return 1;
David Brazdil493411a2016-02-01 13:48:46 +0000421 } else {
David Brazdil990fb6b2016-03-01 10:02:27 +0000422 pw.print("Failure: the following packages could not be compiled: ");
423 boolean is_first = true;
424 for (String packageName : failedPackages) {
425 if (is_first) {
426 is_first = false;
427 } else {
428 pw.print(", ");
429 }
430 pw.print(packageName);
431 }
432 pw.println();
David Brazdil493411a2016-02-01 13:48:46 +0000433 return 1;
434 }
435 }
436
David Sehra8777082016-05-24 15:25:23 -0700437 private int runDumpProfiles() throws RemoteException {
438 String packageName = getNextArg();
439 mInterface.dumpProfiles(packageName);
440 return 0;
441 }
442
Todd Kennedy60459ab2015-10-30 11:32:16 -0700443 private int runList() throws RemoteException {
444 final PrintWriter pw = getOutPrintWriter();
445 final String type = getNextArg();
446 if (type == null) {
447 pw.println("Error: didn't specify type of data to list");
448 return -1;
449 }
450 switch(type) {
451 case "features":
452 return runListFeatures();
453 case "instrumentation":
454 return runListInstrumentation();
455 case "libraries":
456 return runListLibraries();
457 case "package":
458 case "packages":
459 return runListPackages(false /*showSourceDir*/);
460 case "permission-groups":
461 return runListPermissionGroups();
462 case "permissions":
463 return runListPermissions();
464 }
465 pw.println("Error: unknown list type '" + type + "'");
466 return -1;
467 }
468
469 private int runListFeatures() throws RemoteException {
470 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700471 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700472
473 // sort by name
474 Collections.sort(list, new Comparator<FeatureInfo>() {
475 public int compare(FeatureInfo o1, FeatureInfo o2) {
476 if (o1.name == o2.name) return 0;
477 if (o1.name == null) return -1;
478 if (o2.name == null) return 1;
479 return o1.name.compareTo(o2.name);
480 }
481 });
482
483 final int count = (list != null) ? list.size() : 0;
484 for (int p = 0; p < count; p++) {
485 FeatureInfo fi = list.get(p);
486 pw.print("feature:");
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700487 if (fi.name != null) {
488 pw.print(fi.name);
489 if (fi.version > 0) {
490 pw.print("=");
491 pw.print(fi.version);
492 }
493 pw.println();
494 } else {
495 pw.println("reqGlEsVersion=0x"
Todd Kennedy60459ab2015-10-30 11:32:16 -0700496 + Integer.toHexString(fi.reqGlEsVersion));
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700497 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700498 }
499 return 0;
500 }
501
502 private int runListInstrumentation() throws RemoteException {
503 final PrintWriter pw = getOutPrintWriter();
504 boolean showSourceDir = false;
505 String targetPackage = null;
506
507 try {
508 String opt;
509 while ((opt = getNextArg()) != null) {
510 switch (opt) {
511 case "-f":
512 showSourceDir = true;
513 break;
514 default:
515 if (opt.charAt(0) != '-') {
516 targetPackage = opt;
517 } else {
518 pw.println("Error: Unknown option: " + opt);
519 return -1;
520 }
521 break;
522 }
523 }
524 } catch (RuntimeException ex) {
525 pw.println("Error: " + ex.toString());
526 return -1;
527 }
528
529 final List<InstrumentationInfo> list =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700530 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700531
532 // sort by target package
533 Collections.sort(list, new Comparator<InstrumentationInfo>() {
534 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
535 return o1.targetPackage.compareTo(o2.targetPackage);
536 }
537 });
538
539 final int count = (list != null) ? list.size() : 0;
540 for (int p = 0; p < count; p++) {
541 final InstrumentationInfo ii = list.get(p);
542 pw.print("instrumentation:");
543 if (showSourceDir) {
544 pw.print(ii.sourceDir);
545 pw.print("=");
546 }
547 final ComponentName cn = new ComponentName(ii.packageName, ii.name);
548 pw.print(cn.flattenToShortString());
549 pw.print(" (target=");
550 pw.print(ii.targetPackage);
551 pw.println(")");
552 }
553 return 0;
554 }
555
556 private int runListLibraries() throws RemoteException {
557 final PrintWriter pw = getOutPrintWriter();
558 final List<String> list = new ArrayList<String>();
559 final String[] rawList = mInterface.getSystemSharedLibraryNames();
560 for (int i = 0; i < rawList.length; i++) {
561 list.add(rawList[i]);
562 }
563
564 // sort by name
565 Collections.sort(list, new Comparator<String>() {
566 public int compare(String o1, String o2) {
567 if (o1 == o2) return 0;
568 if (o1 == null) return -1;
569 if (o2 == null) return 1;
570 return o1.compareTo(o2);
571 }
572 });
573
574 final int count = (list != null) ? list.size() : 0;
575 for (int p = 0; p < count; p++) {
576 String lib = list.get(p);
577 pw.print("library:");
578 pw.println(lib);
579 }
580 return 0;
581 }
582
583 private int runListPackages(boolean showSourceDir) throws RemoteException {
584 final PrintWriter pw = getOutPrintWriter();
585 int getFlags = 0;
586 boolean listDisabled = false, listEnabled = false;
587 boolean listSystem = false, listThirdParty = false;
588 boolean listInstaller = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700589 boolean showUid = false;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800590 boolean showVersionCode = false;
Felipe Lemeeece9862016-06-29 11:45:03 -0700591 int uid = -1;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700592 int userId = UserHandle.USER_SYSTEM;
593 try {
594 String opt;
595 while ((opt = getNextOption()) != null) {
596 switch (opt) {
597 case "-d":
598 listDisabled = true;
599 break;
600 case "-e":
601 listEnabled = true;
602 break;
603 case "-f":
604 showSourceDir = true;
605 break;
606 case "-i":
607 listInstaller = true;
608 break;
609 case "-l":
610 // old compat
611 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700612 case "-s":
613 listSystem = true;
614 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700615 case "-U":
616 showUid = true;
617 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700618 case "-u":
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700619 getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700620 break;
621 case "-3":
622 listThirdParty = true;
623 break;
Todd Kennedybadc69a2017-01-24 11:05:47 -0800624 case "--show-versioncode":
625 showVersionCode = true;
626 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700627 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800628 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy60459ab2015-10-30 11:32:16 -0700629 break;
Felipe Lemeeece9862016-06-29 11:45:03 -0700630 case "--uid":
631 showUid = true;
632 uid = Integer.parseInt(getNextArgRequired());
633 break;
Todd Kennedy60459ab2015-10-30 11:32:16 -0700634 default:
635 pw.println("Error: Unknown option: " + opt);
636 return -1;
637 }
638 }
639 } catch (RuntimeException ex) {
640 pw.println("Error: " + ex.toString());
641 return -1;
642 }
643
644 final String filter = getNextArg();
645
646 @SuppressWarnings("unchecked")
647 final ParceledListSlice<PackageInfo> slice =
648 mInterface.getInstalledPackages(getFlags, userId);
649 final List<PackageInfo> packages = slice.getList();
650
651 final int count = packages.size();
652 for (int p = 0; p < count; p++) {
653 final PackageInfo info = packages.get(p);
654 if (filter != null && !info.packageName.contains(filter)) {
655 continue;
656 }
Felipe Lemeeece9862016-06-29 11:45:03 -0700657 if (uid != -1 && info.applicationInfo.uid != uid) {
658 continue;
659 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700660 final boolean isSystem =
661 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
662 if ((!listDisabled || !info.applicationInfo.enabled) &&
663 (!listEnabled || info.applicationInfo.enabled) &&
664 (!listSystem || isSystem) &&
665 (!listThirdParty || !isSystem)) {
666 pw.print("package:");
667 if (showSourceDir) {
668 pw.print(info.applicationInfo.sourceDir);
669 pw.print("=");
670 }
Todd Kennedybadc69a2017-01-24 11:05:47 -0800671 pw.print(info.packageName);
672 if (showVersionCode) {
673 pw.print(" versionCode:");
674 pw.print(info.applicationInfo.versionCode);
675 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700676 if (listInstaller) {
677 pw.print(" installer=");
678 pw.print(mInterface.getInstallerPackageName(info.packageName));
679 }
Felipe Lemeeece9862016-06-29 11:45:03 -0700680 if (showUid) {
681 pw.print(" uid:");
682 pw.print(info.applicationInfo.uid);
683 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700684 pw.println();
685 }
686 }
687 return 0;
688 }
689
690 private int runListPermissionGroups() throws RemoteException {
691 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700692 final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700693
694 final int count = pgs.size();
695 for (int p = 0; p < count ; p++) {
696 final PermissionGroupInfo pgi = pgs.get(p);
697 pw.print("permission group:");
698 pw.println(pgi.name);
699 }
700 return 0;
701 }
702
703 private int runListPermissions() throws RemoteException {
704 final PrintWriter pw = getOutPrintWriter();
705 boolean labels = false;
706 boolean groups = false;
707 boolean userOnly = false;
708 boolean summary = false;
709 boolean dangerousOnly = false;
710 String opt;
711 while ((opt = getNextOption()) != null) {
712 switch (opt) {
713 case "-d":
714 dangerousOnly = true;
715 break;
716 case "-f":
717 labels = true;
718 break;
719 case "-g":
720 groups = true;
721 break;
722 case "-s":
723 groups = true;
724 labels = true;
725 summary = true;
726 break;
727 case "-u":
728 userOnly = true;
729 break;
730 default:
731 pw.println("Error: Unknown option: " + opt);
732 return 1;
733 }
734 }
735
736 final ArrayList<String> groupList = new ArrayList<String>();
737 if (groups) {
738 final List<PermissionGroupInfo> infos =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700739 mInterface.getAllPermissionGroups(0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700740 final int count = infos.size();
741 for (int i = 0; i < count; i++) {
742 groupList.add(infos.get(i).name);
743 }
744 groupList.add(null);
745 } else {
746 final String grp = getNextArg();
747 groupList.add(grp);
748 }
749
750 if (dangerousOnly) {
751 pw.println("Dangerous Permissions:");
752 pw.println("");
753 doListPermissions(groupList, groups, labels, summary,
754 PermissionInfo.PROTECTION_DANGEROUS,
755 PermissionInfo.PROTECTION_DANGEROUS);
756 if (userOnly) {
757 pw.println("Normal Permissions:");
758 pw.println("");
759 doListPermissions(groupList, groups, labels, summary,
760 PermissionInfo.PROTECTION_NORMAL,
761 PermissionInfo.PROTECTION_NORMAL);
762 }
763 } else if (userOnly) {
764 pw.println("Dangerous and Normal Permissions:");
765 pw.println("");
766 doListPermissions(groupList, groups, labels, summary,
767 PermissionInfo.PROTECTION_NORMAL,
768 PermissionInfo.PROTECTION_DANGEROUS);
769 } else {
770 pw.println("All Permissions:");
771 pw.println("");
772 doListPermissions(groupList, groups, labels, summary,
773 -10000, 10000);
774 }
775 return 0;
776 }
777
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800778 private int runUninstall() throws RemoteException {
779 final PrintWriter pw = getOutPrintWriter();
780 int flags = 0;
781 int userId = UserHandle.USER_ALL;
Svet Ganov67882122016-12-11 16:36:34 -0800782 int versionCode = PackageManager.VERSION_CODE_HIGHEST;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800783
784 String opt;
785 while ((opt = getNextOption()) != null) {
786 switch (opt) {
787 case "-k":
788 flags |= PackageManager.DELETE_KEEP_DATA;
789 break;
790 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800791 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800792 break;
Svet Ganov67882122016-12-11 16:36:34 -0800793 case "--versionCode":
794 versionCode = Integer.parseInt(getNextArgRequired());
795 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800796 default:
797 pw.println("Error: Unknown option: " + opt);
798 return 1;
799 }
800 }
801
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800802 final String packageName = getNextArg();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800803 if (packageName == null) {
804 pw.println("Error: package name not specified");
805 return 1;
806 }
807
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800808 // if a split is specified, just remove it and not the whole package
809 final String splitName = getNextArg();
810 if (splitName != null) {
811 return runRemoveSplit(packageName, splitName);
812 }
813
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800814 userId = translateUserId(userId, "runUninstall");
815 if (userId == UserHandle.USER_ALL) {
816 userId = UserHandle.USER_SYSTEM;
817 flags |= PackageManager.DELETE_ALL_USERS;
818 } else {
819 final PackageInfo info = mInterface.getPackageInfo(packageName, 0, userId);
820 if (info == null) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800821 pw.println("Failure [not installed for " + userId + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800822 return 1;
823 }
824 final boolean isSystem =
825 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
826 // If we are being asked to delete a system app for just one
827 // user set flag so it disables rather than reverting to system
828 // version of the app.
829 if (isSystem) {
830 flags |= PackageManager.DELETE_SYSTEM_APP;
831 }
832 }
833
834 final LocalIntentReceiver receiver = new LocalIntentReceiver();
Svet Ganov67882122016-12-11 16:36:34 -0800835 mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
836 versionCode), null /*callerPackageName*/, flags,
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800837 receiver.getIntentSender(), userId);
838
839 final Intent result = receiver.getResult();
840 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
841 PackageInstaller.STATUS_FAILURE);
842 if (status == PackageInstaller.STATUS_SUCCESS) {
843 pw.println("Success");
844 return 0;
845 } else {
846 pw.println("Failure ["
847 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
848 return 1;
849 }
850 }
851
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800852 private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
853 final PrintWriter pw = getOutPrintWriter();
854 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
855 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
856 sessionParams.appPackageName = packageName;
857 final int sessionId =
858 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
859 boolean abandonSession = true;
860 try {
861 if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
862 != PackageInstaller.STATUS_SUCCESS) {
863 return 1;
864 }
865 if (doCommitSession(sessionId, false /*logSuccess*/)
866 != PackageInstaller.STATUS_SUCCESS) {
867 return 1;
868 }
869 abandonSession = false;
870 pw.println("Success");
871 return 0;
872 } finally {
873 if (abandonSession) {
874 try {
875 doAbandonSession(sessionId, false /*logSuccess*/);
876 } catch (Exception ignore) {
877 }
878 }
879 }
880 }
881
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800882 private Intent parseIntentAndUser() throws URISyntaxException {
883 mTargetUser = UserHandle.USER_CURRENT;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700884 mBrief = false;
885 mComponents = false;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800886 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
887 @Override
888 public boolean handleOption(String opt, ShellCommand cmd) {
889 if ("--user".equals(opt)) {
890 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
891 return true;
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700892 } else if ("--brief".equals(opt)) {
893 mBrief = true;
894 return true;
895 } else if ("--components".equals(opt)) {
896 mComponents = true;
897 return true;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800898 }
899 return false;
900 }
901 });
902 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
903 Binder.getCallingUid(), mTargetUser, false, false, null, null);
904 return intent;
905 }
906
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700907 private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri,
908 boolean brief, boolean components) {
909 if (brief || components) {
910 final ComponentName comp;
911 if (ri.activityInfo != null) {
912 comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
913 } else if (ri.serviceInfo != null) {
914 comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
915 } else if (ri.providerInfo != null) {
916 comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name);
917 } else {
918 comp = null;
919 }
920 if (comp != null) {
921 if (!components) {
922 pr.println(prefix + "priority=" + ri.priority
923 + " preferredOrder=" + ri.preferredOrder
924 + " match=0x" + Integer.toHexString(ri.match)
925 + " specificIndex=" + ri.specificIndex
926 + " isDefault=" + ri.isDefault);
927 }
928 pr.println(prefix + comp.flattenToShortString());
929 return;
930 }
931 }
932 ri.dump(pr, prefix);
933 }
934
Dianne Hackborn99878e92015-12-02 16:27:41 -0800935 private int runResolveActivity() {
936 Intent intent;
937 try {
938 intent = parseIntentAndUser();
939 } catch (URISyntaxException e) {
940 throw new RuntimeException(e.getMessage(), e);
941 }
942 try {
943 ResolveInfo ri = mInterface.resolveIntent(intent, null, 0, mTargetUser);
944 PrintWriter pw = getOutPrintWriter();
945 if (ri == null) {
946 pw.println("No activity found");
947 } else {
948 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700949 printResolveInfo(pr, "", ri, mBrief, mComponents);
Dianne Hackborn99878e92015-12-02 16:27:41 -0800950 }
951 } catch (RemoteException e) {
952 throw new RuntimeException("Failed calling service", e);
953 }
954 return 0;
955 }
956
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800957 private int runQueryIntentActivities() {
958 Intent intent;
959 try {
960 intent = parseIntentAndUser();
961 } catch (URISyntaxException e) {
962 throw new RuntimeException(e.getMessage(), e);
963 }
964 try {
965 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700966 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800967 PrintWriter pw = getOutPrintWriter();
968 if (result == null || result.size() <= 0) {
969 pw.println("No activities found");
970 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -0700971 if (!mComponents) {
972 pw.print(result.size()); pw.println(" activities found:");
973 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
974 for (int i = 0; i < result.size(); i++) {
975 pw.print(" Activity #"); pw.print(i); pw.println(":");
976 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
977 }
978 } else {
979 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
980 for (int i = 0; i < result.size(); i++) {
981 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
982 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800983 }
984 }
985 } catch (RemoteException e) {
986 throw new RuntimeException("Failed calling service", e);
987 }
988 return 0;
989 }
990
991 private int runQueryIntentServices() {
992 Intent intent;
993 try {
994 intent = parseIntentAndUser();
995 } catch (URISyntaxException e) {
996 throw new RuntimeException(e.getMessage(), e);
997 }
998 try {
999 List<ResolveInfo> result = mInterface.queryIntentServices(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -07001000 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001001 PrintWriter pw = getOutPrintWriter();
1002 if (result == null || result.size() <= 0) {
1003 pw.println("No services found");
1004 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001005 if (!mComponents) {
1006 pw.print(result.size()); pw.println(" services found:");
1007 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1008 for (int i = 0; i < result.size(); i++) {
1009 pw.print(" Service #"); pw.print(i); pw.println(":");
1010 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1011 }
1012 } else {
1013 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1014 for (int i = 0; i < result.size(); i++) {
1015 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1016 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001017 }
1018 }
1019 } catch (RemoteException e) {
1020 throw new RuntimeException("Failed calling service", e);
1021 }
1022 return 0;
1023 }
1024
1025 private int runQueryIntentReceivers() {
1026 Intent intent;
1027 try {
1028 intent = parseIntentAndUser();
1029 } catch (URISyntaxException e) {
1030 throw new RuntimeException(e.getMessage(), e);
1031 }
1032 try {
1033 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -07001034 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001035 PrintWriter pw = getOutPrintWriter();
1036 if (result == null || result.size() <= 0) {
1037 pw.println("No receivers found");
1038 } else {
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001039 if (!mComponents) {
1040 pw.print(result.size()); pw.println(" receivers found:");
1041 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1042 for (int i = 0; i < result.size(); i++) {
1043 pw.print(" Receiver #"); pw.print(i); pw.println(":");
1044 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents);
1045 }
1046 } else {
1047 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1048 for (int i = 0; i < result.size(); i++) {
1049 printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1050 }
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001051 }
1052 }
1053 } catch (RemoteException e) {
1054 throw new RuntimeException("Failed calling service", e);
1055 }
1056 return 0;
1057 }
1058
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001059 private static class InstallParams {
1060 SessionParams sessionParams;
1061 String installerPackageName;
1062 int userId = UserHandle.USER_ALL;
1063 }
1064
1065 private InstallParams makeInstallParams() {
1066 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
1067 final InstallParams params = new InstallParams();
1068 params.sessionParams = sessionParams;
1069 String opt;
1070 while ((opt = getNextOption()) != null) {
1071 switch (opt) {
1072 case "-l":
1073 sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
1074 break;
1075 case "-r":
1076 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1077 break;
1078 case "-i":
1079 params.installerPackageName = getNextArg();
1080 if (params.installerPackageName == null) {
1081 throw new IllegalArgumentException("Missing installer package");
1082 }
1083 break;
1084 case "-t":
1085 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
1086 break;
1087 case "-s":
1088 sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL;
1089 break;
1090 case "-f":
1091 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
1092 break;
1093 case "-d":
1094 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
1095 break;
1096 case "-g":
1097 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1098 break;
Todd Kennedyb1072712016-04-26 15:41:20 -07001099 case "--dont-kill":
1100 sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
1101 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001102 case "--originating-uri":
1103 sessionParams.originatingUri = Uri.parse(getNextArg());
1104 break;
1105 case "--referrer":
1106 sessionParams.referrerUri = Uri.parse(getNextArg());
1107 break;
1108 case "-p":
1109 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
1110 sessionParams.appPackageName = getNextArg();
1111 if (sessionParams.appPackageName == null) {
1112 throw new IllegalArgumentException("Missing inherit package name");
1113 }
1114 break;
1115 case "-S":
Todd Kennedy9caf94e2016-10-12 15:26:08 -07001116 final long sizeBytes = Long.parseLong(getNextArg());
1117 if (sizeBytes <= 0) {
1118 throw new IllegalArgumentException("Size must be positive");
1119 }
1120 sessionParams.setSize(sizeBytes);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001121 break;
1122 case "--abi":
1123 sessionParams.abiOverride = checkAbiArgument(getNextArg());
1124 break;
Todd Kennedy2699f062015-11-20 13:07:17 -08001125 case "--ephemeral":
Todd Kennedyb7717682016-11-30 15:41:21 -08001126 sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
Todd Kennedy2699f062015-11-20 13:07:17 -08001127 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001128 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001129 params.userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001130 break;
1131 case "--install-location":
1132 sessionParams.installLocation = Integer.parseInt(getNextArg());
1133 break;
1134 case "--force-uuid":
1135 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
1136 sessionParams.volumeUuid = getNextArg();
1137 if ("internal".equals(sessionParams.volumeUuid)) {
1138 sessionParams.volumeUuid = null;
1139 }
1140 break;
Todd Kennedyb1072712016-04-26 15:41:20 -07001141 case "--force-sdk":
1142 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK;
1143 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001144 default:
1145 throw new IllegalArgumentException("Unknown option " + opt);
1146 }
1147 }
1148 return params;
1149 }
1150
Makoto Onuki4828a592016-03-15 18:06:57 -07001151 private int runSetHomeActivity() {
1152 final PrintWriter pw = getOutPrintWriter();
1153 int userId = UserHandle.USER_SYSTEM;
1154 String opt;
1155 while ((opt = getNextOption()) != null) {
1156 switch (opt) {
1157 case "--user":
1158 userId = UserHandle.parseUserArg(getNextArgRequired());
1159 break;
1160 default:
1161 pw.println("Error: Unknown option: " + opt);
1162 return 1;
1163 }
1164 }
1165
1166 String component = getNextArg();
1167 ComponentName componentName =
1168 component != null ? ComponentName.unflattenFromString(component) : null;
1169
1170 if (componentName == null) {
1171 pw.println("Error: component name not specified or invalid");
1172 return 1;
1173 }
1174
1175 try {
1176 mInterface.setHomeActivity(componentName, userId);
Makoto Onuki3bdbf982016-06-23 16:56:35 -07001177 pw.println("Success");
Makoto Onuki4828a592016-03-15 18:06:57 -07001178 return 0;
Makoto Onuki3bdbf982016-06-23 16:56:35 -07001179 } catch (Exception e) {
Makoto Onuki4828a592016-03-15 18:06:57 -07001180 pw.println(e.toString());
1181 return 1;
1182 }
1183 }
1184
Fyodor Kupolov51245c72016-12-01 11:34:10 -08001185 private int runGetPrivappPermissions() {
1186 final String pkg = getNextArg();
1187 if (pkg == null) {
1188 System.err.println("Error: no package specified.");
1189 return 1;
1190 }
1191 ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
1192 getOutPrintWriter().println(privAppPermissions == null
1193 ? "{}" : privAppPermissions.toString());
1194 return 0;
1195 }
1196
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001197 private static String checkAbiArgument(String abi) {
1198 if (TextUtils.isEmpty(abi)) {
1199 throw new IllegalArgumentException("Missing ABI argument");
1200 }
1201
1202 if ("-".equals(abi)) {
1203 return abi;
1204 }
1205
1206 final String[] supportedAbis = Build.SUPPORTED_ABIS;
1207 for (String supportedAbi : supportedAbis) {
1208 if (supportedAbi.equals(abi)) {
1209 return abi;
1210 }
1211 }
1212
1213 throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
1214 }
1215
1216 private int translateUserId(int userId, String logContext) {
1217 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
1218 userId, true, true, logContext, "pm command");
1219 }
1220
1221 private int doCreateSession(SessionParams params, String installerPackageName, int userId)
1222 throws RemoteException {
1223 userId = translateUserId(userId, "runInstallCreate");
1224 if (userId == UserHandle.USER_ALL) {
1225 userId = UserHandle.USER_SYSTEM;
1226 params.installFlags |= PackageManager.INSTALL_ALL_USERS;
1227 }
1228
1229 final int sessionId = mInterface.getPackageInstaller()
1230 .createSession(params, installerPackageName, userId);
1231 return sessionId;
1232 }
1233
Todd Kennedyeb9b0532016-03-08 10:10:54 -08001234 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001235 boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001236 final PrintWriter pw = getOutPrintWriter();
Todd Kennedy9caf94e2016-10-12 15:26:08 -07001237 if (FORCE_STREAM_INSTALL && inPath != null && !STDIN_PATH.equals(inPath)) {
1238 pw.println("Error: APK content must be streamed");
1239 return 1;
1240 }
1241 if (STDIN_PATH.equals(inPath)) {
1242 inPath = null;
1243 } else if (inPath != null) {
1244 final File file = new File(inPath);
1245 if (file.isFile()) {
1246 sizeBytes = file.length();
1247 }
1248 }
Todd Kennedy63cc8b02016-09-22 13:25:46 -07001249 if (sizeBytes <= 0) {
1250 pw.println("Error: must specify a APK size");
1251 return 1;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001252 }
1253
1254 final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId);
1255
1256 PackageInstaller.Session session = null;
1257 InputStream in = null;
1258 OutputStream out = null;
1259 try {
1260 session = new PackageInstaller.Session(
1261 mInterface.getPackageInstaller().openSession(sessionId));
1262
1263 if (inPath != null) {
1264 in = new FileInputStream(inPath);
1265 } else {
Dianne Hackborn2e931f52016-01-28 12:21:17 -08001266 in = new SizedInputStream(getRawInputStream(), sizeBytes);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001267 }
1268 out = session.openWrite(splitName, 0, sizeBytes);
1269
1270 int total = 0;
1271 byte[] buffer = new byte[65536];
1272 int c;
1273 while ((c = in.read(buffer)) != -1) {
1274 total += c;
1275 out.write(buffer, 0, c);
1276
1277 if (info.sizeBytes > 0) {
1278 final float fraction = ((float) c / (float) info.sizeBytes);
1279 session.addProgress(fraction);
1280 }
1281 }
1282 session.fsync(out);
1283
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001284 if (logSuccess) {
1285 pw.println("Success: streamed " + total + " bytes");
1286 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001287 return 0;
1288 } catch (IOException e) {
1289 pw.println("Error: failed to write; " + e.getMessage());
1290 return 1;
1291 } finally {
1292 IoUtils.closeQuietly(out);
1293 IoUtils.closeQuietly(in);
1294 IoUtils.closeQuietly(session);
1295 }
1296 }
1297
Todd Kennedyeb9b0532016-03-08 10:10:54 -08001298 private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
1299 throws RemoteException {
1300 final PrintWriter pw = getOutPrintWriter();
1301 PackageInstaller.Session session = null;
1302 try {
1303 session = new PackageInstaller.Session(
1304 mInterface.getPackageInstaller().openSession(sessionId));
1305 session.removeSplit(splitName);
1306
1307 if (logSuccess) {
1308 pw.println("Success");
1309 }
1310 return 0;
1311 } catch (IOException e) {
1312 pw.println("Error: failed to remove split; " + e.getMessage());
1313 return 1;
1314 } finally {
1315 IoUtils.closeQuietly(session);
1316 }
1317 }
1318
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001319 private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001320 final PrintWriter pw = getOutPrintWriter();
1321 PackageInstaller.Session session = null;
1322 try {
1323 session = new PackageInstaller.Session(
1324 mInterface.getPackageInstaller().openSession(sessionId));
1325
1326 final LocalIntentReceiver receiver = new LocalIntentReceiver();
1327 session.commit(receiver.getIntentSender());
1328
1329 final Intent result = receiver.getResult();
1330 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1331 PackageInstaller.STATUS_FAILURE);
1332 if (status == PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001333 if (logSuccess) {
Todd Kennedyb6e96e52016-07-20 16:27:39 -07001334 pw.println("Success");
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001335 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001336 } else {
1337 pw.println("Failure ["
1338 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001339 }
1340 return status;
1341 } finally {
1342 IoUtils.closeQuietly(session);
1343 }
1344 }
1345
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001346 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001347 final PrintWriter pw = getOutPrintWriter();
1348 PackageInstaller.Session session = null;
1349 try {
1350 session = new PackageInstaller.Session(
1351 mInterface.getPackageInstaller().openSession(sessionId));
1352 session.abandon();
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001353 if (logSuccess) {
1354 pw.println("Success");
1355 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001356 return 0;
1357 } finally {
1358 IoUtils.closeQuietly(session);
1359 }
1360 }
1361
Todd Kennedy60459ab2015-10-30 11:32:16 -07001362 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
1363 boolean summary, int startProtectionLevel, int endProtectionLevel)
1364 throws RemoteException {
1365 final PrintWriter pw = getOutPrintWriter();
1366 final int groupCount = groupList.size();
1367 for (int i = 0; i < groupCount; i++) {
1368 String groupName = groupList.get(i);
1369 String prefix = "";
1370 if (groups) {
1371 if (i > 0) {
1372 pw.println("");
1373 }
1374 if (groupName != null) {
1375 PermissionGroupInfo pgi =
1376 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
1377 if (summary) {
1378 Resources res = getResources(pgi);
1379 if (res != null) {
1380 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
1381 } else {
1382 pw.print(pgi.name + ": ");
1383
1384 }
1385 } else {
1386 pw.println((labels ? "+ " : "") + "group:" + pgi.name);
1387 if (labels) {
1388 pw.println(" package:" + pgi.packageName);
1389 Resources res = getResources(pgi);
1390 if (res != null) {
1391 pw.println(" label:"
1392 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
1393 pw.println(" description:"
1394 + loadText(pgi, pgi.descriptionRes,
1395 pgi.nonLocalizedDescription));
1396 }
1397 }
1398 }
1399 } else {
1400 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
1401 }
1402 prefix = " ";
1403 }
1404 List<PermissionInfo> ps =
Jeff Sharkeyd5896632016-03-04 16:16:00 -07001405 mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -07001406 final int count = ps.size();
1407 boolean first = true;
1408 for (int p = 0 ; p < count ; p++) {
1409 PermissionInfo pi = ps.get(p);
1410 if (groups && groupName == null && pi.group != null) {
1411 continue;
1412 }
1413 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
1414 if (base < startProtectionLevel
1415 || base > endProtectionLevel) {
1416 continue;
1417 }
1418 if (summary) {
1419 if (first) {
1420 first = false;
1421 } else {
1422 pw.print(", ");
1423 }
1424 Resources res = getResources(pi);
1425 if (res != null) {
1426 pw.print(loadText(pi, pi.labelRes,
1427 pi.nonLocalizedLabel));
1428 } else {
1429 pw.print(pi.name);
1430 }
1431 } else {
1432 pw.println(prefix + (labels ? "+ " : "")
1433 + "permission:" + pi.name);
1434 if (labels) {
1435 pw.println(prefix + " package:" + pi.packageName);
1436 Resources res = getResources(pi);
1437 if (res != null) {
1438 pw.println(prefix + " label:"
1439 + loadText(pi, pi.labelRes,
1440 pi.nonLocalizedLabel));
1441 pw.println(prefix + " description:"
1442 + loadText(pi, pi.descriptionRes,
1443 pi.nonLocalizedDescription));
1444 }
1445 pw.println(prefix + " protectionLevel:"
1446 + PermissionInfo.protectionToString(pi.protectionLevel));
1447 }
1448 }
1449 }
1450
1451 if (summary) {
1452 pw.println("");
1453 }
1454 }
1455 }
1456
1457 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
1458 throws RemoteException {
1459 if (nonLocalized != null) {
1460 return nonLocalized.toString();
1461 }
1462 if (res != 0) {
1463 Resources r = getResources(pii);
1464 if (r != null) {
1465 try {
1466 return r.getString(res);
1467 } catch (Resources.NotFoundException e) {
1468 }
1469 }
1470 }
1471 return null;
1472 }
1473
1474 private Resources getResources(PackageItemInfo pii) throws RemoteException {
1475 Resources res = mResourceCache.get(pii.packageName);
1476 if (res != null) return res;
1477
1478 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0);
1479 AssetManager am = new AssetManager();
1480 am.addAssetPath(ai.publicSourceDir);
1481 res = new Resources(am, null, null);
1482 mResourceCache.put(pii.packageName, res);
1483 return res;
1484 }
1485
1486 @Override
1487 public void onHelp() {
1488 final PrintWriter pw = getOutPrintWriter();
1489 pw.println("Package manager (package) commands:");
1490 pw.println(" help");
1491 pw.println(" Print this help text.");
1492 pw.println("");
Richard Uhler568a9692016-05-03 16:02:52 -07001493 pw.println(" compile [-m MODE | -r REASON] [-f] [-c]");
1494 pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
David Brazdil990fb6b2016-03-01 10:02:27 +00001495 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".");
David Brazdil493411a2016-02-01 13:48:46 +00001496 pw.println(" Options:");
David Brazdil990fb6b2016-03-01 10:02:27 +00001497 pw.println(" -a: compile all packages");
David Brazdil9aa6db02016-03-08 12:57:12 +00001498 pw.println(" -c: clear profile data before compiling");
1499 pw.println(" -f: force compilation even if not needed");
David Brazdil493411a2016-02-01 13:48:46 +00001500 pw.println(" -m: select compilation mode");
Richard Uhler568a9692016-05-03 16:02:52 -07001501 pw.println(" MODE is one of the dex2oat compiler filters:");
1502 pw.println(" verify-none");
1503 pw.println(" verify-at-runtime");
1504 pw.println(" verify-profile");
1505 pw.println(" interpret-only");
1506 pw.println(" space-profile");
1507 pw.println(" space");
1508 pw.println(" speed-profile");
1509 pw.println(" speed");
1510 pw.println(" everything");
1511 pw.println(" -r: select compilation reason");
1512 pw.println(" REASON is one of:");
1513 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
1514 pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
1515 }
David Brazdilcf046952016-03-08 16:40:20 +00001516 pw.println(" --reset: restore package to its post-install state");
Richard Uhler568a9692016-05-03 16:02:52 -07001517 pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001518 pw.println(" list features");
1519 pw.println(" Prints all features of the system.");
1520 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00001521 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001522 pw.println(" Options:");
1523 pw.println(" -f: dump the name of the .apk file containing the test package");
1524 pw.println(" list libraries");
1525 pw.println(" Prints all system libraries.");
Felipe Lemeeece9862016-06-29 11:45:03 -07001526 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] "
1527 + "[--uid UID] [--user USER_ID] [FILTER]");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001528 pw.println(" Prints all packages; optionally only those whose name contains");
1529 pw.println(" the text in FILTER.");
1530 pw.println(" Options:");
1531 pw.println(" -f: see their associated file");
Felipe Leme3f24edf2015-11-18 15:04:13 -08001532 pw.println(" -d: filter to only show disabled packages");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001533 pw.println(" -e: filter to only show enabled packages");
1534 pw.println(" -s: filter to only show system packages");
1535 pw.println(" -3: filter to only show third party packages");
1536 pw.println(" -i: see the installer for the packages");
Felipe Lemeeece9862016-06-29 11:45:03 -07001537 pw.println(" -l: ignored (used for compatibility with older releases)");
1538 pw.println(" -U: also show the package UID");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001539 pw.println(" -u: also include uninstalled packages");
Felipe Lemeeece9862016-06-29 11:45:03 -07001540 pw.println(" --uid UID: filter to only show packages with the given UID");
1541 pw.println(" --user USER_ID: only list packages belonging to the given user");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001542 pw.println(" list permission-groups");
1543 pw.println(" Prints all known permission groups.");
1544 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
1545 pw.println(" Prints all known permissions; optionally only those in GROUP.");
1546 pw.println(" Options:");
1547 pw.println(" -g: organize by group");
1548 pw.println(" -f: print all information");
1549 pw.println(" -s: short summary");
1550 pw.println(" -d: only list dangerous permissions");
1551 pw.println(" -u: list only the permissions users will see");
David Sehrcae13b02016-06-07 09:11:27 -07001552 pw.println(" dump-profiles TARGET-PACKAGE");
1553 pw.println(" Dumps method/class profile files to");
1554 pw.println(" /data/misc/profman/TARGET-PACKAGE.txt");
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001555 pw.println(" resolve-activity [--brief] [--components] [--user USER_ID] INTENT");
Dianne Hackborn99878e92015-12-02 16:27:41 -08001556 pw.println(" Prints the activity that resolves to the given Intent.");
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001557 pw.println(" query-activities [--brief] [--components] [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001558 pw.println(" Prints all activities that can handle the given Intent.");
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001559 pw.println(" query-services [--brief] [--components] [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001560 pw.println(" Prints all services that can handle the given Intent.");
Dianne Hackbornd6e4aa42016-04-26 13:51:07 -07001561 pw.println(" query-receivers [--brief] [--components] [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001562 pw.println(" Prints all broadcast receivers that can handle the given Intent.");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00001563 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE");
1564 pw.println(" Suspends the specified package (as user).");
1565 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE");
1566 pw.println(" Unsuspends the specified package (as user).");
Makoto Onuki4828a592016-03-15 18:06:57 -07001567 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
1568 pw.println(" set the default home activity (aka launcher).");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001569 pw.println();
1570 Intent.printIntentArgsHelp(pw , "");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001571 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001572
1573 private static class LocalIntentReceiver {
1574 private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
1575
1576 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
1577 @Override
Dianne Hackborn0c4e6a82016-05-13 17:37:08 -07001578 public void send(int code, Intent intent, String resolvedType,
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001579 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
1580 try {
1581 mResult.offer(intent, 5, TimeUnit.SECONDS);
1582 } catch (InterruptedException e) {
1583 throw new RuntimeException(e);
1584 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001585 }
1586 };
1587
1588 public IntentSender getIntentSender() {
1589 return new IntentSender((IIntentSender) mLocalSender);
1590 }
1591
1592 public Intent getResult() {
1593 try {
1594 return mResult.take();
1595 } catch (InterruptedException e) {
1596 throw new RuntimeException(e);
1597 }
1598 }
1599 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07001600}