blob: 238ce95d1afaeeb5bd7a1a3d1c7815fba534d78b [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;
33import android.content.pm.ParceledListSlice;
34import android.content.pm.PermissionGroupInfo;
35import android.content.pm.PermissionInfo;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080036import android.content.pm.PackageInstaller.SessionInfo;
37import android.content.pm.PackageInstaller.SessionParams;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080038import android.content.pm.ResolveInfo;
Todd Kennedy60459ab2015-10-30 11:32:16 -070039import android.content.res.AssetManager;
40import android.content.res.Resources;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080041import android.net.Uri;
42import android.os.Binder;
43import android.os.Build;
44import android.os.Bundle;
Todd Kennedy60459ab2015-10-30 11:32:16 -070045import android.os.RemoteException;
46import android.os.ShellCommand;
Calin Juravle8bc758b2016-03-28 12:31:52 +010047import android.os.SystemProperties;
Todd Kennedy60459ab2015-10-30 11:32:16 -070048import android.os.UserHandle;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080049import android.text.TextUtils;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080050import android.util.PrintWriterPrinter;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080051import com.android.internal.util.SizedInputStream;
52
Andreas Gampebdd30d82016-03-20 11:32:11 -070053import dalvik.system.DexFile;
54
Todd Kennedy72cfcd02015-11-03 17:08:55 -080055import libcore.io.IoUtils;
56
57import java.io.File;
58import java.io.FileInputStream;
59import java.io.IOException;
60import java.io.InputStream;
61import java.io.OutputStream;
Todd Kennedy60459ab2015-10-30 11:32:16 -070062import java.io.PrintWriter;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080063import java.net.URISyntaxException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070064import java.util.ArrayList;
65import java.util.Collections;
66import java.util.Comparator;
67import java.util.List;
68import java.util.WeakHashMap;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080069import java.util.concurrent.SynchronousQueue;
70import java.util.concurrent.TimeUnit;
Todd Kennedy60459ab2015-10-30 11:32:16 -070071
72class PackageManagerShellCommand extends ShellCommand {
73 final IPackageManager mInterface;
74 final private WeakHashMap<String, Resources> mResourceCache =
75 new WeakHashMap<String, Resources>();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080076 int mTargetUser;
Todd Kennedy60459ab2015-10-30 11:32:16 -070077
78 PackageManagerShellCommand(PackageManagerService service) {
79 mInterface = service;
80 }
81
82 @Override
83 public int onCommand(String cmd) {
84 if (cmd == null) {
85 return handleDefaultCommands(cmd);
86 }
87
88 final PrintWriter pw = getOutPrintWriter();
89 try {
90 switch(cmd) {
Todd Kennedy72cfcd02015-11-03 17:08:55 -080091 case "install":
92 return runInstall();
93 case "install-abandon":
94 case "install-destroy":
95 return runInstallAbandon();
96 case "install-commit":
97 return runInstallCommit();
98 case "install-create":
99 return runInstallCreate();
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800100 case "install-remove":
101 return runInstallRemove();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800102 case "install-write":
103 return runInstallWrite();
David Brazdil493411a2016-02-01 13:48:46 +0000104 case "compile":
105 return runCompile();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700106 case "list":
107 return runList();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800108 case "uninstall":
109 return runUninstall();
Dianne Hackborn99878e92015-12-02 16:27:41 -0800110 case "resolve-activity":
111 return runResolveActivity();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800112 case "query-activities":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800113 return runQueryIntentActivities();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800114 case "query-services":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800115 return runQueryIntentServices();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800116 case "query-receivers":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800117 return runQueryIntentReceivers();
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000118 case "suspend":
119 return runSuspend(true);
120 case "unsuspend":
121 return runSuspend(false);
Makoto Onuki4828a592016-03-15 18:06:57 -0700122 case "set-home-activity":
123 return runSetHomeActivity();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700124 default:
125 return handleDefaultCommands(cmd);
126 }
127 } catch (RemoteException e) {
128 pw.println("Remote exception: " + e);
129 }
130 return -1;
131 }
132
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800133 private int runInstall() throws RemoteException {
134 final PrintWriter pw = getOutPrintWriter();
135 final InstallParams params = makeInstallParams();
136 final int sessionId = doCreateSession(params.sessionParams,
137 params.installerPackageName, params.userId);
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800138 boolean abandonSession = true;
139 try {
140 final String inPath = getNextArg();
141 if (inPath == null && params.sessionParams.sizeBytes == 0) {
142 pw.println("Error: must either specify a package size or an APK file");
143 return 1;
144 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800145 if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800146 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
147 return 1;
148 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800149 if (doCommitSession(sessionId, false /*logSuccess*/)
150 != PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800151 return 1;
152 }
153 abandonSession = false;
Todd Kennedy50ea35f2015-12-17 14:46:39 -0800154 pw.println("Success");
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800155 return 0;
156 } finally {
157 if (abandonSession) {
158 try {
159 doAbandonSession(sessionId, false /*logSuccess*/);
160 } catch (Exception ignore) {
161 }
162 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800163 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800164 }
165
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000166 private int runSuspend(boolean suspendedState) {
167 final PrintWriter pw = getOutPrintWriter();
168 int userId = UserHandle.USER_SYSTEM;
169 String opt;
170 while ((opt = getNextOption()) != null) {
171 switch (opt) {
172 case "--user":
173 userId = UserHandle.parseUserArg(getNextArgRequired());
174 break;
175 default:
176 pw.println("Error: Unknown option: " + opt);
177 return 1;
178 }
179 }
180
181 String packageName = getNextArg();
182 if (packageName == null) {
183 pw.println("Error: package name not specified");
184 return 1;
185 }
186
187 try {
Andrei Stingaceanueb84b182016-01-26 18:39:55 +0000188 mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
189 userId);
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000190 pw.println("Package " + packageName + " new suspended state: "
Andrei Stingaceanu355b2322016-02-12 16:43:51 +0000191 + mInterface.isPackageSuspendedForUser(packageName, userId));
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000192 return 0;
193 } catch (RemoteException e) {
194 pw.println(e.toString());
195 return 1;
196 }
197 }
198
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800199 private int runInstallAbandon() throws RemoteException {
200 final int sessionId = Integer.parseInt(getNextArg());
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800201 return doAbandonSession(sessionId, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800202 }
203
204 private int runInstallCommit() throws RemoteException {
205 final int sessionId = Integer.parseInt(getNextArg());
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800206 return doCommitSession(sessionId, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800207 }
208
209 private int runInstallCreate() throws RemoteException {
210 final PrintWriter pw = getOutPrintWriter();
211 final InstallParams installParams = makeInstallParams();
212 final int sessionId = doCreateSession(installParams.sessionParams,
213 installParams.installerPackageName, installParams.userId);
214
215 // NOTE: adb depends on parsing this string
216 pw.println("Success: created install session [" + sessionId + "]");
217 return 0;
218 }
219
220 private int runInstallWrite() throws RemoteException {
221 long sizeBytes = -1;
222
223 String opt;
224 while ((opt = getNextOption()) != null) {
225 if (opt.equals("-S")) {
226 sizeBytes = Long.parseLong(getNextArg());
227 } else {
228 throw new IllegalArgumentException("Unknown option: " + opt);
229 }
230 }
231
232 final int sessionId = Integer.parseInt(getNextArg());
233 final String splitName = getNextArg();
234 final String path = getNextArg();
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800235 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
236 }
237
238 private int runInstallRemove() throws RemoteException {
239 final PrintWriter pw = getOutPrintWriter();
240
241 final int sessionId = Integer.parseInt(getNextArg());
242
243 final String splitName = getNextArg();
244 if (splitName == null) {
245 pw.println("Error: split name not specified");
246 return 1;
247 }
248 return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800249 }
250
David Brazdil493411a2016-02-01 13:48:46 +0000251 private int runCompile() throws RemoteException {
252 final PrintWriter pw = getOutPrintWriter();
Calin Juravle8bc758b2016-03-28 12:31:52 +0100253 boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
David Brazdil493411a2016-02-01 13:48:46 +0000254 boolean forceCompilation = false;
David Brazdil990fb6b2016-03-01 10:02:27 +0000255 boolean allPackages = false;
David Brazdil9aa6db02016-03-08 12:57:12 +0000256 boolean clearProfileData = false;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700257 String compilerFilter = null;
258 String compilationReason = null;
Calin Juravle8bc758b2016-03-28 12:31:52 +0100259 String checkProfilesRaw = null;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700260
261 if (peekNextArg() == null) {
262 // No arguments, show help.
263 pw.println("Usage: cmd package compile [-c] [-f] [--reset] [-m mode] " +
264 "[-r reason] [-a|pkg]");
265 pw.println();
Calin Juravle8bc758b2016-03-28 12:31:52 +0100266 pw.println(" -c Clear profile data");
267 pw.println(" -f Force compilation");
268 pw.println(" --check-prof val Look at profiles when doing dexopt.");
269 pw.println(" Overrides dalvik.vm.usejitprofiles to true of false");
270 pw.println(" --reset Reset package");
271 pw.println(" -m mode Compilation mode, one of the dex2oat compiler filters");
272 pw.println(" verify-none");
273 pw.println(" verify-at-runtime");
274 pw.println(" verify-profile");
275 pw.println(" interpret-only");
276 pw.println(" space-profile");
277 pw.println(" space");
278 pw.println(" speed-profile");
279 pw.println(" speed");
280 pw.println(" everything");
Andreas Gampebdd30d82016-03-20 11:32:11 -0700281 pw.println(" -r reason Compiler reason, one of the package manager reasons");
282 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
283 pw.println(" " +
284 PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
285 }
286 pw.println(" -a Apply to all packages");
287 return 1;
288 }
David Brazdil493411a2016-02-01 13:48:46 +0000289
290 String opt;
291 while ((opt = getNextOption()) != null) {
292 switch (opt) {
David Brazdil990fb6b2016-03-01 10:02:27 +0000293 case "-a":
294 allPackages = true;
295 break;
David Brazdil9aa6db02016-03-08 12:57:12 +0000296 case "-c":
297 clearProfileData = true;
David Brazdil493411a2016-02-01 13:48:46 +0000298 break;
299 case "-f":
300 forceCompilation = true;
301 break;
David Brazdil9aa6db02016-03-08 12:57:12 +0000302 case "-m":
Andreas Gampebdd30d82016-03-20 11:32:11 -0700303 compilerFilter = getNextArgRequired();
304 break;
305 case "-r":
306 compilationReason = getNextArgRequired();
David Brazdil9aa6db02016-03-08 12:57:12 +0000307 break;
Calin Juravle8bc758b2016-03-28 12:31:52 +0100308 case "-check-prof":
309 checkProfilesRaw = getNextArgRequired();
310 break;
David Brazdil9aa6db02016-03-08 12:57:12 +0000311 case "--reset":
312 forceCompilation = true;
313 clearProfileData = true;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700314 compilerFilter = "reset";
David Brazdil9aa6db02016-03-08 12:57:12 +0000315 break;
David Brazdil493411a2016-02-01 13:48:46 +0000316 default:
317 pw.println("Error: Unknown option: " + opt);
318 return 1;
319 }
320 }
321
Calin Juravle8bc758b2016-03-28 12:31:52 +0100322 if (checkProfilesRaw != null) {
323 if ("true".equals(checkProfilesRaw)) {
324 checkProfiles = true;
325 } else if ("false".equals(checkProfilesRaw)) {
326 checkProfiles = false;
327 } else {
328 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
329 return 1;
330 }
331 }
332
Andreas Gampebdd30d82016-03-20 11:32:11 -0700333 if (compilerFilter != null && compilationReason != null) {
334 pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " +
335 "at the same time");
336 return 1;
David Brazdil493411a2016-02-01 13:48:46 +0000337 }
Andreas Gampebdd30d82016-03-20 11:32:11 -0700338 if (compilerFilter == null && compilationReason == null) {
339 pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " +
340 "reason (\"-r\") at the same time");
341 return 1;
342 }
343
344 String targetCompilerFilter;
345 if (compilerFilter != null) {
346 // Specially recognize default and reset. Otherwise, only accept valid modes.
347 if ("default".equals(compilerFilter)) {
348 // Use the default mode for background dexopt.
349 targetCompilerFilter =
350 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
Andreas Gampe43fc2442016-03-24 20:13:34 -0700351 PackageManagerService.REASON_BACKGROUND_DEXOPT);
Andreas Gampebdd30d82016-03-20 11:32:11 -0700352 } else if ("reset".equals(compilerFilter)) {
353 // Use the default mode for install.
354 targetCompilerFilter =
355 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
Andreas Gampe43fc2442016-03-24 20:13:34 -0700356 PackageManagerService.REASON_INSTALL);
Andreas Gampebdd30d82016-03-20 11:32:11 -0700357 } else {
358 if (!DexFile.isValidCompilerFilter(compilerFilter)) {
359 pw.println("Error: \"" + compilerFilter +
360 "\" is not a valid compilation filter.");
361 return 1;
362 }
363 targetCompilerFilter = compilerFilter;
364 }
365 } else {
366 int reason = -1;
367 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
368 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
369 compilationReason)) {
370 reason = i;
371 break;
372 }
373 }
374 if (reason == -1) {
375 pw.println("Error: Unknown compilation reason: " + compilationReason);
376 return 1;
377 }
378 targetCompilerFilter =
379 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
380 }
381
David Brazdil493411a2016-02-01 13:48:46 +0000382
David Brazdil990fb6b2016-03-01 10:02:27 +0000383 List<String> packageNames = null;
384 if (allPackages) {
385 packageNames = mInterface.getAllPackages();
386 } else {
387 String packageName = getNextArg();
388 if (packageName == null) {
389 pw.println("Error: package name not specified");
390 return 1;
391 }
392 packageNames = Collections.singletonList(packageName);
David Brazdil493411a2016-02-01 13:48:46 +0000393 }
394
David Brazdil990fb6b2016-03-01 10:02:27 +0000395 List<String> failedPackages = new ArrayList<>();
396 for (String packageName : packageNames) {
David Brazdil9aa6db02016-03-08 12:57:12 +0000397 if (clearProfileData) {
398 mInterface.clearApplicationProfileData(packageName);
399 }
400
Andreas Gampebdd30d82016-03-20 11:32:11 -0700401 boolean result = mInterface.performDexOptMode(packageName, null /* instructionSet */,
Calin Juravle8bc758b2016-03-28 12:31:52 +0100402 checkProfiles, targetCompilerFilter, forceCompilation);
David Brazdil990fb6b2016-03-01 10:02:27 +0000403 if (!result) {
404 failedPackages.add(packageName);
405 }
406 }
407
408 if (failedPackages.isEmpty()) {
David Brazdil493411a2016-02-01 13:48:46 +0000409 pw.println("Success");
410 return 0;
David Brazdil990fb6b2016-03-01 10:02:27 +0000411 } else if (failedPackages.size() == 1) {
412 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
413 return 1;
David Brazdil493411a2016-02-01 13:48:46 +0000414 } else {
David Brazdil990fb6b2016-03-01 10:02:27 +0000415 pw.print("Failure: the following packages could not be compiled: ");
416 boolean is_first = true;
417 for (String packageName : failedPackages) {
418 if (is_first) {
419 is_first = false;
420 } else {
421 pw.print(", ");
422 }
423 pw.print(packageName);
424 }
425 pw.println();
David Brazdil493411a2016-02-01 13:48:46 +0000426 return 1;
427 }
428 }
429
Todd Kennedy60459ab2015-10-30 11:32:16 -0700430 private int runList() throws RemoteException {
431 final PrintWriter pw = getOutPrintWriter();
432 final String type = getNextArg();
433 if (type == null) {
434 pw.println("Error: didn't specify type of data to list");
435 return -1;
436 }
437 switch(type) {
438 case "features":
439 return runListFeatures();
440 case "instrumentation":
441 return runListInstrumentation();
442 case "libraries":
443 return runListLibraries();
444 case "package":
445 case "packages":
446 return runListPackages(false /*showSourceDir*/);
447 case "permission-groups":
448 return runListPermissionGroups();
449 case "permissions":
450 return runListPermissions();
451 }
452 pw.println("Error: unknown list type '" + type + "'");
453 return -1;
454 }
455
456 private int runListFeatures() throws RemoteException {
457 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700458 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700459
460 // sort by name
461 Collections.sort(list, new Comparator<FeatureInfo>() {
462 public int compare(FeatureInfo o1, FeatureInfo o2) {
463 if (o1.name == o2.name) return 0;
464 if (o1.name == null) return -1;
465 if (o2.name == null) return 1;
466 return o1.name.compareTo(o2.name);
467 }
468 });
469
470 final int count = (list != null) ? list.size() : 0;
471 for (int p = 0; p < count; p++) {
472 FeatureInfo fi = list.get(p);
473 pw.print("feature:");
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700474 if (fi.name != null) {
475 pw.print(fi.name);
476 if (fi.version > 0) {
477 pw.print("=");
478 pw.print(fi.version);
479 }
480 pw.println();
481 } else {
482 pw.println("reqGlEsVersion=0x"
Todd Kennedy60459ab2015-10-30 11:32:16 -0700483 + Integer.toHexString(fi.reqGlEsVersion));
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700484 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700485 }
486 return 0;
487 }
488
489 private int runListInstrumentation() throws RemoteException {
490 final PrintWriter pw = getOutPrintWriter();
491 boolean showSourceDir = false;
492 String targetPackage = null;
493
494 try {
495 String opt;
496 while ((opt = getNextArg()) != null) {
497 switch (opt) {
498 case "-f":
499 showSourceDir = true;
500 break;
501 default:
502 if (opt.charAt(0) != '-') {
503 targetPackage = opt;
504 } else {
505 pw.println("Error: Unknown option: " + opt);
506 return -1;
507 }
508 break;
509 }
510 }
511 } catch (RuntimeException ex) {
512 pw.println("Error: " + ex.toString());
513 return -1;
514 }
515
516 final List<InstrumentationInfo> list =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700517 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700518
519 // sort by target package
520 Collections.sort(list, new Comparator<InstrumentationInfo>() {
521 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
522 return o1.targetPackage.compareTo(o2.targetPackage);
523 }
524 });
525
526 final int count = (list != null) ? list.size() : 0;
527 for (int p = 0; p < count; p++) {
528 final InstrumentationInfo ii = list.get(p);
529 pw.print("instrumentation:");
530 if (showSourceDir) {
531 pw.print(ii.sourceDir);
532 pw.print("=");
533 }
534 final ComponentName cn = new ComponentName(ii.packageName, ii.name);
535 pw.print(cn.flattenToShortString());
536 pw.print(" (target=");
537 pw.print(ii.targetPackage);
538 pw.println(")");
539 }
540 return 0;
541 }
542
543 private int runListLibraries() throws RemoteException {
544 final PrintWriter pw = getOutPrintWriter();
545 final List<String> list = new ArrayList<String>();
546 final String[] rawList = mInterface.getSystemSharedLibraryNames();
547 for (int i = 0; i < rawList.length; i++) {
548 list.add(rawList[i]);
549 }
550
551 // sort by name
552 Collections.sort(list, new Comparator<String>() {
553 public int compare(String o1, String o2) {
554 if (o1 == o2) return 0;
555 if (o1 == null) return -1;
556 if (o2 == null) return 1;
557 return o1.compareTo(o2);
558 }
559 });
560
561 final int count = (list != null) ? list.size() : 0;
562 for (int p = 0; p < count; p++) {
563 String lib = list.get(p);
564 pw.print("library:");
565 pw.println(lib);
566 }
567 return 0;
568 }
569
570 private int runListPackages(boolean showSourceDir) throws RemoteException {
571 final PrintWriter pw = getOutPrintWriter();
572 int getFlags = 0;
573 boolean listDisabled = false, listEnabled = false;
574 boolean listSystem = false, listThirdParty = false;
575 boolean listInstaller = false;
576 int userId = UserHandle.USER_SYSTEM;
577 try {
578 String opt;
579 while ((opt = getNextOption()) != null) {
580 switch (opt) {
581 case "-d":
582 listDisabled = true;
583 break;
584 case "-e":
585 listEnabled = true;
586 break;
587 case "-f":
588 showSourceDir = true;
589 break;
590 case "-i":
591 listInstaller = true;
592 break;
593 case "-l":
594 // old compat
595 break;
596 case "-lf":
597 showSourceDir = true;
598 break;
599 case "-s":
600 listSystem = true;
601 break;
602 case "-u":
603 getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
604 break;
605 case "-3":
606 listThirdParty = true;
607 break;
608 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800609 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy60459ab2015-10-30 11:32:16 -0700610 break;
611 default:
612 pw.println("Error: Unknown option: " + opt);
613 return -1;
614 }
615 }
616 } catch (RuntimeException ex) {
617 pw.println("Error: " + ex.toString());
618 return -1;
619 }
620
621 final String filter = getNextArg();
622
623 @SuppressWarnings("unchecked")
624 final ParceledListSlice<PackageInfo> slice =
625 mInterface.getInstalledPackages(getFlags, userId);
626 final List<PackageInfo> packages = slice.getList();
627
628 final int count = packages.size();
629 for (int p = 0; p < count; p++) {
630 final PackageInfo info = packages.get(p);
631 if (filter != null && !info.packageName.contains(filter)) {
632 continue;
633 }
634 final boolean isSystem =
635 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
636 if ((!listDisabled || !info.applicationInfo.enabled) &&
637 (!listEnabled || info.applicationInfo.enabled) &&
638 (!listSystem || isSystem) &&
639 (!listThirdParty || !isSystem)) {
640 pw.print("package:");
641 if (showSourceDir) {
642 pw.print(info.applicationInfo.sourceDir);
643 pw.print("=");
644 }
645 pw.print(info.packageName);
646 if (listInstaller) {
647 pw.print(" installer=");
648 pw.print(mInterface.getInstallerPackageName(info.packageName));
649 }
650 pw.println();
651 }
652 }
653 return 0;
654 }
655
656 private int runListPermissionGroups() throws RemoteException {
657 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700658 final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700659
660 final int count = pgs.size();
661 for (int p = 0; p < count ; p++) {
662 final PermissionGroupInfo pgi = pgs.get(p);
663 pw.print("permission group:");
664 pw.println(pgi.name);
665 }
666 return 0;
667 }
668
669 private int runListPermissions() throws RemoteException {
670 final PrintWriter pw = getOutPrintWriter();
671 boolean labels = false;
672 boolean groups = false;
673 boolean userOnly = false;
674 boolean summary = false;
675 boolean dangerousOnly = false;
676 String opt;
677 while ((opt = getNextOption()) != null) {
678 switch (opt) {
679 case "-d":
680 dangerousOnly = true;
681 break;
682 case "-f":
683 labels = true;
684 break;
685 case "-g":
686 groups = true;
687 break;
688 case "-s":
689 groups = true;
690 labels = true;
691 summary = true;
692 break;
693 case "-u":
694 userOnly = true;
695 break;
696 default:
697 pw.println("Error: Unknown option: " + opt);
698 return 1;
699 }
700 }
701
702 final ArrayList<String> groupList = new ArrayList<String>();
703 if (groups) {
704 final List<PermissionGroupInfo> infos =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700705 mInterface.getAllPermissionGroups(0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700706 final int count = infos.size();
707 for (int i = 0; i < count; i++) {
708 groupList.add(infos.get(i).name);
709 }
710 groupList.add(null);
711 } else {
712 final String grp = getNextArg();
713 groupList.add(grp);
714 }
715
716 if (dangerousOnly) {
717 pw.println("Dangerous Permissions:");
718 pw.println("");
719 doListPermissions(groupList, groups, labels, summary,
720 PermissionInfo.PROTECTION_DANGEROUS,
721 PermissionInfo.PROTECTION_DANGEROUS);
722 if (userOnly) {
723 pw.println("Normal Permissions:");
724 pw.println("");
725 doListPermissions(groupList, groups, labels, summary,
726 PermissionInfo.PROTECTION_NORMAL,
727 PermissionInfo.PROTECTION_NORMAL);
728 }
729 } else if (userOnly) {
730 pw.println("Dangerous and Normal Permissions:");
731 pw.println("");
732 doListPermissions(groupList, groups, labels, summary,
733 PermissionInfo.PROTECTION_NORMAL,
734 PermissionInfo.PROTECTION_DANGEROUS);
735 } else {
736 pw.println("All Permissions:");
737 pw.println("");
738 doListPermissions(groupList, groups, labels, summary,
739 -10000, 10000);
740 }
741 return 0;
742 }
743
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800744 private int runUninstall() throws RemoteException {
745 final PrintWriter pw = getOutPrintWriter();
746 int flags = 0;
747 int userId = UserHandle.USER_ALL;
748
749 String opt;
750 while ((opt = getNextOption()) != null) {
751 switch (opt) {
752 case "-k":
753 flags |= PackageManager.DELETE_KEEP_DATA;
754 break;
755 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800756 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800757 break;
758 default:
759 pw.println("Error: Unknown option: " + opt);
760 return 1;
761 }
762 }
763
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800764 final String packageName = getNextArg();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800765 if (packageName == null) {
766 pw.println("Error: package name not specified");
767 return 1;
768 }
769
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800770 // if a split is specified, just remove it and not the whole package
771 final String splitName = getNextArg();
772 if (splitName != null) {
773 return runRemoveSplit(packageName, splitName);
774 }
775
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800776 userId = translateUserId(userId, "runUninstall");
777 if (userId == UserHandle.USER_ALL) {
778 userId = UserHandle.USER_SYSTEM;
779 flags |= PackageManager.DELETE_ALL_USERS;
780 } else {
781 final PackageInfo info = mInterface.getPackageInfo(packageName, 0, userId);
782 if (info == null) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800783 pw.println("Failure [not installed for " + userId + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800784 return 1;
785 }
786 final boolean isSystem =
787 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
788 // If we are being asked to delete a system app for just one
789 // user set flag so it disables rather than reverting to system
790 // version of the app.
791 if (isSystem) {
792 flags |= PackageManager.DELETE_SYSTEM_APP;
793 }
794 }
795
796 final LocalIntentReceiver receiver = new LocalIntentReceiver();
797 mInterface.getPackageInstaller().uninstall(packageName, null /*callerPackageName*/, flags,
798 receiver.getIntentSender(), userId);
799
800 final Intent result = receiver.getResult();
801 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
802 PackageInstaller.STATUS_FAILURE);
803 if (status == PackageInstaller.STATUS_SUCCESS) {
804 pw.println("Success");
805 return 0;
806 } else {
807 pw.println("Failure ["
808 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
809 return 1;
810 }
811 }
812
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800813 private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
814 final PrintWriter pw = getOutPrintWriter();
815 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
816 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
817 sessionParams.appPackageName = packageName;
818 final int sessionId =
819 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
820 boolean abandonSession = true;
821 try {
822 if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
823 != PackageInstaller.STATUS_SUCCESS) {
824 return 1;
825 }
826 if (doCommitSession(sessionId, false /*logSuccess*/)
827 != PackageInstaller.STATUS_SUCCESS) {
828 return 1;
829 }
830 abandonSession = false;
831 pw.println("Success");
832 return 0;
833 } finally {
834 if (abandonSession) {
835 try {
836 doAbandonSession(sessionId, false /*logSuccess*/);
837 } catch (Exception ignore) {
838 }
839 }
840 }
841 }
842
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800843 private Intent parseIntentAndUser() throws URISyntaxException {
844 mTargetUser = UserHandle.USER_CURRENT;
845 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
846 @Override
847 public boolean handleOption(String opt, ShellCommand cmd) {
848 if ("--user".equals(opt)) {
849 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
850 return true;
851 }
852 return false;
853 }
854 });
855 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
856 Binder.getCallingUid(), mTargetUser, false, false, null, null);
857 return intent;
858 }
859
Dianne Hackborn99878e92015-12-02 16:27:41 -0800860 private int runResolveActivity() {
861 Intent intent;
862 try {
863 intent = parseIntentAndUser();
864 } catch (URISyntaxException e) {
865 throw new RuntimeException(e.getMessage(), e);
866 }
867 try {
868 ResolveInfo ri = mInterface.resolveIntent(intent, null, 0, mTargetUser);
869 PrintWriter pw = getOutPrintWriter();
870 if (ri == null) {
871 pw.println("No activity found");
872 } else {
873 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
874 ri.dump(pr, "");
875 }
876 } catch (RemoteException e) {
877 throw new RuntimeException("Failed calling service", e);
878 }
879 return 0;
880 }
881
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800882 private int runQueryIntentActivities() {
883 Intent intent;
884 try {
885 intent = parseIntentAndUser();
886 } catch (URISyntaxException e) {
887 throw new RuntimeException(e.getMessage(), e);
888 }
889 try {
890 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700891 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800892 PrintWriter pw = getOutPrintWriter();
893 if (result == null || result.size() <= 0) {
894 pw.println("No activities found");
895 } else {
896 pw.print(result.size()); pw.println(" activities found:");
897 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
898 for (int i=0; i<result.size(); i++) {
899 pw.print(" Activity #"); pw.print(i); pw.println(":");
900 result.get(i).dump(pr, " ");
901 }
902 }
903 } catch (RemoteException e) {
904 throw new RuntimeException("Failed calling service", e);
905 }
906 return 0;
907 }
908
909 private int runQueryIntentServices() {
910 Intent intent;
911 try {
912 intent = parseIntentAndUser();
913 } catch (URISyntaxException e) {
914 throw new RuntimeException(e.getMessage(), e);
915 }
916 try {
917 List<ResolveInfo> result = mInterface.queryIntentServices(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700918 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800919 PrintWriter pw = getOutPrintWriter();
920 if (result == null || result.size() <= 0) {
921 pw.println("No services found");
922 } else {
923 pw.print(result.size()); pw.println(" services found:");
924 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
925 for (int i=0; i<result.size(); i++) {
926 pw.print(" Service #"); pw.print(i); pw.println(":");
927 result.get(i).dump(pr, " ");
928 }
929 }
930 } catch (RemoteException e) {
931 throw new RuntimeException("Failed calling service", e);
932 }
933 return 0;
934 }
935
936 private int runQueryIntentReceivers() {
937 Intent intent;
938 try {
939 intent = parseIntentAndUser();
940 } catch (URISyntaxException e) {
941 throw new RuntimeException(e.getMessage(), e);
942 }
943 try {
944 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700945 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800946 PrintWriter pw = getOutPrintWriter();
947 if (result == null || result.size() <= 0) {
948 pw.println("No receivers found");
949 } else {
950 pw.print(result.size()); pw.println(" receivers found:");
951 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
952 for (int i=0; i<result.size(); i++) {
953 pw.print(" Receiver #"); pw.print(i); pw.println(":");
954 result.get(i).dump(pr, " ");
955 }
956 }
957 } catch (RemoteException e) {
958 throw new RuntimeException("Failed calling service", e);
959 }
960 return 0;
961 }
962
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800963 private static class InstallParams {
964 SessionParams sessionParams;
965 String installerPackageName;
966 int userId = UserHandle.USER_ALL;
967 }
968
969 private InstallParams makeInstallParams() {
970 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
971 final InstallParams params = new InstallParams();
972 params.sessionParams = sessionParams;
973 String opt;
974 while ((opt = getNextOption()) != null) {
975 switch (opt) {
976 case "-l":
977 sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
978 break;
979 case "-r":
980 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
981 break;
982 case "-i":
983 params.installerPackageName = getNextArg();
984 if (params.installerPackageName == null) {
985 throw new IllegalArgumentException("Missing installer package");
986 }
987 break;
988 case "-t":
989 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
990 break;
991 case "-s":
992 sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL;
993 break;
994 case "-f":
995 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
996 break;
997 case "-d":
998 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
999 break;
1000 case "-g":
1001 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1002 break;
1003 case "--originating-uri":
1004 sessionParams.originatingUri = Uri.parse(getNextArg());
1005 break;
1006 case "--referrer":
1007 sessionParams.referrerUri = Uri.parse(getNextArg());
1008 break;
1009 case "-p":
1010 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
1011 sessionParams.appPackageName = getNextArg();
1012 if (sessionParams.appPackageName == null) {
1013 throw new IllegalArgumentException("Missing inherit package name");
1014 }
1015 break;
1016 case "-S":
1017 sessionParams.setSize(Long.parseLong(getNextArg()));
1018 break;
1019 case "--abi":
1020 sessionParams.abiOverride = checkAbiArgument(getNextArg());
1021 break;
Todd Kennedy2699f062015-11-20 13:07:17 -08001022 case "--ephemeral":
1023 sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL;
1024 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001025 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001026 params.userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001027 break;
1028 case "--install-location":
1029 sessionParams.installLocation = Integer.parseInt(getNextArg());
1030 break;
1031 case "--force-uuid":
1032 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
1033 sessionParams.volumeUuid = getNextArg();
1034 if ("internal".equals(sessionParams.volumeUuid)) {
1035 sessionParams.volumeUuid = null;
1036 }
1037 break;
1038 default:
1039 throw new IllegalArgumentException("Unknown option " + opt);
1040 }
1041 }
1042 return params;
1043 }
1044
Makoto Onuki4828a592016-03-15 18:06:57 -07001045 private int runSetHomeActivity() {
1046 final PrintWriter pw = getOutPrintWriter();
1047 int userId = UserHandle.USER_SYSTEM;
1048 String opt;
1049 while ((opt = getNextOption()) != null) {
1050 switch (opt) {
1051 case "--user":
1052 userId = UserHandle.parseUserArg(getNextArgRequired());
1053 break;
1054 default:
1055 pw.println("Error: Unknown option: " + opt);
1056 return 1;
1057 }
1058 }
1059
1060 String component = getNextArg();
1061 ComponentName componentName =
1062 component != null ? ComponentName.unflattenFromString(component) : null;
1063
1064 if (componentName == null) {
1065 pw.println("Error: component name not specified or invalid");
1066 return 1;
1067 }
1068
1069 try {
1070 mInterface.setHomeActivity(componentName, userId);
1071 return 0;
1072 } catch (RemoteException e) {
1073 pw.println(e.toString());
1074 return 1;
1075 }
1076 }
1077
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001078 private static String checkAbiArgument(String abi) {
1079 if (TextUtils.isEmpty(abi)) {
1080 throw new IllegalArgumentException("Missing ABI argument");
1081 }
1082
1083 if ("-".equals(abi)) {
1084 return abi;
1085 }
1086
1087 final String[] supportedAbis = Build.SUPPORTED_ABIS;
1088 for (String supportedAbi : supportedAbis) {
1089 if (supportedAbi.equals(abi)) {
1090 return abi;
1091 }
1092 }
1093
1094 throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
1095 }
1096
1097 private int translateUserId(int userId, String logContext) {
1098 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
1099 userId, true, true, logContext, "pm command");
1100 }
1101
1102 private int doCreateSession(SessionParams params, String installerPackageName, int userId)
1103 throws RemoteException {
1104 userId = translateUserId(userId, "runInstallCreate");
1105 if (userId == UserHandle.USER_ALL) {
1106 userId = UserHandle.USER_SYSTEM;
1107 params.installFlags |= PackageManager.INSTALL_ALL_USERS;
1108 }
1109
1110 final int sessionId = mInterface.getPackageInstaller()
1111 .createSession(params, installerPackageName, userId);
1112 return sessionId;
1113 }
1114
Todd Kennedyeb9b0532016-03-08 10:10:54 -08001115 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001116 boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001117 final PrintWriter pw = getOutPrintWriter();
1118 if ("-".equals(inPath)) {
1119 inPath = null;
1120 } else if (inPath != null) {
1121 final File file = new File(inPath);
1122 if (file.isFile()) {
1123 sizeBytes = file.length();
1124 }
1125 }
1126
1127 final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId);
1128
1129 PackageInstaller.Session session = null;
1130 InputStream in = null;
1131 OutputStream out = null;
1132 try {
1133 session = new PackageInstaller.Session(
1134 mInterface.getPackageInstaller().openSession(sessionId));
1135
1136 if (inPath != null) {
1137 in = new FileInputStream(inPath);
1138 } else {
Dianne Hackborn2e931f52016-01-28 12:21:17 -08001139 in = new SizedInputStream(getRawInputStream(), sizeBytes);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001140 }
1141 out = session.openWrite(splitName, 0, sizeBytes);
1142
1143 int total = 0;
1144 byte[] buffer = new byte[65536];
1145 int c;
1146 while ((c = in.read(buffer)) != -1) {
1147 total += c;
1148 out.write(buffer, 0, c);
1149
1150 if (info.sizeBytes > 0) {
1151 final float fraction = ((float) c / (float) info.sizeBytes);
1152 session.addProgress(fraction);
1153 }
1154 }
1155 session.fsync(out);
1156
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001157 if (logSuccess) {
1158 pw.println("Success: streamed " + total + " bytes");
1159 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001160 return 0;
1161 } catch (IOException e) {
1162 pw.println("Error: failed to write; " + e.getMessage());
1163 return 1;
1164 } finally {
1165 IoUtils.closeQuietly(out);
1166 IoUtils.closeQuietly(in);
1167 IoUtils.closeQuietly(session);
1168 }
1169 }
1170
Todd Kennedyeb9b0532016-03-08 10:10:54 -08001171 private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
1172 throws RemoteException {
1173 final PrintWriter pw = getOutPrintWriter();
1174 PackageInstaller.Session session = null;
1175 try {
1176 session = new PackageInstaller.Session(
1177 mInterface.getPackageInstaller().openSession(sessionId));
1178 session.removeSplit(splitName);
1179
1180 if (logSuccess) {
1181 pw.println("Success");
1182 }
1183 return 0;
1184 } catch (IOException e) {
1185 pw.println("Error: failed to remove split; " + e.getMessage());
1186 return 1;
1187 } finally {
1188 IoUtils.closeQuietly(session);
1189 }
1190 }
1191
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001192 private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001193 final PrintWriter pw = getOutPrintWriter();
1194 PackageInstaller.Session session = null;
1195 try {
1196 session = new PackageInstaller.Session(
1197 mInterface.getPackageInstaller().openSession(sessionId));
1198
1199 final LocalIntentReceiver receiver = new LocalIntentReceiver();
1200 session.commit(receiver.getIntentSender());
1201
1202 final Intent result = receiver.getResult();
1203 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1204 PackageInstaller.STATUS_FAILURE);
1205 if (status == PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001206 if (logSuccess) {
1207 System.out.println("Success");
1208 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001209 } else {
1210 pw.println("Failure ["
1211 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001212 }
1213 return status;
1214 } finally {
1215 IoUtils.closeQuietly(session);
1216 }
1217 }
1218
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001219 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001220 final PrintWriter pw = getOutPrintWriter();
1221 PackageInstaller.Session session = null;
1222 try {
1223 session = new PackageInstaller.Session(
1224 mInterface.getPackageInstaller().openSession(sessionId));
1225 session.abandon();
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001226 if (logSuccess) {
1227 pw.println("Success");
1228 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001229 return 0;
1230 } finally {
1231 IoUtils.closeQuietly(session);
1232 }
1233 }
1234
Todd Kennedy60459ab2015-10-30 11:32:16 -07001235 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
1236 boolean summary, int startProtectionLevel, int endProtectionLevel)
1237 throws RemoteException {
1238 final PrintWriter pw = getOutPrintWriter();
1239 final int groupCount = groupList.size();
1240 for (int i = 0; i < groupCount; i++) {
1241 String groupName = groupList.get(i);
1242 String prefix = "";
1243 if (groups) {
1244 if (i > 0) {
1245 pw.println("");
1246 }
1247 if (groupName != null) {
1248 PermissionGroupInfo pgi =
1249 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
1250 if (summary) {
1251 Resources res = getResources(pgi);
1252 if (res != null) {
1253 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
1254 } else {
1255 pw.print(pgi.name + ": ");
1256
1257 }
1258 } else {
1259 pw.println((labels ? "+ " : "") + "group:" + pgi.name);
1260 if (labels) {
1261 pw.println(" package:" + pgi.packageName);
1262 Resources res = getResources(pgi);
1263 if (res != null) {
1264 pw.println(" label:"
1265 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
1266 pw.println(" description:"
1267 + loadText(pgi, pgi.descriptionRes,
1268 pgi.nonLocalizedDescription));
1269 }
1270 }
1271 }
1272 } else {
1273 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
1274 }
1275 prefix = " ";
1276 }
1277 List<PermissionInfo> ps =
Jeff Sharkeyd5896632016-03-04 16:16:00 -07001278 mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -07001279 final int count = ps.size();
1280 boolean first = true;
1281 for (int p = 0 ; p < count ; p++) {
1282 PermissionInfo pi = ps.get(p);
1283 if (groups && groupName == null && pi.group != null) {
1284 continue;
1285 }
1286 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
1287 if (base < startProtectionLevel
1288 || base > endProtectionLevel) {
1289 continue;
1290 }
1291 if (summary) {
1292 if (first) {
1293 first = false;
1294 } else {
1295 pw.print(", ");
1296 }
1297 Resources res = getResources(pi);
1298 if (res != null) {
1299 pw.print(loadText(pi, pi.labelRes,
1300 pi.nonLocalizedLabel));
1301 } else {
1302 pw.print(pi.name);
1303 }
1304 } else {
1305 pw.println(prefix + (labels ? "+ " : "")
1306 + "permission:" + pi.name);
1307 if (labels) {
1308 pw.println(prefix + " package:" + pi.packageName);
1309 Resources res = getResources(pi);
1310 if (res != null) {
1311 pw.println(prefix + " label:"
1312 + loadText(pi, pi.labelRes,
1313 pi.nonLocalizedLabel));
1314 pw.println(prefix + " description:"
1315 + loadText(pi, pi.descriptionRes,
1316 pi.nonLocalizedDescription));
1317 }
1318 pw.println(prefix + " protectionLevel:"
1319 + PermissionInfo.protectionToString(pi.protectionLevel));
1320 }
1321 }
1322 }
1323
1324 if (summary) {
1325 pw.println("");
1326 }
1327 }
1328 }
1329
1330 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
1331 throws RemoteException {
1332 if (nonLocalized != null) {
1333 return nonLocalized.toString();
1334 }
1335 if (res != 0) {
1336 Resources r = getResources(pii);
1337 if (r != null) {
1338 try {
1339 return r.getString(res);
1340 } catch (Resources.NotFoundException e) {
1341 }
1342 }
1343 }
1344 return null;
1345 }
1346
1347 private Resources getResources(PackageItemInfo pii) throws RemoteException {
1348 Resources res = mResourceCache.get(pii.packageName);
1349 if (res != null) return res;
1350
1351 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0);
1352 AssetManager am = new AssetManager();
1353 am.addAssetPath(ai.publicSourceDir);
1354 res = new Resources(am, null, null);
1355 mResourceCache.put(pii.packageName, res);
1356 return res;
1357 }
1358
1359 @Override
1360 public void onHelp() {
1361 final PrintWriter pw = getOutPrintWriter();
1362 pw.println("Package manager (package) commands:");
1363 pw.println(" help");
1364 pw.println(" Print this help text.");
1365 pw.println("");
David Brazdilcf046952016-03-08 16:40:20 +00001366 pw.println(" compile [-m MODE] [-f] [-c] [--reset] (-a | TARGET-PACKAGE)");
David Brazdil990fb6b2016-03-01 10:02:27 +00001367 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".");
David Brazdil493411a2016-02-01 13:48:46 +00001368 pw.println(" Options:");
David Brazdil990fb6b2016-03-01 10:02:27 +00001369 pw.println(" -a: compile all packages");
David Brazdil9aa6db02016-03-08 12:57:12 +00001370 pw.println(" -c: clear profile data before compiling");
1371 pw.println(" -f: force compilation even if not needed");
David Brazdil493411a2016-02-01 13:48:46 +00001372 pw.println(" -m: select compilation mode");
David Brazdilcf046952016-03-08 16:40:20 +00001373 pw.println(" MODE can be one of \"default\", \"full\", \"profile\"," +
David Brazdilce389e52016-03-08 16:22:23 +00001374 " and \"extract\"");
David Brazdilcf046952016-03-08 16:40:20 +00001375 pw.println(" --reset: restore package to its post-install state");
David Brazdil9aa6db02016-03-08 12:57:12 +00001376 pw.println(" shorthand for \"-c -f -m extract\"");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001377 pw.println(" list features");
1378 pw.println(" Prints all features of the system.");
1379 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00001380 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001381 pw.println(" Options:");
1382 pw.println(" -f: dump the name of the .apk file containing the test package");
1383 pw.println(" list libraries");
1384 pw.println(" Prints all system libraries.");
1385 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]");
1386 pw.println(" Prints all packages; optionally only those whose name contains");
1387 pw.println(" the text in FILTER.");
1388 pw.println(" Options:");
1389 pw.println(" -f: see their associated file");
Felipe Leme3f24edf2015-11-18 15:04:13 -08001390 pw.println(" -d: filter to only show disabled packages");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001391 pw.println(" -e: filter to only show enabled packages");
1392 pw.println(" -s: filter to only show system packages");
1393 pw.println(" -3: filter to only show third party packages");
1394 pw.println(" -i: see the installer for the packages");
1395 pw.println(" -u: also include uninstalled packages");
1396 pw.println(" list permission-groups");
1397 pw.println(" Prints all known permission groups.");
1398 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
1399 pw.println(" Prints all known permissions; optionally only those in GROUP.");
1400 pw.println(" Options:");
1401 pw.println(" -g: organize by group");
1402 pw.println(" -f: print all information");
1403 pw.println(" -s: short summary");
1404 pw.println(" -d: only list dangerous permissions");
1405 pw.println(" -u: list only the permissions users will see");
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -08001406 pw.println(" resolve-activity [--user USER_ID] INTENT");
Dianne Hackborn99878e92015-12-02 16:27:41 -08001407 pw.println(" Prints the activity that resolves to the given Intent.");
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -08001408 pw.println(" query-activities [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001409 pw.println(" Prints all activities that can handle the given Intent.");
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -08001410 pw.println(" query-services [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001411 pw.println(" Prints all services that can handle the given Intent.");
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -08001412 pw.println(" query-receivers [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001413 pw.println(" Prints all broadcast receivers that can handle the given Intent.");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00001414 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE");
1415 pw.println(" Suspends the specified package (as user).");
1416 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE");
1417 pw.println(" Unsuspends the specified package (as user).");
Makoto Onuki4828a592016-03-15 18:06:57 -07001418 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
1419 pw.println(" set the default home activity (aka launcher).");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001420 pw.println();
1421 Intent.printIntentArgsHelp(pw , "");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001422 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001423
1424 private static class LocalIntentReceiver {
1425 private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
1426
1427 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
1428 @Override
1429 public int send(int code, Intent intent, String resolvedType,
1430 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
1431 try {
1432 mResult.offer(intent, 5, TimeUnit.SECONDS);
1433 } catch (InterruptedException e) {
1434 throw new RuntimeException(e);
1435 }
1436 return 0;
1437 }
1438 };
1439
1440 public IntentSender getIntentSender() {
1441 return new IntentSender((IIntentSender) mLocalSender);
1442 }
1443
1444 public Intent getResult() {
1445 try {
1446 return mResult.take();
1447 } catch (InterruptedException e) {
1448 throw new RuntimeException(e);
1449 }
1450 }
1451 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07001452}