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