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