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