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