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