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