blob: bf44b0f56325948519c016dd906274fac31b1da1 [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;
47import android.os.UserHandle;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080048import android.text.TextUtils;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080049import android.util.PrintWriterPrinter;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080050import com.android.internal.util.SizedInputStream;
51
Andreas Gampebdd30d82016-03-20 11:32:11 -070052import dalvik.system.DexFile;
53
Todd Kennedy72cfcd02015-11-03 17:08:55 -080054import libcore.io.IoUtils;
55
56import java.io.File;
57import java.io.FileInputStream;
58import java.io.IOException;
59import java.io.InputStream;
60import java.io.OutputStream;
Todd Kennedy60459ab2015-10-30 11:32:16 -070061import java.io.PrintWriter;
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080062import java.net.URISyntaxException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070063import java.util.ArrayList;
64import java.util.Collections;
65import java.util.Comparator;
66import java.util.List;
67import java.util.WeakHashMap;
Todd Kennedy72cfcd02015-11-03 17:08:55 -080068import java.util.concurrent.SynchronousQueue;
69import java.util.concurrent.TimeUnit;
Todd Kennedy60459ab2015-10-30 11:32:16 -070070
71class PackageManagerShellCommand extends ShellCommand {
72 final IPackageManager mInterface;
73 final private WeakHashMap<String, Resources> mResourceCache =
74 new WeakHashMap<String, Resources>();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -080075 int mTargetUser;
Todd Kennedy60459ab2015-10-30 11:32:16 -070076
77 PackageManagerShellCommand(PackageManagerService service) {
78 mInterface = service;
79 }
80
81 @Override
82 public int onCommand(String cmd) {
83 if (cmd == null) {
84 return handleDefaultCommands(cmd);
85 }
86
87 final PrintWriter pw = getOutPrintWriter();
88 try {
89 switch(cmd) {
Todd Kennedy72cfcd02015-11-03 17:08:55 -080090 case "install":
91 return runInstall();
92 case "install-abandon":
93 case "install-destroy":
94 return runInstallAbandon();
95 case "install-commit":
96 return runInstallCommit();
97 case "install-create":
98 return runInstallCreate();
Todd Kennedyeb9b0532016-03-08 10:10:54 -080099 case "install-remove":
100 return runInstallRemove();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800101 case "install-write":
102 return runInstallWrite();
David Brazdil493411a2016-02-01 13:48:46 +0000103 case "compile":
104 return runCompile();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700105 case "list":
106 return runList();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800107 case "uninstall":
108 return runUninstall();
Dianne Hackborn99878e92015-12-02 16:27:41 -0800109 case "resolve-activity":
110 return runResolveActivity();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800111 case "query-activities":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800112 return runQueryIntentActivities();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800113 case "query-services":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800114 return runQueryIntentServices();
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -0800115 case "query-receivers":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800116 return runQueryIntentReceivers();
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000117 case "suspend":
118 return runSuspend(true);
119 case "unsuspend":
120 return runSuspend(false);
Makoto Onuki4828a592016-03-15 18:06:57 -0700121 case "set-home-activity":
122 return runSetHomeActivity();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700123 default:
124 return handleDefaultCommands(cmd);
125 }
126 } catch (RemoteException e) {
127 pw.println("Remote exception: " + e);
128 }
129 return -1;
130 }
131
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800132 private int runInstall() throws RemoteException {
133 final PrintWriter pw = getOutPrintWriter();
134 final InstallParams params = makeInstallParams();
135 final int sessionId = doCreateSession(params.sessionParams,
136 params.installerPackageName, params.userId);
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800137 boolean abandonSession = true;
138 try {
139 final String inPath = getNextArg();
140 if (inPath == null && params.sessionParams.sizeBytes == 0) {
141 pw.println("Error: must either specify a package size or an APK file");
142 return 1;
143 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800144 if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800145 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
146 return 1;
147 }
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800148 if (doCommitSession(sessionId, false /*logSuccess*/)
149 != PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800150 return 1;
151 }
152 abandonSession = false;
Todd Kennedy50ea35f2015-12-17 14:46:39 -0800153 pw.println("Success");
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800154 return 0;
155 } finally {
156 if (abandonSession) {
157 try {
158 doAbandonSession(sessionId, false /*logSuccess*/);
159 } catch (Exception ignore) {
160 }
161 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800162 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800163 }
164
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000165 private int runSuspend(boolean suspendedState) {
166 final PrintWriter pw = getOutPrintWriter();
167 int userId = UserHandle.USER_SYSTEM;
168 String opt;
169 while ((opt = getNextOption()) != null) {
170 switch (opt) {
171 case "--user":
172 userId = UserHandle.parseUserArg(getNextArgRequired());
173 break;
174 default:
175 pw.println("Error: Unknown option: " + opt);
176 return 1;
177 }
178 }
179
180 String packageName = getNextArg();
181 if (packageName == null) {
182 pw.println("Error: package name not specified");
183 return 1;
184 }
185
186 try {
Andrei Stingaceanueb84b182016-01-26 18:39:55 +0000187 mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
188 userId);
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000189 pw.println("Package " + packageName + " new suspended state: "
Andrei Stingaceanu355b2322016-02-12 16:43:51 +0000190 + mInterface.isPackageSuspendedForUser(packageName, userId));
Andrei Stingaceanu1e283912015-11-26 15:26:28 +0000191 return 0;
192 } catch (RemoteException e) {
193 pw.println(e.toString());
194 return 1;
195 }
196 }
197
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800198 private int runInstallAbandon() throws RemoteException {
199 final int sessionId = Integer.parseInt(getNextArg());
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800200 return doAbandonSession(sessionId, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800201 }
202
203 private int runInstallCommit() throws RemoteException {
204 final int sessionId = Integer.parseInt(getNextArg());
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800205 return doCommitSession(sessionId, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800206 }
207
208 private int runInstallCreate() throws RemoteException {
209 final PrintWriter pw = getOutPrintWriter();
210 final InstallParams installParams = makeInstallParams();
211 final int sessionId = doCreateSession(installParams.sessionParams,
212 installParams.installerPackageName, installParams.userId);
213
214 // NOTE: adb depends on parsing this string
215 pw.println("Success: created install session [" + sessionId + "]");
216 return 0;
217 }
218
219 private int runInstallWrite() throws RemoteException {
220 long sizeBytes = -1;
221
222 String opt;
223 while ((opt = getNextOption()) != null) {
224 if (opt.equals("-S")) {
225 sizeBytes = Long.parseLong(getNextArg());
226 } else {
227 throw new IllegalArgumentException("Unknown option: " + opt);
228 }
229 }
230
231 final int sessionId = Integer.parseInt(getNextArg());
232 final String splitName = getNextArg();
233 final String path = getNextArg();
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800234 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
235 }
236
237 private int runInstallRemove() throws RemoteException {
238 final PrintWriter pw = getOutPrintWriter();
239
240 final int sessionId = Integer.parseInt(getNextArg());
241
242 final String splitName = getNextArg();
243 if (splitName == null) {
244 pw.println("Error: split name not specified");
245 return 1;
246 }
247 return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800248 }
249
David Brazdil493411a2016-02-01 13:48:46 +0000250 private int runCompile() throws RemoteException {
251 final PrintWriter pw = getOutPrintWriter();
252 boolean useJitProfiles = false;
David Brazdil493411a2016-02-01 13:48:46 +0000253 boolean forceCompilation = false;
David Brazdil990fb6b2016-03-01 10:02:27 +0000254 boolean allPackages = false;
David Brazdil9aa6db02016-03-08 12:57:12 +0000255 boolean clearProfileData = false;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700256 String compilerFilter = null;
257 String compilationReason = null;
258
259 if (peekNextArg() == null) {
260 // No arguments, show help.
261 pw.println("Usage: cmd package compile [-c] [-f] [--reset] [-m mode] " +
262 "[-r reason] [-a|pkg]");
263 pw.println();
264 pw.println(" -c Clear profile data");
265 pw.println(" -f Force compilation");
266 pw.println(" --reset Reset package");
267 pw.println(" -m mode Compilation mode, one of the dex2oat compiler filters");
268 pw.println(" verify-none");
269 pw.println(" verify-at-runtime");
270 pw.println(" verify-profile");
271 pw.println(" interpret-only");
272 pw.println(" space-profile");
273 pw.println(" space");
274 pw.println(" speed-profile");
275 pw.println(" speed");
276 pw.println(" everything");
277 pw.println(" -r reason Compiler reason, one of the package manager reasons");
278 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
279 pw.println(" " +
280 PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
281 }
282 pw.println(" -a Apply to all packages");
283 return 1;
284 }
David Brazdil493411a2016-02-01 13:48:46 +0000285
286 String opt;
287 while ((opt = getNextOption()) != null) {
288 switch (opt) {
David Brazdil990fb6b2016-03-01 10:02:27 +0000289 case "-a":
290 allPackages = true;
291 break;
David Brazdil9aa6db02016-03-08 12:57:12 +0000292 case "-c":
293 clearProfileData = true;
David Brazdil493411a2016-02-01 13:48:46 +0000294 break;
295 case "-f":
296 forceCompilation = true;
297 break;
David Brazdil9aa6db02016-03-08 12:57:12 +0000298 case "-m":
Andreas Gampebdd30d82016-03-20 11:32:11 -0700299 compilerFilter = getNextArgRequired();
300 break;
301 case "-r":
302 compilationReason = getNextArgRequired();
David Brazdil9aa6db02016-03-08 12:57:12 +0000303 break;
304 case "--reset":
305 forceCompilation = true;
306 clearProfileData = true;
Andreas Gampebdd30d82016-03-20 11:32:11 -0700307 compilerFilter = "reset";
David Brazdil9aa6db02016-03-08 12:57:12 +0000308 break;
David Brazdil493411a2016-02-01 13:48:46 +0000309 default:
310 pw.println("Error: Unknown option: " + opt);
311 return 1;
312 }
313 }
314
Andreas Gampebdd30d82016-03-20 11:32:11 -0700315 if (compilerFilter != null && compilationReason != null) {
316 pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " +
317 "at the same time");
318 return 1;
David Brazdil493411a2016-02-01 13:48:46 +0000319 }
Andreas Gampebdd30d82016-03-20 11:32:11 -0700320 if (compilerFilter == null && compilationReason == null) {
321 pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " +
322 "reason (\"-r\") at the same time");
323 return 1;
324 }
325
326 String targetCompilerFilter;
327 if (compilerFilter != null) {
328 // Specially recognize default and reset. Otherwise, only accept valid modes.
329 if ("default".equals(compilerFilter)) {
330 // Use the default mode for background dexopt.
331 targetCompilerFilter =
332 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
Andreas Gampe43fc2442016-03-24 20:13:34 -0700333 PackageManagerService.REASON_BACKGROUND_DEXOPT);
Andreas Gampebdd30d82016-03-20 11:32:11 -0700334 } else if ("reset".equals(compilerFilter)) {
335 // Use the default mode for install.
336 targetCompilerFilter =
337 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
Andreas Gampe43fc2442016-03-24 20:13:34 -0700338 PackageManagerService.REASON_INSTALL);
Andreas Gampebdd30d82016-03-20 11:32:11 -0700339 } else {
340 if (!DexFile.isValidCompilerFilter(compilerFilter)) {
341 pw.println("Error: \"" + compilerFilter +
342 "\" is not a valid compilation filter.");
343 return 1;
344 }
345 targetCompilerFilter = compilerFilter;
346 }
347 } else {
348 int reason = -1;
349 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
350 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
351 compilationReason)) {
352 reason = i;
353 break;
354 }
355 }
356 if (reason == -1) {
357 pw.println("Error: Unknown compilation reason: " + compilationReason);
358 return 1;
359 }
360 targetCompilerFilter =
361 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
362 }
363
David Brazdil493411a2016-02-01 13:48:46 +0000364
David Brazdil990fb6b2016-03-01 10:02:27 +0000365 List<String> packageNames = null;
366 if (allPackages) {
367 packageNames = mInterface.getAllPackages();
368 } else {
369 String packageName = getNextArg();
370 if (packageName == null) {
371 pw.println("Error: package name not specified");
372 return 1;
373 }
374 packageNames = Collections.singletonList(packageName);
David Brazdil493411a2016-02-01 13:48:46 +0000375 }
376
David Brazdil990fb6b2016-03-01 10:02:27 +0000377 List<String> failedPackages = new ArrayList<>();
378 for (String packageName : packageNames) {
David Brazdil9aa6db02016-03-08 12:57:12 +0000379 if (clearProfileData) {
380 mInterface.clearApplicationProfileData(packageName);
381 }
382
Andreas Gampebdd30d82016-03-20 11:32:11 -0700383 boolean result = mInterface.performDexOptMode(packageName, null /* instructionSet */,
384 useJitProfiles, targetCompilerFilter, forceCompilation);
David Brazdil990fb6b2016-03-01 10:02:27 +0000385 if (!result) {
386 failedPackages.add(packageName);
387 }
388 }
389
390 if (failedPackages.isEmpty()) {
David Brazdil493411a2016-02-01 13:48:46 +0000391 pw.println("Success");
392 return 0;
David Brazdil990fb6b2016-03-01 10:02:27 +0000393 } else if (failedPackages.size() == 1) {
394 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
395 return 1;
David Brazdil493411a2016-02-01 13:48:46 +0000396 } else {
David Brazdil990fb6b2016-03-01 10:02:27 +0000397 pw.print("Failure: the following packages could not be compiled: ");
398 boolean is_first = true;
399 for (String packageName : failedPackages) {
400 if (is_first) {
401 is_first = false;
402 } else {
403 pw.print(", ");
404 }
405 pw.print(packageName);
406 }
407 pw.println();
David Brazdil493411a2016-02-01 13:48:46 +0000408 return 1;
409 }
410 }
411
Todd Kennedy60459ab2015-10-30 11:32:16 -0700412 private int runList() throws RemoteException {
413 final PrintWriter pw = getOutPrintWriter();
414 final String type = getNextArg();
415 if (type == null) {
416 pw.println("Error: didn't specify type of data to list");
417 return -1;
418 }
419 switch(type) {
420 case "features":
421 return runListFeatures();
422 case "instrumentation":
423 return runListInstrumentation();
424 case "libraries":
425 return runListLibraries();
426 case "package":
427 case "packages":
428 return runListPackages(false /*showSourceDir*/);
429 case "permission-groups":
430 return runListPermissionGroups();
431 case "permissions":
432 return runListPermissions();
433 }
434 pw.println("Error: unknown list type '" + type + "'");
435 return -1;
436 }
437
438 private int runListFeatures() throws RemoteException {
439 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700440 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700441
442 // sort by name
443 Collections.sort(list, new Comparator<FeatureInfo>() {
444 public int compare(FeatureInfo o1, FeatureInfo o2) {
445 if (o1.name == o2.name) return 0;
446 if (o1.name == null) return -1;
447 if (o2.name == null) return 1;
448 return o1.name.compareTo(o2.name);
449 }
450 });
451
452 final int count = (list != null) ? list.size() : 0;
453 for (int p = 0; p < count; p++) {
454 FeatureInfo fi = list.get(p);
455 pw.print("feature:");
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700456 if (fi.name != null) {
457 pw.print(fi.name);
458 if (fi.version > 0) {
459 pw.print("=");
460 pw.print(fi.version);
461 }
462 pw.println();
463 } else {
464 pw.println("reqGlEsVersion=0x"
Todd Kennedy60459ab2015-10-30 11:32:16 -0700465 + Integer.toHexString(fi.reqGlEsVersion));
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700466 }
Todd Kennedy60459ab2015-10-30 11:32:16 -0700467 }
468 return 0;
469 }
470
471 private int runListInstrumentation() throws RemoteException {
472 final PrintWriter pw = getOutPrintWriter();
473 boolean showSourceDir = false;
474 String targetPackage = null;
475
476 try {
477 String opt;
478 while ((opt = getNextArg()) != null) {
479 switch (opt) {
480 case "-f":
481 showSourceDir = true;
482 break;
483 default:
484 if (opt.charAt(0) != '-') {
485 targetPackage = opt;
486 } else {
487 pw.println("Error: Unknown option: " + opt);
488 return -1;
489 }
490 break;
491 }
492 }
493 } catch (RuntimeException ex) {
494 pw.println("Error: " + ex.toString());
495 return -1;
496 }
497
498 final List<InstrumentationInfo> list =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700499 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700500
501 // sort by target package
502 Collections.sort(list, new Comparator<InstrumentationInfo>() {
503 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
504 return o1.targetPackage.compareTo(o2.targetPackage);
505 }
506 });
507
508 final int count = (list != null) ? list.size() : 0;
509 for (int p = 0; p < count; p++) {
510 final InstrumentationInfo ii = list.get(p);
511 pw.print("instrumentation:");
512 if (showSourceDir) {
513 pw.print(ii.sourceDir);
514 pw.print("=");
515 }
516 final ComponentName cn = new ComponentName(ii.packageName, ii.name);
517 pw.print(cn.flattenToShortString());
518 pw.print(" (target=");
519 pw.print(ii.targetPackage);
520 pw.println(")");
521 }
522 return 0;
523 }
524
525 private int runListLibraries() throws RemoteException {
526 final PrintWriter pw = getOutPrintWriter();
527 final List<String> list = new ArrayList<String>();
528 final String[] rawList = mInterface.getSystemSharedLibraryNames();
529 for (int i = 0; i < rawList.length; i++) {
530 list.add(rawList[i]);
531 }
532
533 // sort by name
534 Collections.sort(list, new Comparator<String>() {
535 public int compare(String o1, String o2) {
536 if (o1 == o2) return 0;
537 if (o1 == null) return -1;
538 if (o2 == null) return 1;
539 return o1.compareTo(o2);
540 }
541 });
542
543 final int count = (list != null) ? list.size() : 0;
544 for (int p = 0; p < count; p++) {
545 String lib = list.get(p);
546 pw.print("library:");
547 pw.println(lib);
548 }
549 return 0;
550 }
551
552 private int runListPackages(boolean showSourceDir) throws RemoteException {
553 final PrintWriter pw = getOutPrintWriter();
554 int getFlags = 0;
555 boolean listDisabled = false, listEnabled = false;
556 boolean listSystem = false, listThirdParty = false;
557 boolean listInstaller = false;
558 int userId = UserHandle.USER_SYSTEM;
559 try {
560 String opt;
561 while ((opt = getNextOption()) != null) {
562 switch (opt) {
563 case "-d":
564 listDisabled = true;
565 break;
566 case "-e":
567 listEnabled = true;
568 break;
569 case "-f":
570 showSourceDir = true;
571 break;
572 case "-i":
573 listInstaller = true;
574 break;
575 case "-l":
576 // old compat
577 break;
578 case "-lf":
579 showSourceDir = true;
580 break;
581 case "-s":
582 listSystem = true;
583 break;
584 case "-u":
585 getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
586 break;
587 case "-3":
588 listThirdParty = true;
589 break;
590 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800591 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy60459ab2015-10-30 11:32:16 -0700592 break;
593 default:
594 pw.println("Error: Unknown option: " + opt);
595 return -1;
596 }
597 }
598 } catch (RuntimeException ex) {
599 pw.println("Error: " + ex.toString());
600 return -1;
601 }
602
603 final String filter = getNextArg();
604
605 @SuppressWarnings("unchecked")
606 final ParceledListSlice<PackageInfo> slice =
607 mInterface.getInstalledPackages(getFlags, userId);
608 final List<PackageInfo> packages = slice.getList();
609
610 final int count = packages.size();
611 for (int p = 0; p < count; p++) {
612 final PackageInfo info = packages.get(p);
613 if (filter != null && !info.packageName.contains(filter)) {
614 continue;
615 }
616 final boolean isSystem =
617 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
618 if ((!listDisabled || !info.applicationInfo.enabled) &&
619 (!listEnabled || info.applicationInfo.enabled) &&
620 (!listSystem || isSystem) &&
621 (!listThirdParty || !isSystem)) {
622 pw.print("package:");
623 if (showSourceDir) {
624 pw.print(info.applicationInfo.sourceDir);
625 pw.print("=");
626 }
627 pw.print(info.packageName);
628 if (listInstaller) {
629 pw.print(" installer=");
630 pw.print(mInterface.getInstallerPackageName(info.packageName));
631 }
632 pw.println();
633 }
634 }
635 return 0;
636 }
637
638 private int runListPermissionGroups() throws RemoteException {
639 final PrintWriter pw = getOutPrintWriter();
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700640 final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700641
642 final int count = pgs.size();
643 for (int p = 0; p < count ; p++) {
644 final PermissionGroupInfo pgi = pgs.get(p);
645 pw.print("permission group:");
646 pw.println(pgi.name);
647 }
648 return 0;
649 }
650
651 private int runListPermissions() throws RemoteException {
652 final PrintWriter pw = getOutPrintWriter();
653 boolean labels = false;
654 boolean groups = false;
655 boolean userOnly = false;
656 boolean summary = false;
657 boolean dangerousOnly = false;
658 String opt;
659 while ((opt = getNextOption()) != null) {
660 switch (opt) {
661 case "-d":
662 dangerousOnly = true;
663 break;
664 case "-f":
665 labels = true;
666 break;
667 case "-g":
668 groups = true;
669 break;
670 case "-s":
671 groups = true;
672 labels = true;
673 summary = true;
674 break;
675 case "-u":
676 userOnly = true;
677 break;
678 default:
679 pw.println("Error: Unknown option: " + opt);
680 return 1;
681 }
682 }
683
684 final ArrayList<String> groupList = new ArrayList<String>();
685 if (groups) {
686 final List<PermissionGroupInfo> infos =
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700687 mInterface.getAllPermissionGroups(0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -0700688 final int count = infos.size();
689 for (int i = 0; i < count; i++) {
690 groupList.add(infos.get(i).name);
691 }
692 groupList.add(null);
693 } else {
694 final String grp = getNextArg();
695 groupList.add(grp);
696 }
697
698 if (dangerousOnly) {
699 pw.println("Dangerous Permissions:");
700 pw.println("");
701 doListPermissions(groupList, groups, labels, summary,
702 PermissionInfo.PROTECTION_DANGEROUS,
703 PermissionInfo.PROTECTION_DANGEROUS);
704 if (userOnly) {
705 pw.println("Normal Permissions:");
706 pw.println("");
707 doListPermissions(groupList, groups, labels, summary,
708 PermissionInfo.PROTECTION_NORMAL,
709 PermissionInfo.PROTECTION_NORMAL);
710 }
711 } else if (userOnly) {
712 pw.println("Dangerous and Normal Permissions:");
713 pw.println("");
714 doListPermissions(groupList, groups, labels, summary,
715 PermissionInfo.PROTECTION_NORMAL,
716 PermissionInfo.PROTECTION_DANGEROUS);
717 } else {
718 pw.println("All Permissions:");
719 pw.println("");
720 doListPermissions(groupList, groups, labels, summary,
721 -10000, 10000);
722 }
723 return 0;
724 }
725
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800726 private int runUninstall() throws RemoteException {
727 final PrintWriter pw = getOutPrintWriter();
728 int flags = 0;
729 int userId = UserHandle.USER_ALL;
730
731 String opt;
732 while ((opt = getNextOption()) != null) {
733 switch (opt) {
734 case "-k":
735 flags |= PackageManager.DELETE_KEEP_DATA;
736 break;
737 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800738 userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800739 break;
740 default:
741 pw.println("Error: Unknown option: " + opt);
742 return 1;
743 }
744 }
745
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800746 final String packageName = getNextArg();
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800747 if (packageName == null) {
748 pw.println("Error: package name not specified");
749 return 1;
750 }
751
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800752 // if a split is specified, just remove it and not the whole package
753 final String splitName = getNextArg();
754 if (splitName != null) {
755 return runRemoveSplit(packageName, splitName);
756 }
757
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800758 userId = translateUserId(userId, "runUninstall");
759 if (userId == UserHandle.USER_ALL) {
760 userId = UserHandle.USER_SYSTEM;
761 flags |= PackageManager.DELETE_ALL_USERS;
762 } else {
763 final PackageInfo info = mInterface.getPackageInfo(packageName, 0, userId);
764 if (info == null) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -0800765 pw.println("Failure [not installed for " + userId + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800766 return 1;
767 }
768 final boolean isSystem =
769 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
770 // If we are being asked to delete a system app for just one
771 // user set flag so it disables rather than reverting to system
772 // version of the app.
773 if (isSystem) {
774 flags |= PackageManager.DELETE_SYSTEM_APP;
775 }
776 }
777
778 final LocalIntentReceiver receiver = new LocalIntentReceiver();
779 mInterface.getPackageInstaller().uninstall(packageName, null /*callerPackageName*/, flags,
780 receiver.getIntentSender(), userId);
781
782 final Intent result = receiver.getResult();
783 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
784 PackageInstaller.STATUS_FAILURE);
785 if (status == PackageInstaller.STATUS_SUCCESS) {
786 pw.println("Success");
787 return 0;
788 } else {
789 pw.println("Failure ["
790 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
791 return 1;
792 }
793 }
794
Todd Kennedyeb9b0532016-03-08 10:10:54 -0800795 private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
796 final PrintWriter pw = getOutPrintWriter();
797 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
798 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
799 sessionParams.appPackageName = packageName;
800 final int sessionId =
801 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
802 boolean abandonSession = true;
803 try {
804 if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
805 != PackageInstaller.STATUS_SUCCESS) {
806 return 1;
807 }
808 if (doCommitSession(sessionId, false /*logSuccess*/)
809 != PackageInstaller.STATUS_SUCCESS) {
810 return 1;
811 }
812 abandonSession = false;
813 pw.println("Success");
814 return 0;
815 } finally {
816 if (abandonSession) {
817 try {
818 doAbandonSession(sessionId, false /*logSuccess*/);
819 } catch (Exception ignore) {
820 }
821 }
822 }
823 }
824
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800825 private Intent parseIntentAndUser() throws URISyntaxException {
826 mTargetUser = UserHandle.USER_CURRENT;
827 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
828 @Override
829 public boolean handleOption(String opt, ShellCommand cmd) {
830 if ("--user".equals(opt)) {
831 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
832 return true;
833 }
834 return false;
835 }
836 });
837 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
838 Binder.getCallingUid(), mTargetUser, false, false, null, null);
839 return intent;
840 }
841
Dianne Hackborn99878e92015-12-02 16:27:41 -0800842 private int runResolveActivity() {
843 Intent intent;
844 try {
845 intent = parseIntentAndUser();
846 } catch (URISyntaxException e) {
847 throw new RuntimeException(e.getMessage(), e);
848 }
849 try {
850 ResolveInfo ri = mInterface.resolveIntent(intent, null, 0, mTargetUser);
851 PrintWriter pw = getOutPrintWriter();
852 if (ri == null) {
853 pw.println("No activity found");
854 } else {
855 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
856 ri.dump(pr, "");
857 }
858 } catch (RemoteException e) {
859 throw new RuntimeException("Failed calling service", e);
860 }
861 return 0;
862 }
863
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800864 private int runQueryIntentActivities() {
865 Intent intent;
866 try {
867 intent = parseIntentAndUser();
868 } catch (URISyntaxException e) {
869 throw new RuntimeException(e.getMessage(), e);
870 }
871 try {
872 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700873 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800874 PrintWriter pw = getOutPrintWriter();
875 if (result == null || result.size() <= 0) {
876 pw.println("No activities found");
877 } else {
878 pw.print(result.size()); pw.println(" activities found:");
879 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
880 for (int i=0; i<result.size(); i++) {
881 pw.print(" Activity #"); pw.print(i); pw.println(":");
882 result.get(i).dump(pr, " ");
883 }
884 }
885 } catch (RemoteException e) {
886 throw new RuntimeException("Failed calling service", e);
887 }
888 return 0;
889 }
890
891 private int runQueryIntentServices() {
892 Intent intent;
893 try {
894 intent = parseIntentAndUser();
895 } catch (URISyntaxException e) {
896 throw new RuntimeException(e.getMessage(), e);
897 }
898 try {
899 List<ResolveInfo> result = mInterface.queryIntentServices(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700900 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800901 PrintWriter pw = getOutPrintWriter();
902 if (result == null || result.size() <= 0) {
903 pw.println("No services found");
904 } else {
905 pw.print(result.size()); pw.println(" services found:");
906 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
907 for (int i=0; i<result.size(); i++) {
908 pw.print(" Service #"); pw.print(i); pw.println(":");
909 result.get(i).dump(pr, " ");
910 }
911 }
912 } catch (RemoteException e) {
913 throw new RuntimeException("Failed calling service", e);
914 }
915 return 0;
916 }
917
918 private int runQueryIntentReceivers() {
919 Intent intent;
920 try {
921 intent = parseIntentAndUser();
922 } catch (URISyntaxException e) {
923 throw new RuntimeException(e.getMessage(), e);
924 }
925 try {
926 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, null, 0,
Jeff Sharkeyd5896632016-03-04 16:16:00 -0700927 mTargetUser).getList();
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -0800928 PrintWriter pw = getOutPrintWriter();
929 if (result == null || result.size() <= 0) {
930 pw.println("No receivers found");
931 } else {
932 pw.print(result.size()); pw.println(" receivers found:");
933 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
934 for (int i=0; i<result.size(); i++) {
935 pw.print(" Receiver #"); pw.print(i); pw.println(":");
936 result.get(i).dump(pr, " ");
937 }
938 }
939 } catch (RemoteException e) {
940 throw new RuntimeException("Failed calling service", e);
941 }
942 return 0;
943 }
944
Todd Kennedy72cfcd02015-11-03 17:08:55 -0800945 private static class InstallParams {
946 SessionParams sessionParams;
947 String installerPackageName;
948 int userId = UserHandle.USER_ALL;
949 }
950
951 private InstallParams makeInstallParams() {
952 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
953 final InstallParams params = new InstallParams();
954 params.sessionParams = sessionParams;
955 String opt;
956 while ((opt = getNextOption()) != null) {
957 switch (opt) {
958 case "-l":
959 sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
960 break;
961 case "-r":
962 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
963 break;
964 case "-i":
965 params.installerPackageName = getNextArg();
966 if (params.installerPackageName == null) {
967 throw new IllegalArgumentException("Missing installer package");
968 }
969 break;
970 case "-t":
971 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
972 break;
973 case "-s":
974 sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL;
975 break;
976 case "-f":
977 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
978 break;
979 case "-d":
980 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
981 break;
982 case "-g":
983 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
984 break;
985 case "--originating-uri":
986 sessionParams.originatingUri = Uri.parse(getNextArg());
987 break;
988 case "--referrer":
989 sessionParams.referrerUri = Uri.parse(getNextArg());
990 break;
991 case "-p":
992 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
993 sessionParams.appPackageName = getNextArg();
994 if (sessionParams.appPackageName == null) {
995 throw new IllegalArgumentException("Missing inherit package name");
996 }
997 break;
998 case "-S":
999 sessionParams.setSize(Long.parseLong(getNextArg()));
1000 break;
1001 case "--abi":
1002 sessionParams.abiOverride = checkAbiArgument(getNextArg());
1003 break;
Todd Kennedy2699f062015-11-20 13:07:17 -08001004 case "--ephemeral":
1005 sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL;
1006 break;
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001007 case "--user":
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001008 params.userId = UserHandle.parseUserArg(getNextArgRequired());
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001009 break;
1010 case "--install-location":
1011 sessionParams.installLocation = Integer.parseInt(getNextArg());
1012 break;
1013 case "--force-uuid":
1014 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
1015 sessionParams.volumeUuid = getNextArg();
1016 if ("internal".equals(sessionParams.volumeUuid)) {
1017 sessionParams.volumeUuid = null;
1018 }
1019 break;
1020 default:
1021 throw new IllegalArgumentException("Unknown option " + opt);
1022 }
1023 }
1024 return params;
1025 }
1026
Makoto Onuki4828a592016-03-15 18:06:57 -07001027 private int runSetHomeActivity() {
1028 final PrintWriter pw = getOutPrintWriter();
1029 int userId = UserHandle.USER_SYSTEM;
1030 String opt;
1031 while ((opt = getNextOption()) != null) {
1032 switch (opt) {
1033 case "--user":
1034 userId = UserHandle.parseUserArg(getNextArgRequired());
1035 break;
1036 default:
1037 pw.println("Error: Unknown option: " + opt);
1038 return 1;
1039 }
1040 }
1041
1042 String component = getNextArg();
1043 ComponentName componentName =
1044 component != null ? ComponentName.unflattenFromString(component) : null;
1045
1046 if (componentName == null) {
1047 pw.println("Error: component name not specified or invalid");
1048 return 1;
1049 }
1050
1051 try {
1052 mInterface.setHomeActivity(componentName, userId);
1053 return 0;
1054 } catch (RemoteException e) {
1055 pw.println(e.toString());
1056 return 1;
1057 }
1058 }
1059
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001060 private static String checkAbiArgument(String abi) {
1061 if (TextUtils.isEmpty(abi)) {
1062 throw new IllegalArgumentException("Missing ABI argument");
1063 }
1064
1065 if ("-".equals(abi)) {
1066 return abi;
1067 }
1068
1069 final String[] supportedAbis = Build.SUPPORTED_ABIS;
1070 for (String supportedAbi : supportedAbis) {
1071 if (supportedAbi.equals(abi)) {
1072 return abi;
1073 }
1074 }
1075
1076 throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
1077 }
1078
1079 private int translateUserId(int userId, String logContext) {
1080 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
1081 userId, true, true, logContext, "pm command");
1082 }
1083
1084 private int doCreateSession(SessionParams params, String installerPackageName, int userId)
1085 throws RemoteException {
1086 userId = translateUserId(userId, "runInstallCreate");
1087 if (userId == UserHandle.USER_ALL) {
1088 userId = UserHandle.USER_SYSTEM;
1089 params.installFlags |= PackageManager.INSTALL_ALL_USERS;
1090 }
1091
1092 final int sessionId = mInterface.getPackageInstaller()
1093 .createSession(params, installerPackageName, userId);
1094 return sessionId;
1095 }
1096
Todd Kennedyeb9b0532016-03-08 10:10:54 -08001097 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001098 boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001099 final PrintWriter pw = getOutPrintWriter();
1100 if ("-".equals(inPath)) {
1101 inPath = null;
1102 } else if (inPath != null) {
1103 final File file = new File(inPath);
1104 if (file.isFile()) {
1105 sizeBytes = file.length();
1106 }
1107 }
1108
1109 final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId);
1110
1111 PackageInstaller.Session session = null;
1112 InputStream in = null;
1113 OutputStream out = null;
1114 try {
1115 session = new PackageInstaller.Session(
1116 mInterface.getPackageInstaller().openSession(sessionId));
1117
1118 if (inPath != null) {
1119 in = new FileInputStream(inPath);
1120 } else {
Dianne Hackborn2e931f52016-01-28 12:21:17 -08001121 in = new SizedInputStream(getRawInputStream(), sizeBytes);
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001122 }
1123 out = session.openWrite(splitName, 0, sizeBytes);
1124
1125 int total = 0;
1126 byte[] buffer = new byte[65536];
1127 int c;
1128 while ((c = in.read(buffer)) != -1) {
1129 total += c;
1130 out.write(buffer, 0, c);
1131
1132 if (info.sizeBytes > 0) {
1133 final float fraction = ((float) c / (float) info.sizeBytes);
1134 session.addProgress(fraction);
1135 }
1136 }
1137 session.fsync(out);
1138
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001139 if (logSuccess) {
1140 pw.println("Success: streamed " + total + " bytes");
1141 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001142 return 0;
1143 } catch (IOException e) {
1144 pw.println("Error: failed to write; " + e.getMessage());
1145 return 1;
1146 } finally {
1147 IoUtils.closeQuietly(out);
1148 IoUtils.closeQuietly(in);
1149 IoUtils.closeQuietly(session);
1150 }
1151 }
1152
Todd Kennedyeb9b0532016-03-08 10:10:54 -08001153 private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
1154 throws RemoteException {
1155 final PrintWriter pw = getOutPrintWriter();
1156 PackageInstaller.Session session = null;
1157 try {
1158 session = new PackageInstaller.Session(
1159 mInterface.getPackageInstaller().openSession(sessionId));
1160 session.removeSplit(splitName);
1161
1162 if (logSuccess) {
1163 pw.println("Success");
1164 }
1165 return 0;
1166 } catch (IOException e) {
1167 pw.println("Error: failed to remove split; " + e.getMessage());
1168 return 1;
1169 } finally {
1170 IoUtils.closeQuietly(session);
1171 }
1172 }
1173
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001174 private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001175 final PrintWriter pw = getOutPrintWriter();
1176 PackageInstaller.Session session = null;
1177 try {
1178 session = new PackageInstaller.Session(
1179 mInterface.getPackageInstaller().openSession(sessionId));
1180
1181 final LocalIntentReceiver receiver = new LocalIntentReceiver();
1182 session.commit(receiver.getIntentSender());
1183
1184 final Intent result = receiver.getResult();
1185 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1186 PackageInstaller.STATUS_FAILURE);
1187 if (status == PackageInstaller.STATUS_SUCCESS) {
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001188 if (logSuccess) {
1189 System.out.println("Success");
1190 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001191 } else {
1192 pw.println("Failure ["
1193 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001194 }
1195 return status;
1196 } finally {
1197 IoUtils.closeQuietly(session);
1198 }
1199 }
1200
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001201 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001202 final PrintWriter pw = getOutPrintWriter();
1203 PackageInstaller.Session session = null;
1204 try {
1205 session = new PackageInstaller.Session(
1206 mInterface.getPackageInstaller().openSession(sessionId));
1207 session.abandon();
Todd Kennedy8d9366c2015-12-16 13:47:14 -08001208 if (logSuccess) {
1209 pw.println("Success");
1210 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001211 return 0;
1212 } finally {
1213 IoUtils.closeQuietly(session);
1214 }
1215 }
1216
Todd Kennedy60459ab2015-10-30 11:32:16 -07001217 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
1218 boolean summary, int startProtectionLevel, int endProtectionLevel)
1219 throws RemoteException {
1220 final PrintWriter pw = getOutPrintWriter();
1221 final int groupCount = groupList.size();
1222 for (int i = 0; i < groupCount; i++) {
1223 String groupName = groupList.get(i);
1224 String prefix = "";
1225 if (groups) {
1226 if (i > 0) {
1227 pw.println("");
1228 }
1229 if (groupName != null) {
1230 PermissionGroupInfo pgi =
1231 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
1232 if (summary) {
1233 Resources res = getResources(pgi);
1234 if (res != null) {
1235 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
1236 } else {
1237 pw.print(pgi.name + ": ");
1238
1239 }
1240 } else {
1241 pw.println((labels ? "+ " : "") + "group:" + pgi.name);
1242 if (labels) {
1243 pw.println(" package:" + pgi.packageName);
1244 Resources res = getResources(pgi);
1245 if (res != null) {
1246 pw.println(" label:"
1247 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
1248 pw.println(" description:"
1249 + loadText(pgi, pgi.descriptionRes,
1250 pgi.nonLocalizedDescription));
1251 }
1252 }
1253 }
1254 } else {
1255 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
1256 }
1257 prefix = " ";
1258 }
1259 List<PermissionInfo> ps =
Jeff Sharkeyd5896632016-03-04 16:16:00 -07001260 mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
Todd Kennedy60459ab2015-10-30 11:32:16 -07001261 final int count = ps.size();
1262 boolean first = true;
1263 for (int p = 0 ; p < count ; p++) {
1264 PermissionInfo pi = ps.get(p);
1265 if (groups && groupName == null && pi.group != null) {
1266 continue;
1267 }
1268 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
1269 if (base < startProtectionLevel
1270 || base > endProtectionLevel) {
1271 continue;
1272 }
1273 if (summary) {
1274 if (first) {
1275 first = false;
1276 } else {
1277 pw.print(", ");
1278 }
1279 Resources res = getResources(pi);
1280 if (res != null) {
1281 pw.print(loadText(pi, pi.labelRes,
1282 pi.nonLocalizedLabel));
1283 } else {
1284 pw.print(pi.name);
1285 }
1286 } else {
1287 pw.println(prefix + (labels ? "+ " : "")
1288 + "permission:" + pi.name);
1289 if (labels) {
1290 pw.println(prefix + " package:" + pi.packageName);
1291 Resources res = getResources(pi);
1292 if (res != null) {
1293 pw.println(prefix + " label:"
1294 + loadText(pi, pi.labelRes,
1295 pi.nonLocalizedLabel));
1296 pw.println(prefix + " description:"
1297 + loadText(pi, pi.descriptionRes,
1298 pi.nonLocalizedDescription));
1299 }
1300 pw.println(prefix + " protectionLevel:"
1301 + PermissionInfo.protectionToString(pi.protectionLevel));
1302 }
1303 }
1304 }
1305
1306 if (summary) {
1307 pw.println("");
1308 }
1309 }
1310 }
1311
1312 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
1313 throws RemoteException {
1314 if (nonLocalized != null) {
1315 return nonLocalized.toString();
1316 }
1317 if (res != 0) {
1318 Resources r = getResources(pii);
1319 if (r != null) {
1320 try {
1321 return r.getString(res);
1322 } catch (Resources.NotFoundException e) {
1323 }
1324 }
1325 }
1326 return null;
1327 }
1328
1329 private Resources getResources(PackageItemInfo pii) throws RemoteException {
1330 Resources res = mResourceCache.get(pii.packageName);
1331 if (res != null) return res;
1332
1333 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0);
1334 AssetManager am = new AssetManager();
1335 am.addAssetPath(ai.publicSourceDir);
1336 res = new Resources(am, null, null);
1337 mResourceCache.put(pii.packageName, res);
1338 return res;
1339 }
1340
1341 @Override
1342 public void onHelp() {
1343 final PrintWriter pw = getOutPrintWriter();
1344 pw.println("Package manager (package) commands:");
1345 pw.println(" help");
1346 pw.println(" Print this help text.");
1347 pw.println("");
David Brazdilcf046952016-03-08 16:40:20 +00001348 pw.println(" compile [-m MODE] [-f] [-c] [--reset] (-a | TARGET-PACKAGE)");
David Brazdil990fb6b2016-03-01 10:02:27 +00001349 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".");
David Brazdil493411a2016-02-01 13:48:46 +00001350 pw.println(" Options:");
David Brazdil990fb6b2016-03-01 10:02:27 +00001351 pw.println(" -a: compile all packages");
David Brazdil9aa6db02016-03-08 12:57:12 +00001352 pw.println(" -c: clear profile data before compiling");
1353 pw.println(" -f: force compilation even if not needed");
David Brazdil493411a2016-02-01 13:48:46 +00001354 pw.println(" -m: select compilation mode");
David Brazdilcf046952016-03-08 16:40:20 +00001355 pw.println(" MODE can be one of \"default\", \"full\", \"profile\"," +
David Brazdilce389e52016-03-08 16:22:23 +00001356 " and \"extract\"");
David Brazdilcf046952016-03-08 16:40:20 +00001357 pw.println(" --reset: restore package to its post-install state");
David Brazdil9aa6db02016-03-08 12:57:12 +00001358 pw.println(" shorthand for \"-c -f -m extract\"");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001359 pw.println(" list features");
1360 pw.println(" Prints all features of the system.");
1361 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00001362 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001363 pw.println(" Options:");
1364 pw.println(" -f: dump the name of the .apk file containing the test package");
1365 pw.println(" list libraries");
1366 pw.println(" Prints all system libraries.");
1367 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]");
1368 pw.println(" Prints all packages; optionally only those whose name contains");
1369 pw.println(" the text in FILTER.");
1370 pw.println(" Options:");
1371 pw.println(" -f: see their associated file");
Felipe Leme3f24edf2015-11-18 15:04:13 -08001372 pw.println(" -d: filter to only show disabled packages");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001373 pw.println(" -e: filter to only show enabled packages");
1374 pw.println(" -s: filter to only show system packages");
1375 pw.println(" -3: filter to only show third party packages");
1376 pw.println(" -i: see the installer for the packages");
1377 pw.println(" -u: also include uninstalled packages");
1378 pw.println(" list permission-groups");
1379 pw.println(" Prints all known permission groups.");
1380 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
1381 pw.println(" Prints all known permissions; optionally only those in GROUP.");
1382 pw.println(" Options:");
1383 pw.println(" -g: organize by group");
1384 pw.println(" -f: print all information");
1385 pw.println(" -s: short summary");
1386 pw.println(" -d: only list dangerous permissions");
1387 pw.println(" -u: list only the permissions users will see");
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -08001388 pw.println(" resolve-activity [--user USER_ID] INTENT");
Dianne Hackborn99878e92015-12-02 16:27:41 -08001389 pw.println(" Prints the activity that resolves to the given Intent.");
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -08001390 pw.println(" query-activities [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001391 pw.println(" Prints all activities that can handle the given Intent.");
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -08001392 pw.println(" query-services [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001393 pw.println(" Prints all services that can handle the given Intent.");
Dianne Hackborn6ac42ae2015-12-08 17:22:10 -08001394 pw.println(" query-receivers [--user USER_ID] INTENT");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001395 pw.println(" Prints all broadcast receivers that can handle the given Intent.");
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00001396 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE");
1397 pw.println(" Suspends the specified package (as user).");
1398 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE");
1399 pw.println(" Unsuspends the specified package (as user).");
Makoto Onuki4828a592016-03-15 18:06:57 -07001400 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT");
1401 pw.println(" set the default home activity (aka launcher).");
Dianne Hackborn3cdb56e2015-11-11 12:45:44 -08001402 pw.println();
1403 Intent.printIntentArgsHelp(pw , "");
Todd Kennedy60459ab2015-10-30 11:32:16 -07001404 }
Todd Kennedy72cfcd02015-11-03 17:08:55 -08001405
1406 private static class LocalIntentReceiver {
1407 private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
1408
1409 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
1410 @Override
1411 public int send(int code, Intent intent, String resolvedType,
1412 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
1413 try {
1414 mResult.offer(intent, 5, TimeUnit.SECONDS);
1415 } catch (InterruptedException e) {
1416 throw new RuntimeException(e);
1417 }
1418 return 0;
1419 }
1420 };
1421
1422 public IntentSender getIntentSender() {
1423 return new IntentSender((IIntentSender) mLocalSender);
1424 }
1425
1426 public Intent getResult() {
1427 try {
1428 return mResult.take();
1429 } catch (InterruptedException e) {
1430 throw new RuntimeException(e);
1431 }
1432 }
1433 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07001434}