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