PackageManagerShellCommand.java revision 355b232d7998cfc9b29d42a0356390e25191bcbd
1/* 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 17package com.android.server.pm; 18 19import android.app.ActivityManager; 20import android.content.ComponentName; 21import android.content.IIntentReceiver; 22import android.content.IIntentSender; 23import android.content.Intent; 24import android.content.IntentSender; 25import android.content.pm.ApplicationInfo; 26import android.content.pm.FeatureInfo; 27import android.content.pm.IPackageManager; 28import android.content.pm.InstrumentationInfo; 29import android.content.pm.PackageInfo; 30import android.content.pm.PackageInstaller; 31import android.content.pm.PackageItemInfo; 32import android.content.pm.PackageManager; 33import android.content.pm.ParceledListSlice; 34import android.content.pm.PermissionGroupInfo; 35import android.content.pm.PermissionInfo; 36import android.content.pm.PackageInstaller.SessionInfo; 37import android.content.pm.PackageInstaller.SessionParams; 38import android.content.pm.ResolveInfo; 39import android.content.res.AssetManager; 40import android.content.res.Resources; 41import android.net.Uri; 42import android.os.Binder; 43import android.os.Build; 44import android.os.Bundle; 45import android.os.RemoteException; 46import android.os.ShellCommand; 47import android.os.SystemProperties; 48import android.os.UserHandle; 49import android.text.TextUtils; 50import android.util.PrintWriterPrinter; 51import com.android.internal.util.SizedInputStream; 52 53import libcore.io.IoUtils; 54 55import java.io.File; 56import java.io.FileInputStream; 57import java.io.IOException; 58import java.io.InputStream; 59import java.io.OutputStream; 60import java.io.PrintWriter; 61import java.net.URISyntaxException; 62import java.util.ArrayList; 63import java.util.Collections; 64import java.util.Comparator; 65import java.util.List; 66import java.util.WeakHashMap; 67import java.util.concurrent.SynchronousQueue; 68import java.util.concurrent.TimeUnit; 69 70class PackageManagerShellCommand extends ShellCommand { 71 final IPackageManager mInterface; 72 final private WeakHashMap<String, Resources> mResourceCache = 73 new WeakHashMap<String, Resources>(); 74 int mTargetUser; 75 76 PackageManagerShellCommand(PackageManagerService service) { 77 mInterface = service; 78 } 79 80 @Override 81 public int onCommand(String cmd) { 82 if (cmd == null) { 83 return handleDefaultCommands(cmd); 84 } 85 86 final PrintWriter pw = getOutPrintWriter(); 87 try { 88 switch(cmd) { 89 case "install": 90 return runInstall(); 91 case "install-abandon": 92 case "install-destroy": 93 return runInstallAbandon(); 94 case "install-commit": 95 return runInstallCommit(); 96 case "install-create": 97 return runInstallCreate(); 98 case "install-write": 99 return runInstallWrite(); 100 case "compile": 101 return runCompile(); 102 case "list": 103 return runList(); 104 case "uninstall": 105 return runUninstall(); 106 case "resolve-activity": 107 return runResolveActivity(); 108 case "query-activities": 109 return runQueryIntentActivities(); 110 case "query-services": 111 return runQueryIntentServices(); 112 case "query-receivers": 113 return runQueryIntentReceivers(); 114 case "suspend": 115 return runSuspend(true); 116 case "unsuspend": 117 return runSuspend(false); 118 default: 119 return handleDefaultCommands(cmd); 120 } 121 } catch (RemoteException e) { 122 pw.println("Remote exception: " + e); 123 } 124 return -1; 125 } 126 127 private int runInstall() throws RemoteException { 128 final PrintWriter pw = getOutPrintWriter(); 129 final InstallParams params = makeInstallParams(); 130 final int sessionId = doCreateSession(params.sessionParams, 131 params.installerPackageName, params.userId); 132 boolean abandonSession = true; 133 try { 134 final String inPath = getNextArg(); 135 if (inPath == null && params.sessionParams.sizeBytes == 0) { 136 pw.println("Error: must either specify a package size or an APK file"); 137 return 1; 138 } 139 if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk", 140 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { 141 return 1; 142 } 143 if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { 144 return 1; 145 } 146 abandonSession = false; 147 pw.println("Success"); 148 return 0; 149 } finally { 150 if (abandonSession) { 151 try { 152 doAbandonSession(sessionId, false /*logSuccess*/); 153 } catch (Exception ignore) { 154 } 155 } 156 } 157 } 158 159 private int runSuspend(boolean suspendedState) { 160 final PrintWriter pw = getOutPrintWriter(); 161 int userId = UserHandle.USER_SYSTEM; 162 String opt; 163 while ((opt = getNextOption()) != null) { 164 switch (opt) { 165 case "--user": 166 userId = UserHandle.parseUserArg(getNextArgRequired()); 167 break; 168 default: 169 pw.println("Error: Unknown option: " + opt); 170 return 1; 171 } 172 } 173 174 String packageName = getNextArg(); 175 if (packageName == null) { 176 pw.println("Error: package name not specified"); 177 return 1; 178 } 179 180 try { 181 mInterface.setPackageSuspendedAsUser(packageName, suspendedState, userId); 182 pw.println("Package " + packageName + " new suspended state: " 183 + mInterface.isPackageSuspendedForUser(packageName, userId)); 184 return 0; 185 } catch (RemoteException e) { 186 pw.println(e.toString()); 187 return 1; 188 } 189 } 190 191 private int runInstallAbandon() throws RemoteException { 192 final int sessionId = Integer.parseInt(getNextArg()); 193 return doAbandonSession(sessionId, true /*logSuccess*/); 194 } 195 196 private int runInstallCommit() throws RemoteException { 197 final int sessionId = Integer.parseInt(getNextArg()); 198 return doCommitSession(sessionId, true /*logSuccess*/); 199 } 200 201 private int runInstallCreate() throws RemoteException { 202 final PrintWriter pw = getOutPrintWriter(); 203 final InstallParams installParams = makeInstallParams(); 204 final int sessionId = doCreateSession(installParams.sessionParams, 205 installParams.installerPackageName, installParams.userId); 206 207 // NOTE: adb depends on parsing this string 208 pw.println("Success: created install session [" + sessionId + "]"); 209 return 0; 210 } 211 212 private int runInstallWrite() throws RemoteException { 213 long sizeBytes = -1; 214 215 String opt; 216 while ((opt = getNextOption()) != null) { 217 if (opt.equals("-S")) { 218 sizeBytes = Long.parseLong(getNextArg()); 219 } else { 220 throw new IllegalArgumentException("Unknown option: " + opt); 221 } 222 } 223 224 final int sessionId = Integer.parseInt(getNextArg()); 225 final String splitName = getNextArg(); 226 final String path = getNextArg(); 227 return doWriteSession(sessionId, path, sizeBytes, splitName, true /*logSuccess*/); 228 } 229 230 private int runCompile() throws RemoteException { 231 final PrintWriter pw = getOutPrintWriter(); 232 boolean useJitProfiles = false; 233 boolean extractOnly = false; 234 boolean forceCompilation = false; 235 String compilationMode = "default"; 236 237 String opt; 238 while ((opt = getNextOption()) != null) { 239 switch (opt) { 240 case "-m": 241 compilationMode = getNextArgRequired(); 242 break; 243 case "-f": 244 forceCompilation = true; 245 break; 246 default: 247 pw.println("Error: Unknown option: " + opt); 248 return 1; 249 } 250 } 251 252 switch (compilationMode) { 253 case "default": 254 useJitProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); 255 extractOnly = false; 256 break; 257 case "all": 258 useJitProfiles = false; 259 extractOnly = false; 260 break; 261 case "profile": 262 useJitProfiles = true; 263 extractOnly = false; 264 break; 265 case "extract": 266 useJitProfiles = false; 267 extractOnly = true; 268 break; 269 default: 270 pw.println("Error: Unknown compilation mode: " + compilationMode); 271 return 1; 272 } 273 274 String packageName = getNextArg(); 275 if (packageName == null) { 276 pw.println("Error: package name not specified"); 277 return 1; 278 } 279 280 boolean success = mInterface.performDexOpt(packageName, null /* instructionSet */, 281 useJitProfiles, extractOnly, forceCompilation); 282 if (success) { 283 pw.println("Success"); 284 return 0; 285 } else { 286 pw.println("Failure: package " + packageName + " could not be compiled"); 287 return 1; 288 } 289 } 290 291 private int runList() throws RemoteException { 292 final PrintWriter pw = getOutPrintWriter(); 293 final String type = getNextArg(); 294 if (type == null) { 295 pw.println("Error: didn't specify type of data to list"); 296 return -1; 297 } 298 switch(type) { 299 case "features": 300 return runListFeatures(); 301 case "instrumentation": 302 return runListInstrumentation(); 303 case "libraries": 304 return runListLibraries(); 305 case "package": 306 case "packages": 307 return runListPackages(false /*showSourceDir*/); 308 case "permission-groups": 309 return runListPermissionGroups(); 310 case "permissions": 311 return runListPermissions(); 312 } 313 pw.println("Error: unknown list type '" + type + "'"); 314 return -1; 315 } 316 317 private int runListFeatures() throws RemoteException { 318 final PrintWriter pw = getOutPrintWriter(); 319 final List<FeatureInfo> list = new ArrayList<FeatureInfo>(); 320 final FeatureInfo[] rawList = mInterface.getSystemAvailableFeatures(); 321 for (int i=0; i<rawList.length; i++) { 322 list.add(rawList[i]); 323 } 324 325 // sort by name 326 Collections.sort(list, new Comparator<FeatureInfo>() { 327 public int compare(FeatureInfo o1, FeatureInfo o2) { 328 if (o1.name == o2.name) return 0; 329 if (o1.name == null) return -1; 330 if (o2.name == null) return 1; 331 return o1.name.compareTo(o2.name); 332 } 333 }); 334 335 final int count = (list != null) ? list.size() : 0; 336 for (int p = 0; p < count; p++) { 337 FeatureInfo fi = list.get(p); 338 pw.print("feature:"); 339 if (fi.name != null) pw.println(fi.name); 340 else pw.println("reqGlEsVersion=0x" 341 + Integer.toHexString(fi.reqGlEsVersion)); 342 } 343 return 0; 344 } 345 346 private int runListInstrumentation() throws RemoteException { 347 final PrintWriter pw = getOutPrintWriter(); 348 boolean showSourceDir = false; 349 String targetPackage = null; 350 351 try { 352 String opt; 353 while ((opt = getNextArg()) != null) { 354 switch (opt) { 355 case "-f": 356 showSourceDir = true; 357 break; 358 default: 359 if (opt.charAt(0) != '-') { 360 targetPackage = opt; 361 } else { 362 pw.println("Error: Unknown option: " + opt); 363 return -1; 364 } 365 break; 366 } 367 } 368 } catch (RuntimeException ex) { 369 pw.println("Error: " + ex.toString()); 370 return -1; 371 } 372 373 final List<InstrumentationInfo> list = 374 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/); 375 376 // sort by target package 377 Collections.sort(list, new Comparator<InstrumentationInfo>() { 378 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) { 379 return o1.targetPackage.compareTo(o2.targetPackage); 380 } 381 }); 382 383 final int count = (list != null) ? list.size() : 0; 384 for (int p = 0; p < count; p++) { 385 final InstrumentationInfo ii = list.get(p); 386 pw.print("instrumentation:"); 387 if (showSourceDir) { 388 pw.print(ii.sourceDir); 389 pw.print("="); 390 } 391 final ComponentName cn = new ComponentName(ii.packageName, ii.name); 392 pw.print(cn.flattenToShortString()); 393 pw.print(" (target="); 394 pw.print(ii.targetPackage); 395 pw.println(")"); 396 } 397 return 0; 398 } 399 400 private int runListLibraries() throws RemoteException { 401 final PrintWriter pw = getOutPrintWriter(); 402 final List<String> list = new ArrayList<String>(); 403 final String[] rawList = mInterface.getSystemSharedLibraryNames(); 404 for (int i = 0; i < rawList.length; i++) { 405 list.add(rawList[i]); 406 } 407 408 // sort by name 409 Collections.sort(list, new Comparator<String>() { 410 public int compare(String o1, String o2) { 411 if (o1 == o2) return 0; 412 if (o1 == null) return -1; 413 if (o2 == null) return 1; 414 return o1.compareTo(o2); 415 } 416 }); 417 418 final int count = (list != null) ? list.size() : 0; 419 for (int p = 0; p < count; p++) { 420 String lib = list.get(p); 421 pw.print("library:"); 422 pw.println(lib); 423 } 424 return 0; 425 } 426 427 private int runListPackages(boolean showSourceDir) throws RemoteException { 428 final PrintWriter pw = getOutPrintWriter(); 429 int getFlags = 0; 430 boolean listDisabled = false, listEnabled = false; 431 boolean listSystem = false, listThirdParty = false; 432 boolean listInstaller = false; 433 int userId = UserHandle.USER_SYSTEM; 434 try { 435 String opt; 436 while ((opt = getNextOption()) != null) { 437 switch (opt) { 438 case "-d": 439 listDisabled = true; 440 break; 441 case "-e": 442 listEnabled = true; 443 break; 444 case "-f": 445 showSourceDir = true; 446 break; 447 case "-i": 448 listInstaller = true; 449 break; 450 case "-l": 451 // old compat 452 break; 453 case "-lf": 454 showSourceDir = true; 455 break; 456 case "-s": 457 listSystem = true; 458 break; 459 case "-u": 460 getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES; 461 break; 462 case "-3": 463 listThirdParty = true; 464 break; 465 case "--user": 466 userId = UserHandle.parseUserArg(getNextArgRequired()); 467 break; 468 default: 469 pw.println("Error: Unknown option: " + opt); 470 return -1; 471 } 472 } 473 } catch (RuntimeException ex) { 474 pw.println("Error: " + ex.toString()); 475 return -1; 476 } 477 478 final String filter = getNextArg(); 479 480 @SuppressWarnings("unchecked") 481 final ParceledListSlice<PackageInfo> slice = 482 mInterface.getInstalledPackages(getFlags, userId); 483 final List<PackageInfo> packages = slice.getList(); 484 485 final int count = packages.size(); 486 for (int p = 0; p < count; p++) { 487 final PackageInfo info = packages.get(p); 488 if (filter != null && !info.packageName.contains(filter)) { 489 continue; 490 } 491 final boolean isSystem = 492 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0; 493 if ((!listDisabled || !info.applicationInfo.enabled) && 494 (!listEnabled || info.applicationInfo.enabled) && 495 (!listSystem || isSystem) && 496 (!listThirdParty || !isSystem)) { 497 pw.print("package:"); 498 if (showSourceDir) { 499 pw.print(info.applicationInfo.sourceDir); 500 pw.print("="); 501 } 502 pw.print(info.packageName); 503 if (listInstaller) { 504 pw.print(" installer="); 505 pw.print(mInterface.getInstallerPackageName(info.packageName)); 506 } 507 pw.println(); 508 } 509 } 510 return 0; 511 } 512 513 private int runListPermissionGroups() throws RemoteException { 514 final PrintWriter pw = getOutPrintWriter(); 515 final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0); 516 517 final int count = pgs.size(); 518 for (int p = 0; p < count ; p++) { 519 final PermissionGroupInfo pgi = pgs.get(p); 520 pw.print("permission group:"); 521 pw.println(pgi.name); 522 } 523 return 0; 524 } 525 526 private int runListPermissions() throws RemoteException { 527 final PrintWriter pw = getOutPrintWriter(); 528 boolean labels = false; 529 boolean groups = false; 530 boolean userOnly = false; 531 boolean summary = false; 532 boolean dangerousOnly = false; 533 String opt; 534 while ((opt = getNextOption()) != null) { 535 switch (opt) { 536 case "-d": 537 dangerousOnly = true; 538 break; 539 case "-f": 540 labels = true; 541 break; 542 case "-g": 543 groups = true; 544 break; 545 case "-s": 546 groups = true; 547 labels = true; 548 summary = true; 549 break; 550 case "-u": 551 userOnly = true; 552 break; 553 default: 554 pw.println("Error: Unknown option: " + opt); 555 return 1; 556 } 557 } 558 559 final ArrayList<String> groupList = new ArrayList<String>(); 560 if (groups) { 561 final List<PermissionGroupInfo> infos = 562 mInterface.getAllPermissionGroups(0 /*flags*/); 563 final int count = infos.size(); 564 for (int i = 0; i < count; i++) { 565 groupList.add(infos.get(i).name); 566 } 567 groupList.add(null); 568 } else { 569 final String grp = getNextArg(); 570 groupList.add(grp); 571 } 572 573 if (dangerousOnly) { 574 pw.println("Dangerous Permissions:"); 575 pw.println(""); 576 doListPermissions(groupList, groups, labels, summary, 577 PermissionInfo.PROTECTION_DANGEROUS, 578 PermissionInfo.PROTECTION_DANGEROUS); 579 if (userOnly) { 580 pw.println("Normal Permissions:"); 581 pw.println(""); 582 doListPermissions(groupList, groups, labels, summary, 583 PermissionInfo.PROTECTION_NORMAL, 584 PermissionInfo.PROTECTION_NORMAL); 585 } 586 } else if (userOnly) { 587 pw.println("Dangerous and Normal Permissions:"); 588 pw.println(""); 589 doListPermissions(groupList, groups, labels, summary, 590 PermissionInfo.PROTECTION_NORMAL, 591 PermissionInfo.PROTECTION_DANGEROUS); 592 } else { 593 pw.println("All Permissions:"); 594 pw.println(""); 595 doListPermissions(groupList, groups, labels, summary, 596 -10000, 10000); 597 } 598 return 0; 599 } 600 601 private int runUninstall() throws RemoteException { 602 final PrintWriter pw = getOutPrintWriter(); 603 int flags = 0; 604 int userId = UserHandle.USER_ALL; 605 606 String opt; 607 while ((opt = getNextOption()) != null) { 608 switch (opt) { 609 case "-k": 610 flags |= PackageManager.DELETE_KEEP_DATA; 611 break; 612 case "--user": 613 userId = UserHandle.parseUserArg(getNextArgRequired()); 614 break; 615 default: 616 pw.println("Error: Unknown option: " + opt); 617 return 1; 618 } 619 } 620 621 String packageName = getNextArg(); 622 if (packageName == null) { 623 pw.println("Error: package name not specified"); 624 return 1; 625 } 626 627 userId = translateUserId(userId, "runUninstall"); 628 if (userId == UserHandle.USER_ALL) { 629 userId = UserHandle.USER_SYSTEM; 630 flags |= PackageManager.DELETE_ALL_USERS; 631 } else { 632 final PackageInfo info = mInterface.getPackageInfo(packageName, 0, userId); 633 if (info == null) { 634 pw.println("Failure [not installed for " + userId + "]"); 635 return 1; 636 } 637 final boolean isSystem = 638 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 639 // If we are being asked to delete a system app for just one 640 // user set flag so it disables rather than reverting to system 641 // version of the app. 642 if (isSystem) { 643 flags |= PackageManager.DELETE_SYSTEM_APP; 644 } 645 } 646 647 final LocalIntentReceiver receiver = new LocalIntentReceiver(); 648 mInterface.getPackageInstaller().uninstall(packageName, null /*callerPackageName*/, flags, 649 receiver.getIntentSender(), userId); 650 651 final Intent result = receiver.getResult(); 652 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, 653 PackageInstaller.STATUS_FAILURE); 654 if (status == PackageInstaller.STATUS_SUCCESS) { 655 pw.println("Success"); 656 return 0; 657 } else { 658 pw.println("Failure [" 659 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); 660 return 1; 661 } 662 } 663 664 private Intent parseIntentAndUser() throws URISyntaxException { 665 mTargetUser = UserHandle.USER_CURRENT; 666 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() { 667 @Override 668 public boolean handleOption(String opt, ShellCommand cmd) { 669 if ("--user".equals(opt)) { 670 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired()); 671 return true; 672 } 673 return false; 674 } 675 }); 676 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 677 Binder.getCallingUid(), mTargetUser, false, false, null, null); 678 return intent; 679 } 680 681 private int runResolveActivity() { 682 Intent intent; 683 try { 684 intent = parseIntentAndUser(); 685 } catch (URISyntaxException e) { 686 throw new RuntimeException(e.getMessage(), e); 687 } 688 try { 689 ResolveInfo ri = mInterface.resolveIntent(intent, null, 0, mTargetUser); 690 PrintWriter pw = getOutPrintWriter(); 691 if (ri == null) { 692 pw.println("No activity found"); 693 } else { 694 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 695 ri.dump(pr, ""); 696 } 697 } catch (RemoteException e) { 698 throw new RuntimeException("Failed calling service", e); 699 } 700 return 0; 701 } 702 703 private int runQueryIntentActivities() { 704 Intent intent; 705 try { 706 intent = parseIntentAndUser(); 707 } catch (URISyntaxException e) { 708 throw new RuntimeException(e.getMessage(), e); 709 } 710 try { 711 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, null, 0, 712 mTargetUser); 713 PrintWriter pw = getOutPrintWriter(); 714 if (result == null || result.size() <= 0) { 715 pw.println("No activities found"); 716 } else { 717 pw.print(result.size()); pw.println(" activities found:"); 718 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 719 for (int i=0; i<result.size(); i++) { 720 pw.print(" Activity #"); pw.print(i); pw.println(":"); 721 result.get(i).dump(pr, " "); 722 } 723 } 724 } catch (RemoteException e) { 725 throw new RuntimeException("Failed calling service", e); 726 } 727 return 0; 728 } 729 730 private int runQueryIntentServices() { 731 Intent intent; 732 try { 733 intent = parseIntentAndUser(); 734 } catch (URISyntaxException e) { 735 throw new RuntimeException(e.getMessage(), e); 736 } 737 try { 738 List<ResolveInfo> result = mInterface.queryIntentServices(intent, null, 0, 739 mTargetUser); 740 PrintWriter pw = getOutPrintWriter(); 741 if (result == null || result.size() <= 0) { 742 pw.println("No services found"); 743 } else { 744 pw.print(result.size()); pw.println(" services found:"); 745 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 746 for (int i=0; i<result.size(); i++) { 747 pw.print(" Service #"); pw.print(i); pw.println(":"); 748 result.get(i).dump(pr, " "); 749 } 750 } 751 } catch (RemoteException e) { 752 throw new RuntimeException("Failed calling service", e); 753 } 754 return 0; 755 } 756 757 private int runQueryIntentReceivers() { 758 Intent intent; 759 try { 760 intent = parseIntentAndUser(); 761 } catch (URISyntaxException e) { 762 throw new RuntimeException(e.getMessage(), e); 763 } 764 try { 765 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, null, 0, 766 mTargetUser); 767 PrintWriter pw = getOutPrintWriter(); 768 if (result == null || result.size() <= 0) { 769 pw.println("No receivers found"); 770 } else { 771 pw.print(result.size()); pw.println(" receivers found:"); 772 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 773 for (int i=0; i<result.size(); i++) { 774 pw.print(" Receiver #"); pw.print(i); pw.println(":"); 775 result.get(i).dump(pr, " "); 776 } 777 } 778 } catch (RemoteException e) { 779 throw new RuntimeException("Failed calling service", e); 780 } 781 return 0; 782 } 783 784 private static class InstallParams { 785 SessionParams sessionParams; 786 String installerPackageName; 787 int userId = UserHandle.USER_ALL; 788 } 789 790 private InstallParams makeInstallParams() { 791 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL); 792 final InstallParams params = new InstallParams(); 793 params.sessionParams = sessionParams; 794 String opt; 795 while ((opt = getNextOption()) != null) { 796 switch (opt) { 797 case "-l": 798 sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK; 799 break; 800 case "-r": 801 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 802 break; 803 case "-i": 804 params.installerPackageName = getNextArg(); 805 if (params.installerPackageName == null) { 806 throw new IllegalArgumentException("Missing installer package"); 807 } 808 break; 809 case "-t": 810 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST; 811 break; 812 case "-s": 813 sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL; 814 break; 815 case "-f": 816 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL; 817 break; 818 case "-d": 819 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; 820 break; 821 case "-g": 822 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS; 823 break; 824 case "--originating-uri": 825 sessionParams.originatingUri = Uri.parse(getNextArg()); 826 break; 827 case "--referrer": 828 sessionParams.referrerUri = Uri.parse(getNextArg()); 829 break; 830 case "-p": 831 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING; 832 sessionParams.appPackageName = getNextArg(); 833 if (sessionParams.appPackageName == null) { 834 throw new IllegalArgumentException("Missing inherit package name"); 835 } 836 break; 837 case "-S": 838 sessionParams.setSize(Long.parseLong(getNextArg())); 839 break; 840 case "--abi": 841 sessionParams.abiOverride = checkAbiArgument(getNextArg()); 842 break; 843 case "--ephemeral": 844 sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL; 845 break; 846 case "--user": 847 params.userId = UserHandle.parseUserArg(getNextArgRequired()); 848 break; 849 case "--install-location": 850 sessionParams.installLocation = Integer.parseInt(getNextArg()); 851 break; 852 case "--force-uuid": 853 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID; 854 sessionParams.volumeUuid = getNextArg(); 855 if ("internal".equals(sessionParams.volumeUuid)) { 856 sessionParams.volumeUuid = null; 857 } 858 break; 859 default: 860 throw new IllegalArgumentException("Unknown option " + opt); 861 } 862 } 863 return params; 864 } 865 866 private static String checkAbiArgument(String abi) { 867 if (TextUtils.isEmpty(abi)) { 868 throw new IllegalArgumentException("Missing ABI argument"); 869 } 870 871 if ("-".equals(abi)) { 872 return abi; 873 } 874 875 final String[] supportedAbis = Build.SUPPORTED_ABIS; 876 for (String supportedAbi : supportedAbis) { 877 if (supportedAbi.equals(abi)) { 878 return abi; 879 } 880 } 881 882 throw new IllegalArgumentException("ABI " + abi + " not supported on this device"); 883 } 884 885 private int translateUserId(int userId, String logContext) { 886 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 887 userId, true, true, logContext, "pm command"); 888 } 889 890 private int doCreateSession(SessionParams params, String installerPackageName, int userId) 891 throws RemoteException { 892 userId = translateUserId(userId, "runInstallCreate"); 893 if (userId == UserHandle.USER_ALL) { 894 userId = UserHandle.USER_SYSTEM; 895 params.installFlags |= PackageManager.INSTALL_ALL_USERS; 896 } 897 898 final int sessionId = mInterface.getPackageInstaller() 899 .createSession(params, installerPackageName, userId); 900 return sessionId; 901 } 902 903 private int doWriteSession(int sessionId, String inPath, long sizeBytes, String splitName, 904 boolean logSuccess) throws RemoteException { 905 final PrintWriter pw = getOutPrintWriter(); 906 if ("-".equals(inPath)) { 907 inPath = null; 908 } else if (inPath != null) { 909 final File file = new File(inPath); 910 if (file.isFile()) { 911 sizeBytes = file.length(); 912 } 913 } 914 915 final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId); 916 917 PackageInstaller.Session session = null; 918 InputStream in = null; 919 OutputStream out = null; 920 try { 921 session = new PackageInstaller.Session( 922 mInterface.getPackageInstaller().openSession(sessionId)); 923 924 if (inPath != null) { 925 in = new FileInputStream(inPath); 926 } else { 927 in = new SizedInputStream(getRawInputStream(), sizeBytes); 928 } 929 out = session.openWrite(splitName, 0, sizeBytes); 930 931 int total = 0; 932 byte[] buffer = new byte[65536]; 933 int c; 934 while ((c = in.read(buffer)) != -1) { 935 total += c; 936 out.write(buffer, 0, c); 937 938 if (info.sizeBytes > 0) { 939 final float fraction = ((float) c / (float) info.sizeBytes); 940 session.addProgress(fraction); 941 } 942 } 943 session.fsync(out); 944 945 if (logSuccess) { 946 pw.println("Success: streamed " + total + " bytes"); 947 } 948 return 0; 949 } catch (IOException e) { 950 pw.println("Error: failed to write; " + e.getMessage()); 951 return 1; 952 } finally { 953 IoUtils.closeQuietly(out); 954 IoUtils.closeQuietly(in); 955 IoUtils.closeQuietly(session); 956 } 957 } 958 959 private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException { 960 final PrintWriter pw = getOutPrintWriter(); 961 PackageInstaller.Session session = null; 962 try { 963 session = new PackageInstaller.Session( 964 mInterface.getPackageInstaller().openSession(sessionId)); 965 966 final LocalIntentReceiver receiver = new LocalIntentReceiver(); 967 session.commit(receiver.getIntentSender()); 968 969 final Intent result = receiver.getResult(); 970 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, 971 PackageInstaller.STATUS_FAILURE); 972 if (status == PackageInstaller.STATUS_SUCCESS) { 973 if (logSuccess) { 974 System.out.println("Success"); 975 } 976 } else { 977 pw.println("Failure [" 978 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); 979 } 980 return status; 981 } finally { 982 IoUtils.closeQuietly(session); 983 } 984 } 985 986 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException { 987 final PrintWriter pw = getOutPrintWriter(); 988 PackageInstaller.Session session = null; 989 try { 990 session = new PackageInstaller.Session( 991 mInterface.getPackageInstaller().openSession(sessionId)); 992 session.abandon(); 993 if (logSuccess) { 994 pw.println("Success"); 995 } 996 return 0; 997 } finally { 998 IoUtils.closeQuietly(session); 999 } 1000 } 1001 1002 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels, 1003 boolean summary, int startProtectionLevel, int endProtectionLevel) 1004 throws RemoteException { 1005 final PrintWriter pw = getOutPrintWriter(); 1006 final int groupCount = groupList.size(); 1007 for (int i = 0; i < groupCount; i++) { 1008 String groupName = groupList.get(i); 1009 String prefix = ""; 1010 if (groups) { 1011 if (i > 0) { 1012 pw.println(""); 1013 } 1014 if (groupName != null) { 1015 PermissionGroupInfo pgi = 1016 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/); 1017 if (summary) { 1018 Resources res = getResources(pgi); 1019 if (res != null) { 1020 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": "); 1021 } else { 1022 pw.print(pgi.name + ": "); 1023 1024 } 1025 } else { 1026 pw.println((labels ? "+ " : "") + "group:" + pgi.name); 1027 if (labels) { 1028 pw.println(" package:" + pgi.packageName); 1029 Resources res = getResources(pgi); 1030 if (res != null) { 1031 pw.println(" label:" 1032 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel)); 1033 pw.println(" description:" 1034 + loadText(pgi, pgi.descriptionRes, 1035 pgi.nonLocalizedDescription)); 1036 } 1037 } 1038 } 1039 } else { 1040 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:"); 1041 } 1042 prefix = " "; 1043 } 1044 List<PermissionInfo> ps = 1045 mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/); 1046 final int count = ps.size(); 1047 boolean first = true; 1048 for (int p = 0 ; p < count ; p++) { 1049 PermissionInfo pi = ps.get(p); 1050 if (groups && groupName == null && pi.group != null) { 1051 continue; 1052 } 1053 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; 1054 if (base < startProtectionLevel 1055 || base > endProtectionLevel) { 1056 continue; 1057 } 1058 if (summary) { 1059 if (first) { 1060 first = false; 1061 } else { 1062 pw.print(", "); 1063 } 1064 Resources res = getResources(pi); 1065 if (res != null) { 1066 pw.print(loadText(pi, pi.labelRes, 1067 pi.nonLocalizedLabel)); 1068 } else { 1069 pw.print(pi.name); 1070 } 1071 } else { 1072 pw.println(prefix + (labels ? "+ " : "") 1073 + "permission:" + pi.name); 1074 if (labels) { 1075 pw.println(prefix + " package:" + pi.packageName); 1076 Resources res = getResources(pi); 1077 if (res != null) { 1078 pw.println(prefix + " label:" 1079 + loadText(pi, pi.labelRes, 1080 pi.nonLocalizedLabel)); 1081 pw.println(prefix + " description:" 1082 + loadText(pi, pi.descriptionRes, 1083 pi.nonLocalizedDescription)); 1084 } 1085 pw.println(prefix + " protectionLevel:" 1086 + PermissionInfo.protectionToString(pi.protectionLevel)); 1087 } 1088 } 1089 } 1090 1091 if (summary) { 1092 pw.println(""); 1093 } 1094 } 1095 } 1096 1097 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) 1098 throws RemoteException { 1099 if (nonLocalized != null) { 1100 return nonLocalized.toString(); 1101 } 1102 if (res != 0) { 1103 Resources r = getResources(pii); 1104 if (r != null) { 1105 try { 1106 return r.getString(res); 1107 } catch (Resources.NotFoundException e) { 1108 } 1109 } 1110 } 1111 return null; 1112 } 1113 1114 private Resources getResources(PackageItemInfo pii) throws RemoteException { 1115 Resources res = mResourceCache.get(pii.packageName); 1116 if (res != null) return res; 1117 1118 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0); 1119 AssetManager am = new AssetManager(); 1120 am.addAssetPath(ai.publicSourceDir); 1121 res = new Resources(am, null, null); 1122 mResourceCache.put(pii.packageName, res); 1123 return res; 1124 } 1125 1126 @Override 1127 public void onHelp() { 1128 final PrintWriter pw = getOutPrintWriter(); 1129 pw.println("Package manager (package) commands:"); 1130 pw.println(" help"); 1131 pw.println(" Print this help text."); 1132 pw.println(""); 1133 pw.println(" compile [-m MODE] [-f] TARGET-PACKAGE"); 1134 pw.println(" Trigger compilation of TARGET-PACKAGE."); 1135 pw.println(" Options:"); 1136 pw.println(" -m: select compilation mode"); 1137 pw.println(" MODE can be one of \"default\", \"all\", \"profile\", and \"extract\""); 1138 pw.println(" -f: force compilation even if not needed"); 1139 pw.println(" list features"); 1140 pw.println(" Prints all features of the system."); 1141 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]"); 1142 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE"); 1143 pw.println(" Options:"); 1144 pw.println(" -f: dump the name of the .apk file containing the test package"); 1145 pw.println(" list libraries"); 1146 pw.println(" Prints all system libraries."); 1147 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]"); 1148 pw.println(" Prints all packages; optionally only those whose name contains"); 1149 pw.println(" the text in FILTER."); 1150 pw.println(" Options:"); 1151 pw.println(" -f: see their associated file"); 1152 pw.println(" -d: filter to only show disabled packages"); 1153 pw.println(" -e: filter to only show enabled packages"); 1154 pw.println(" -s: filter to only show system packages"); 1155 pw.println(" -3: filter to only show third party packages"); 1156 pw.println(" -i: see the installer for the packages"); 1157 pw.println(" -u: also include uninstalled packages"); 1158 pw.println(" list permission-groups"); 1159 pw.println(" Prints all known permission groups."); 1160 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]"); 1161 pw.println(" Prints all known permissions; optionally only those in GROUP."); 1162 pw.println(" Options:"); 1163 pw.println(" -g: organize by group"); 1164 pw.println(" -f: print all information"); 1165 pw.println(" -s: short summary"); 1166 pw.println(" -d: only list dangerous permissions"); 1167 pw.println(" -u: list only the permissions users will see"); 1168 pw.println(" resolve-activity [--user USER_ID] INTENT"); 1169 pw.println(" Prints the activity that resolves to the given Intent."); 1170 pw.println(" query-activities [--user USER_ID] INTENT"); 1171 pw.println(" Prints all activities that can handle the given Intent."); 1172 pw.println(" query-services [--user USER_ID] INTENT"); 1173 pw.println(" Prints all services that can handle the given Intent."); 1174 pw.println(" query-receivers [--user USER_ID] INTENT"); 1175 pw.println(" Prints all broadcast receivers that can handle the given Intent."); 1176 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE"); 1177 pw.println(" Suspends the specified package (as user)."); 1178 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE"); 1179 pw.println(" Unsuspends the specified package (as user)."); 1180 pw.println(); 1181 Intent.printIntentArgsHelp(pw , ""); 1182 } 1183 1184 private static class LocalIntentReceiver { 1185 private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>(); 1186 1187 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() { 1188 @Override 1189 public int send(int code, Intent intent, String resolvedType, 1190 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) { 1191 try { 1192 mResult.offer(intent, 5, TimeUnit.SECONDS); 1193 } catch (InterruptedException e) { 1194 throw new RuntimeException(e); 1195 } 1196 return 0; 1197 } 1198 }; 1199 1200 public IntentSender getIntentSender() { 1201 return new IntentSender((IIntentSender) mLocalSender); 1202 } 1203 1204 public Intent getResult() { 1205 try { 1206 return mResult.take(); 1207 } catch (InterruptedException e) { 1208 throw new RuntimeException(e); 1209 } 1210 } 1211 } 1212} 1213