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