Pm.java revision f013e1afd1e68af5e3b868c26a653bbfb39538f8
1/* 2 * Copyright (C) 2007 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.commands.pm; 18 19import android.content.ComponentName; 20import android.content.pm.ApplicationInfo; 21import android.content.pm.IPackageDeleteObserver; 22import android.content.pm.IPackageInstallObserver; 23import android.content.pm.IPackageManager; 24import android.content.pm.InstrumentationInfo; 25import android.content.pm.PackageInfo; 26import android.content.pm.PackageItemInfo; 27import android.content.pm.PackageManager; 28import android.content.pm.PermissionGroupInfo; 29import android.content.pm.PermissionInfo; 30import android.content.res.AssetManager; 31import android.content.res.Resources; 32import android.net.Uri; 33import android.os.RemoteException; 34import android.os.ServiceManager; 35 36import java.io.File; 37import java.util.ArrayList; 38import java.util.Collections; 39import java.util.Comparator; 40import java.util.List; 41import java.util.WeakHashMap; 42 43public final class Pm { 44 IPackageManager mPm; 45 46 private WeakHashMap<String, Resources> mResourceCache 47 = new WeakHashMap<String, Resources>(); 48 49 private String[] mArgs; 50 private int mNextArg; 51 private String mCurArgData; 52 53 private static final String PM_NOT_RUNNING_ERR = 54 "Error: Could not access the Package Manager. Is the system running?"; 55 56 public static void main(String[] args) { 57 new Pm().run(args); 58 } 59 60 public void run(String[] args) { 61 boolean validCommand = false; 62 if (args.length < 1) { 63 showUsage(); 64 return; 65 } 66 67 mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 68 if (mPm == null) { 69 System.err.println(PM_NOT_RUNNING_ERR); 70 return; 71 } 72 73 mArgs = args; 74 String op = args[0]; 75 mNextArg = 1; 76 77 if ("list".equals(op)) { 78 runList(); 79 return; 80 } 81 82 if ("path".equals(op)) { 83 runPath(); 84 return; 85 } 86 87 if ("install".equals(op)) { 88 runInstall(); 89 return; 90 } 91 92 if ("uninstall".equals(op)) { 93 runUninstall(); 94 return; 95 } 96 97 try { 98 if (args.length == 1) { 99 if (args[0].equalsIgnoreCase("-l")) { 100 validCommand = true; 101 runListPackages(false); 102 } else if (args[0].equalsIgnoreCase("-lf")){ 103 validCommand = true; 104 runListPackages(true); 105 } 106 } else if (args.length == 2) { 107 if (args[0].equalsIgnoreCase("-p")) { 108 validCommand = true; 109 displayPackageFilePath(args[1]); 110 } 111 } 112 } finally { 113 if (validCommand == false) { 114 showUsage(); 115 } 116 } 117 } 118 119 /** 120 * Execute the list sub-command. 121 * 122 * pm list [package | packages] 123 * pm list permission-groups 124 * pm list permissions 125 * pm list instrumentation 126 */ 127 private void runList() { 128 String type = nextArg(); 129 if (type == null) { 130 System.err.println("Error: didn't specify type of data to list"); 131 showUsage(); 132 return; 133 } 134 if ("package".equals(type) || "packages".equals(type)) { 135 runListPackages(false); 136 } else if ("permission-groups".equals(type)) { 137 runListPermissionGroups(); 138 } else if ("permissions".equals(type)) { 139 runListPermissions(); 140 } else if ("instrumentation".equals(type)) { 141 runListInstrumentation(); 142 } else { 143 System.err.println("Error: unknown list type '" + type + "'"); 144 showUsage(); 145 } 146 } 147 148 /** 149 * Lists all the installed packages. 150 */ 151 private void runListPackages(boolean showApplicationPackage) { 152 try { 153 String opt; 154 while ((opt=nextOption()) != null) { 155 if (opt.equals("-l")) { 156 // old compat 157 } else if (opt.equals("-lf")) { 158 showApplicationPackage = true; 159 } else if (opt.equals("-f")) { 160 showApplicationPackage = true; 161 } else { 162 System.err.println("Error: Unknown option: " + opt); 163 showUsage(); 164 return; 165 } 166 } 167 } catch (RuntimeException ex) { 168 System.err.println("Error: " + ex.toString()); 169 showUsage(); 170 return; 171 } 172 173 try { 174 List<PackageInfo> packages = mPm.getInstalledPackages(0 /* all */); 175 176 int count = packages.size(); 177 for (int p = 0 ; p < count ; p++) { 178 PackageInfo info = packages.get(p); 179 System.out.print("package:"); 180 if (showApplicationPackage) { 181 System.out.print(info.applicationInfo.sourceDir); 182 System.out.print("="); 183 } 184 System.out.println(info.packageName); 185 } 186 } catch (RemoteException e) { 187 System.err.println(e.toString()); 188 System.err.println(PM_NOT_RUNNING_ERR); 189 } 190 } 191 192 /** 193 * Lists all of the installed instrumentation, or all for a given package 194 * 195 * pm list instrumentation [package] [-f] 196 */ 197 private void runListInstrumentation() { 198 int flags = 0; // flags != 0 is only used to request meta-data 199 boolean showPackage = false; 200 String targetPackage = null; 201 202 try { 203 String opt; 204 while ((opt=nextArg()) != null) { 205 if (opt.equals("-f")) { 206 showPackage = true; 207 } else if (opt.charAt(0) != '-') { 208 targetPackage = opt; 209 } else { 210 System.err.println("Error: Unknown option: " + opt); 211 showUsage(); 212 return; 213 } 214 } 215 } catch (RuntimeException ex) { 216 System.err.println("Error: " + ex.toString()); 217 showUsage(); 218 return; 219 } 220 221 try { 222 List<InstrumentationInfo> list = mPm.queryInstrumentation(targetPackage, flags); 223 224 // Sort by target package 225 Collections.sort(list, new Comparator<InstrumentationInfo>() { 226 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) { 227 return o1.targetPackage.compareTo(o2.targetPackage); 228 } 229 }); 230 231 int count = (list != null) ? list.size() : 0; 232 for (int p = 0; p < count; p++) { 233 InstrumentationInfo ii = list.get(p); 234 System.out.print("instrumentation:"); 235 if (showPackage) { 236 System.out.print(ii.sourceDir); 237 System.out.print("="); 238 } 239 ComponentName cn = new ComponentName(ii.packageName, ii.name); 240 System.out.print(cn.flattenToShortString()); 241 System.out.print(" (target="); 242 System.out.print(ii.targetPackage); 243 System.out.println(")"); 244 } 245 } catch (RemoteException e) { 246 System.err.println(e.toString()); 247 System.err.println(PM_NOT_RUNNING_ERR); 248 } 249 } 250 251 /** 252 * Lists all the known permission groups. 253 */ 254 private void runListPermissionGroups() { 255 try { 256 List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0); 257 258 int count = pgs.size(); 259 for (int p = 0 ; p < count ; p++) { 260 PermissionGroupInfo pgi = pgs.get(p); 261 System.out.print("permission group:"); 262 System.out.println(pgi.name); 263 } 264 } catch (RemoteException e) { 265 System.err.println(e.toString()); 266 System.err.println(PM_NOT_RUNNING_ERR); 267 } 268 } 269 270 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) { 271 if (nonLocalized != null) { 272 return nonLocalized.toString(); 273 } 274 Resources r = getResources(pii); 275 if (r != null) { 276 return r.getString(res); 277 } 278 return null; 279 } 280 281 /** 282 * Lists all the permissions in a group. 283 */ 284 private void runListPermissions() { 285 try { 286 boolean labels = false; 287 boolean groups = false; 288 boolean userOnly = false; 289 boolean summary = false; 290 boolean dangerousOnly = false; 291 String opt; 292 while ((opt=nextOption()) != null) { 293 if (opt.equals("-f")) { 294 labels = true; 295 } else if (opt.equals("-g")) { 296 groups = true; 297 } else if (opt.equals("-s")) { 298 groups = true; 299 labels = true; 300 summary = true; 301 } else if (opt.equals("-u")) { 302 userOnly = true; 303 } else if (opt.equals("-d")) { 304 dangerousOnly = true; 305 } else { 306 System.err.println("Error: Unknown option: " + opt); 307 showUsage(); 308 return; 309 } 310 } 311 312 String grp = nextOption(); 313 ArrayList<String> groupList = new ArrayList<String>(); 314 if (groups) { 315 List<PermissionGroupInfo> infos = 316 mPm.getAllPermissionGroups(0); 317 for (int i=0; i<infos.size(); i++) { 318 groupList.add(infos.get(i).name); 319 } 320 groupList.add(null); 321 } else { 322 groupList.add(grp); 323 } 324 325 if (dangerousOnly) { 326 System.out.println("Dangerous Permissions:"); 327 System.out.println(""); 328 doListPermissions(groupList, groups, labels, summary, 329 PermissionInfo.PROTECTION_DANGEROUS, 330 PermissionInfo.PROTECTION_DANGEROUS); 331 if (userOnly) { 332 System.out.println("Normal Permissions:"); 333 System.out.println(""); 334 doListPermissions(groupList, groups, labels, summary, 335 PermissionInfo.PROTECTION_NORMAL, 336 PermissionInfo.PROTECTION_NORMAL); 337 } 338 } else if (userOnly) { 339 System.out.println("Dangerous and Normal Permissions:"); 340 System.out.println(""); 341 doListPermissions(groupList, groups, labels, summary, 342 PermissionInfo.PROTECTION_NORMAL, 343 PermissionInfo.PROTECTION_DANGEROUS); 344 } else { 345 System.out.println("All Permissions:"); 346 System.out.println(""); 347 doListPermissions(groupList, groups, labels, summary, 348 -10000, 10000); 349 } 350 } catch (RemoteException e) { 351 System.err.println(e.toString()); 352 System.err.println(PM_NOT_RUNNING_ERR); 353 } 354 } 355 356 private void doListPermissions(ArrayList<String> groupList, 357 boolean groups, boolean labels, boolean summary, 358 int startProtectionLevel, int endProtectionLevel) 359 throws RemoteException { 360 for (int i=0; i<groupList.size(); i++) { 361 String groupName = groupList.get(i); 362 String prefix = ""; 363 if (groups) { 364 if (i > 0) System.out.println(""); 365 if (groupName != null) { 366 PermissionGroupInfo pgi = mPm.getPermissionGroupInfo( 367 groupName, 0); 368 if (summary) { 369 Resources res = getResources(pgi); 370 if (res != null) { 371 System.out.print(loadText(pgi, pgi.labelRes, 372 pgi.nonLocalizedLabel) + ": "); 373 } else { 374 System.out.print(pgi.name + ": "); 375 376 } 377 } else { 378 System.out.println((labels ? "+ " : "") 379 + "group:" + pgi.name); 380 if (labels) { 381 System.out.println(" package:" + pgi.packageName); 382 Resources res = getResources(pgi); 383 if (res != null) { 384 System.out.println(" label:" 385 + loadText(pgi, pgi.labelRes, 386 pgi.nonLocalizedLabel)); 387 System.out.println(" description:" 388 + loadText(pgi, pgi.descriptionRes, 389 pgi.nonLocalizedDescription)); 390 } 391 } 392 } 393 } else { 394 System.out.println(((labels && !summary) 395 ? "+ " : "") + "ungrouped:"); 396 } 397 prefix = " "; 398 } 399 List<PermissionInfo> ps = mPm.queryPermissionsByGroup( 400 groupList.get(i), 0); 401 int count = ps.size(); 402 boolean first = true; 403 for (int p = 0 ; p < count ; p++) { 404 PermissionInfo pi = ps.get(p); 405 if (groups && groupName == null && pi.group != null) { 406 continue; 407 } 408 if (pi.protectionLevel < startProtectionLevel 409 || pi.protectionLevel > endProtectionLevel) { 410 continue; 411 } 412 if (summary) { 413 if (first) { 414 first = false; 415 } else { 416 System.out.print(", "); 417 } 418 Resources res = getResources(pi); 419 if (res != null) { 420 System.out.print(loadText(pi, pi.labelRes, 421 pi.nonLocalizedLabel)); 422 } else { 423 System.out.print(pi.name); 424 } 425 } else { 426 System.out.println(prefix + (labels ? "+ " : "") 427 + "permission:" + pi.name); 428 if (labels) { 429 System.out.println(prefix + " package:" + pi.packageName); 430 Resources res = getResources(pi); 431 if (res != null) { 432 System.out.println(prefix + " label:" 433 + loadText(pi, pi.labelRes, 434 pi.nonLocalizedLabel)); 435 System.out.println(prefix + " description:" 436 + loadText(pi, pi.descriptionRes, 437 pi.nonLocalizedDescription)); 438 } 439 String protLevel = "unknown"; 440 switch(pi.protectionLevel) { 441 case PermissionInfo.PROTECTION_DANGEROUS: 442 protLevel = "dangerous"; 443 break; 444 case PermissionInfo.PROTECTION_NORMAL: 445 protLevel = "normal"; 446 break; 447 case PermissionInfo.PROTECTION_SIGNATURE: 448 protLevel = "signature"; 449 break; 450 case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM: 451 protLevel = "signatureOrSystem"; 452 break; 453 } 454 System.out.println(prefix + " protectionLevel:" + protLevel); 455 } 456 } 457 } 458 459 if (summary) { 460 System.out.println(""); 461 } 462 } 463 } 464 465 private void runPath() { 466 String pkg = nextArg(); 467 if (pkg == null) { 468 System.err.println("Error: no package specified"); 469 showUsage(); 470 return; 471 } 472 displayPackageFilePath(pkg); 473 } 474 475 class PackageInstallObserver extends IPackageInstallObserver.Stub { 476 boolean finished; 477 int result; 478 479 public void packageInstalled(String name, int status) { 480 synchronized( this) { 481 finished = true; 482 result = status; 483 notifyAll(); 484 } 485 } 486 } 487 488 private String installFailureToString(int result) { 489 String s; 490 switch (result) { 491 case PackageManager.INSTALL_FAILED_ALREADY_EXISTS: 492 s = "INSTALL_FAILED_ALREADY_EXISTS"; 493 break; 494 case PackageManager.INSTALL_FAILED_INVALID_APK: 495 s = "INSTALL_FAILED_INVALID_APK"; 496 break; 497 case PackageManager.INSTALL_FAILED_INVALID_URI: 498 s = "INSTALL_FAILED_INVALID_URI"; 499 break; 500 case PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE: 501 s = "INSTALL_FAILED_INSUFFICIENT_STORAGE"; 502 break; 503 case PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE: 504 s = "INSTALL_FAILED_DUPLICATE_PACKAGE"; 505 break; 506 case PackageManager.INSTALL_FAILED_NO_SHARED_USER: 507 s = "INSTALL_FAILED_NO_SHARED_USER"; 508 break; 509 case PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE: 510 s = "INSTALL_FAILED_UPDATE_INCOMPATIBLE"; 511 break; 512 case PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE: 513 s = "INSTALL_FAILED_SHARED_USER_INCOMPATIBLE"; 514 break; 515 case PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY: 516 s = "INSTALL_FAILED_MISSING_SHARED_LIBRARY"; 517 break; 518 case PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE: 519 s = "INSTALL_FAILED_REPLACE_COULDNT_DELETE"; 520 break; 521 case PackageManager.INSTALL_PARSE_FAILED_NOT_APK: 522 s = "INSTALL_PARSE_FAILED_NOT_APK"; 523 break; 524 case PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST: 525 s = "INSTALL_PARSE_FAILED_BAD_MANIFEST"; 526 break; 527 case PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION: 528 s = "INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION"; 529 break; 530 case PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES: 531 s = "INSTALL_PARSE_FAILED_NO_CERTIFICATES"; 532 break; 533 case PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES: 534 s = "INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES"; 535 break; 536 case PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING: 537 s = "INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING"; 538 break; 539 case PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME: 540 s = "INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME"; 541 break; 542 case PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID: 543 s = "INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID"; 544 break; 545 case PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: 546 s = "INSTALL_PARSE_FAILED_MANIFEST_MALFORMED"; 547 break; 548 case PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY: 549 s = "INSTALL_PARSE_FAILED_MANIFEST_EMPTY"; 550 break; 551 case PackageManager.INSTALL_FAILED_OLDER_SDK: 552 s = "INSTALL_FAILED_OLDER_SDK"; 553 break; 554 default: 555 s = Integer.toString(result); 556 break; 557 } 558 return s; 559 } 560 561 private void runInstall() { 562 int installFlags = 0; 563 564 String opt; 565 while ((opt=nextOption()) != null) { 566 if (opt.equals("-l")) { 567 installFlags |= PackageManager.FORWARD_LOCK_PACKAGE; 568 } else if (opt.equals("-r")) { 569 installFlags |= PackageManager.REPLACE_EXISTING_PACKAGE; 570 } else { 571 System.err.println("Error: Unknown option: " + opt); 572 showUsage(); 573 return; 574 } 575 } 576 577 String apkFilePath = nextArg(); 578 System.err.println("\tpkg: " + apkFilePath); 579 if (apkFilePath == null) { 580 System.err.println("Error: no package specified"); 581 showUsage(); 582 return; 583 } 584 585 PackageInstallObserver obs = new PackageInstallObserver(); 586 try { 587 mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags); 588 589 synchronized (obs) { 590 while (!obs.finished) { 591 try { 592 obs.wait(); 593 } catch (InterruptedException e) { 594 } 595 } 596 if (obs.result == PackageManager.INSTALL_SUCCEEDED) { 597 System.out.println("Success"); 598 } else { 599 System.err.println("Failure [" 600 + installFailureToString(obs.result) 601 + "]"); 602 } 603 } 604 } catch (RemoteException e) { 605 System.err.println(e.toString()); 606 System.err.println(PM_NOT_RUNNING_ERR); 607 } 608 } 609 610 class PackageDeleteObserver extends IPackageDeleteObserver.Stub { 611 boolean finished; 612 boolean result; 613 614 public void packageDeleted(boolean succeeded) { 615 synchronized (this) { 616 finished = true; 617 result = succeeded; 618 notifyAll(); 619 } 620 } 621 } 622 623 private void runUninstall() { 624 int unInstallFlags = 0; 625 626 String opt = nextOption(); 627 if (opt != null && opt.equals("-k")) { 628 unInstallFlags = PackageManager.DONT_DELETE_DATA; 629 } 630 631 String pkg = nextArg(); 632 if (pkg == null) { 633 System.err.println("Error: no package specified"); 634 showUsage(); 635 return; 636 } 637 boolean result = deletePackage(pkg, unInstallFlags); 638 if (result) { 639 System.out.println("Success"); 640 } else { 641 System.out.println("Failure"); 642 } 643 } 644 645 private boolean deletePackage(String pkg, int unInstallFlags) { 646 PackageDeleteObserver obs = new PackageDeleteObserver(); 647 try { 648 mPm.deletePackage(pkg, obs, unInstallFlags); 649 650 synchronized (obs) { 651 while (!obs.finished) { 652 try { 653 obs.wait(); 654 } catch (InterruptedException e) { 655 } 656 } 657 } 658 } catch (RemoteException e) { 659 System.err.println(e.toString()); 660 System.err.println(PM_NOT_RUNNING_ERR); 661 } 662 return obs.result; 663 } 664 665 /** 666 * Displays the package file for a package. 667 * @param pckg 668 */ 669 private void displayPackageFilePath(String pckg) { 670 try { 671 PackageInfo info = mPm.getPackageInfo(pckg, 0); 672 if (info != null && info.applicationInfo != null) { 673 System.out.print("package:"); 674 System.out.println(info.applicationInfo.sourceDir); 675 } 676 } catch (RemoteException e) { 677 System.err.println(e.toString()); 678 System.err.println(PM_NOT_RUNNING_ERR); 679 } 680 } 681 682 private Resources getResources(PackageItemInfo pii) { 683 Resources res = mResourceCache.get(pii.packageName); 684 if (res != null) return res; 685 686 try { 687 ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0); 688 AssetManager am = new AssetManager(); 689 am.addAssetPath(ai.publicSourceDir); 690 res = new Resources(am, null, null); 691 mResourceCache.put(pii.packageName, res); 692 return res; 693 } catch (RemoteException e) { 694 System.err.println(e.toString()); 695 System.err.println(PM_NOT_RUNNING_ERR); 696 return null; 697 } 698 } 699 700 private String nextOption() { 701 if (mNextArg >= mArgs.length) { 702 return null; 703 } 704 String arg = mArgs[mNextArg]; 705 if (!arg.startsWith("-")) { 706 return null; 707 } 708 mNextArg++; 709 if (arg.equals("--")) { 710 return null; 711 } 712 if (arg.length() > 1 && arg.charAt(1) != '-') { 713 if (arg.length() > 2) { 714 mCurArgData = arg.substring(2); 715 return arg.substring(0, 2); 716 } else { 717 mCurArgData = null; 718 return arg; 719 } 720 } 721 mCurArgData = null; 722 return arg; 723 } 724 725 private String nextOptionData() { 726 if (mCurArgData != null) { 727 return mCurArgData; 728 } 729 if (mNextArg >= mArgs.length) { 730 return null; 731 } 732 String data = mArgs[mNextArg]; 733 mNextArg++; 734 return data; 735 } 736 737 private String nextArg() { 738 if (mNextArg >= mArgs.length) { 739 return null; 740 } 741 String arg = mArgs[mNextArg]; 742 mNextArg++; 743 return arg; 744 } 745 746 private static void showUsage() { 747 System.err.println("usage: pm [list|path|install|uninstall]"); 748 System.err.println(" pm list packages [-f]"); 749 System.err.println(" pm list permission-groups"); 750 System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]"); 751 System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]"); 752 System.err.println(" pm path PACKAGE"); 753 System.err.println(" pm install [-l] [-r] PATH"); 754 System.err.println(" pm uninstall [-k] PACKAGE"); 755 System.err.println(""); 756 System.err.println("The list packages command prints all packages. Use"); 757 System.err.println("the -f option to see their associated file."); 758 System.err.println(""); 759 System.err.println("The list permission-groups command prints all known"); 760 System.err.println("permission groups."); 761 System.err.println(""); 762 System.err.println("The list permissions command prints all known"); 763 System.err.println("permissions, optionally only those in GROUP. Use"); 764 System.err.println("the -g option to organize by group. Use"); 765 System.err.println("the -f option to print all information. Use"); 766 System.err.println("the -s option for a short summary. Use"); 767 System.err.println("the -d option to only list dangerous permissions. Use"); 768 System.err.println("the -u option to list only the permissions users will see."); 769 System.err.println(""); 770 System.err.println("The list instrumentation command prints all instrumentations,"); 771 System.err.println("or only those that target a specified package. Use the -f option"); 772 System.err.println("to see their associated file."); 773 System.err.println(""); 774 System.err.println("The path command prints the path to the .apk of a package."); 775 System.err.println(""); 776 System.err.println("The install command installs a package to the system. Use"); 777 System.err.println("the -l option to install the package with FORWARD_LOCK. Use"); 778 System.err.println("the -r option to reinstall an exisiting app, keeping its data."); 779 System.err.println(""); 780 System.err.println("The uninstall command removes a package from the system. Use"); 781 System.err.println("the -k option to keep the data and cache directories around"); 782 System.err.println("after the package removal."); 783 } 784} 785