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