Pm.java revision 706e8ba26bf0de19ad5f736516dae40c4c88c2d7
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 com.android.internal.content.PackageHelper; 20 21import android.app.ActivityManagerNative; 22import android.content.ComponentName; 23import android.content.Context; 24import android.content.pm.ApplicationInfo; 25import android.content.pm.ContainerEncryptionParams; 26import android.content.pm.FeatureInfo; 27import android.content.pm.IPackageDataObserver; 28import android.content.pm.IPackageDeleteObserver; 29import android.content.pm.IPackageInstallObserver; 30import android.content.pm.IPackageManager; 31import android.content.pm.InstrumentationInfo; 32import android.content.pm.PackageInfo; 33import android.content.pm.PackageItemInfo; 34import android.content.pm.PackageManager; 35import android.content.pm.ParceledListSlice; 36import android.content.pm.PermissionGroupInfo; 37import android.content.pm.PermissionInfo; 38import android.content.pm.UserInfo; 39import android.content.pm.VerificationParams; 40import android.content.res.AssetManager; 41import android.content.res.Resources; 42import android.net.Uri; 43import android.os.Binder; 44import android.os.IUserManager; 45import android.os.Process; 46import android.os.RemoteException; 47import android.os.ServiceManager; 48import android.os.UserManager; 49 50import java.io.File; 51import java.lang.reflect.Field; 52import java.lang.reflect.Modifier; 53import java.security.InvalidAlgorithmParameterException; 54import java.util.ArrayList; 55import java.util.Collections; 56import java.util.Comparator; 57import java.util.List; 58import java.util.WeakHashMap; 59 60import javax.crypto.SecretKey; 61import javax.crypto.spec.IvParameterSpec; 62import javax.crypto.spec.SecretKeySpec; 63 64public final class Pm { 65 IPackageManager mPm; 66 IUserManager mUm; 67 68 private WeakHashMap<String, Resources> mResourceCache 69 = new WeakHashMap<String, Resources>(); 70 71 private String[] mArgs; 72 private int mNextArg; 73 private String mCurArgData; 74 75 private static final String PM_NOT_RUNNING_ERR = 76 "Error: Could not access the Package Manager. Is the system running?"; 77 private static final int ROOT_UID = 0; 78 79 public static void main(String[] args) { 80 new Pm().run(args); 81 } 82 83 public void run(String[] args) { 84 boolean validCommand = false; 85 if (args.length < 1) { 86 showUsage(); 87 return; 88 } 89 90 mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user")); 91 mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 92 if (mPm == null) { 93 System.err.println(PM_NOT_RUNNING_ERR); 94 return; 95 } 96 97 mArgs = args; 98 String op = args[0]; 99 mNextArg = 1; 100 101 if ("list".equals(op)) { 102 runList(); 103 return; 104 } 105 106 if ("path".equals(op)) { 107 runPath(); 108 return; 109 } 110 111 if ("install".equals(op)) { 112 runInstall(); 113 return; 114 } 115 116 if ("uninstall".equals(op)) { 117 runUninstall(); 118 return; 119 } 120 121 if ("clear".equals(op)) { 122 runClear(); 123 return; 124 } 125 126 if ("enable".equals(op)) { 127 runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED); 128 return; 129 } 130 131 if ("disable".equals(op)) { 132 runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); 133 return; 134 } 135 136 if ("disable-user".equals(op)) { 137 runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER); 138 return; 139 } 140 141 if ("grant".equals(op)) { 142 runGrantRevokePermission(true); 143 return; 144 } 145 146 if ("revoke".equals(op)) { 147 runGrantRevokePermission(false); 148 return; 149 } 150 151 if ("set-permission-enforced".equals(op)) { 152 runSetPermissionEnforced(); 153 return; 154 } 155 156 if ("set-install-location".equals(op)) { 157 runSetInstallLocation(); 158 return; 159 } 160 161 if ("get-install-location".equals(op)) { 162 runGetInstallLocation(); 163 return; 164 } 165 166 if ("trim-caches".equals(op)) { 167 runTrimCaches(); 168 return; 169 } 170 171 if ("create-user".equals(op)) { 172 runCreateUser(); 173 return; 174 } 175 176 if ("remove-user".equals(op)) { 177 runRemoveUser(); 178 return; 179 } 180 181 if ("list-users".equals(op)) { 182 runListUsers(); 183 return; 184 } 185 186 try { 187 if (args.length == 1) { 188 if (args[0].equalsIgnoreCase("-l")) { 189 validCommand = true; 190 runListPackages(false); 191 } else if (args[0].equalsIgnoreCase("-lf")){ 192 validCommand = true; 193 runListPackages(true); 194 } 195 } else if (args.length == 2) { 196 if (args[0].equalsIgnoreCase("-p")) { 197 validCommand = true; 198 displayPackageFilePath(args[1]); 199 } 200 } 201 } finally { 202 if (validCommand == false) { 203 if (op != null) { 204 System.err.println("Error: unknown command '" + op + "'"); 205 } 206 showUsage(); 207 } 208 } 209 } 210 211 /** 212 * Execute the list sub-command. 213 * 214 * pm list [package | packages] 215 * pm list permission-groups 216 * pm list permissions 217 * pm list features 218 * pm list libraries 219 * pm list instrumentation 220 */ 221 private void runList() { 222 String type = nextArg(); 223 if (type == null) { 224 System.err.println("Error: didn't specify type of data to list"); 225 showUsage(); 226 return; 227 } 228 if ("package".equals(type) || "packages".equals(type)) { 229 runListPackages(false); 230 } else if ("permission-groups".equals(type)) { 231 runListPermissionGroups(); 232 } else if ("permissions".equals(type)) { 233 runListPermissions(); 234 } else if ("features".equals(type)) { 235 runListFeatures(); 236 } else if ("libraries".equals(type)) { 237 runListLibraries(); 238 } else if ("instrumentation".equals(type)) { 239 runListInstrumentation(); 240 } else if ("users".equals(type)) { 241 runListUsers(); 242 } else { 243 System.err.println("Error: unknown list type '" + type + "'"); 244 showUsage(); 245 } 246 } 247 248 /** 249 * Lists all the installed packages. 250 */ 251 private void runListPackages(boolean showApplicationPackage) { 252 int getFlags = 0; 253 boolean listDisabled = false, listEnabled = false; 254 boolean listSystem = false, listThirdParty = false; 255 boolean listInstaller = false; 256 try { 257 String opt; 258 while ((opt=nextOption()) != null) { 259 if (opt.equals("-l")) { 260 // old compat 261 } else if (opt.equals("-lf")) { 262 showApplicationPackage = true; 263 } else if (opt.equals("-f")) { 264 showApplicationPackage = true; 265 } else if (opt.equals("-d")) { 266 listDisabled = true; 267 } else if (opt.equals("-e")) { 268 listEnabled = true; 269 } else if (opt.equals("-s")) { 270 listSystem = true; 271 } else if (opt.equals("-3")) { 272 listThirdParty = true; 273 } else if (opt.equals("-i")) { 274 listInstaller = true; 275 } else if (opt.equals("-u")) { 276 getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES; 277 } else { 278 System.err.println("Error: Unknown option: " + opt); 279 showUsage(); 280 return; 281 } 282 } 283 } catch (RuntimeException ex) { 284 System.err.println("Error: " + ex.toString()); 285 showUsage(); 286 return; 287 } 288 289 String filter = nextArg(); 290 291 try { 292 final List<PackageInfo> packages = getInstalledPackages(mPm, getFlags); 293 294 int count = packages.size(); 295 for (int p = 0 ; p < count ; p++) { 296 PackageInfo info = packages.get(p); 297 if (filter != null && !info.packageName.contains(filter)) { 298 continue; 299 } 300 final boolean isSystem = 301 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0; 302 if ((!listDisabled || !info.applicationInfo.enabled) && 303 (!listEnabled || info.applicationInfo.enabled) && 304 (!listSystem || isSystem) && 305 (!listThirdParty || !isSystem)) { 306 System.out.print("package:"); 307 if (showApplicationPackage) { 308 System.out.print(info.applicationInfo.sourceDir); 309 System.out.print("="); 310 } 311 System.out.print(info.packageName); 312 if (listInstaller) { 313 System.out.print(" installer="); 314 System.out.print(mPm.getInstallerPackageName(info.packageName)); 315 } 316 System.out.println(); 317 } 318 } 319 } catch (RemoteException e) { 320 System.err.println(e.toString()); 321 System.err.println(PM_NOT_RUNNING_ERR); 322 } 323 } 324 325 @SuppressWarnings("unchecked") 326 private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags) 327 throws RemoteException { 328 final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>(); 329 PackageInfo lastItem = null; 330 ParceledListSlice<PackageInfo> slice; 331 332 do { 333 final String lastKey = lastItem != null ? lastItem.packageName : null; 334 slice = pm.getInstalledPackages(flags, lastKey); 335 lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR); 336 } while (!slice.isLastSlice()); 337 338 return packageInfos; 339 } 340 341 /** 342 * Lists all of the features supported by the current device. 343 * 344 * pm list features 345 */ 346 private void runListFeatures() { 347 try { 348 List<FeatureInfo> list = new ArrayList<FeatureInfo>(); 349 FeatureInfo[] rawList = mPm.getSystemAvailableFeatures(); 350 for (int i=0; i<rawList.length; i++) { 351 list.add(rawList[i]); 352 } 353 354 355 // Sort by name 356 Collections.sort(list, new Comparator<FeatureInfo>() { 357 public int compare(FeatureInfo o1, FeatureInfo o2) { 358 if (o1.name == o2.name) return 0; 359 if (o1.name == null) return -1; 360 if (o2.name == null) return 1; 361 return o1.name.compareTo(o2.name); 362 } 363 }); 364 365 int count = (list != null) ? list.size() : 0; 366 for (int p = 0; p < count; p++) { 367 FeatureInfo fi = list.get(p); 368 System.out.print("feature:"); 369 if (fi.name != null) System.out.println(fi.name); 370 else System.out.println("reqGlEsVersion=0x" 371 + Integer.toHexString(fi.reqGlEsVersion)); 372 } 373 } catch (RemoteException e) { 374 System.err.println(e.toString()); 375 System.err.println(PM_NOT_RUNNING_ERR); 376 } 377 } 378 379 /** 380 * Lists all of the libraries supported by the current device. 381 * 382 * pm list libraries 383 */ 384 private void runListLibraries() { 385 try { 386 List<String> list = new ArrayList<String>(); 387 String[] rawList = mPm.getSystemSharedLibraryNames(); 388 for (int i=0; i<rawList.length; i++) { 389 list.add(rawList[i]); 390 } 391 392 393 // Sort by name 394 Collections.sort(list, new Comparator<String>() { 395 public int compare(String o1, String o2) { 396 if (o1 == o2) return 0; 397 if (o1 == null) return -1; 398 if (o2 == null) return 1; 399 return o1.compareTo(o2); 400 } 401 }); 402 403 int count = (list != null) ? list.size() : 0; 404 for (int p = 0; p < count; p++) { 405 String lib = list.get(p); 406 System.out.print("library:"); 407 System.out.println(lib); 408 } 409 } catch (RemoteException e) { 410 System.err.println(e.toString()); 411 System.err.println(PM_NOT_RUNNING_ERR); 412 } 413 } 414 415 /** 416 * Lists all of the installed instrumentation, or all for a given package 417 * 418 * pm list instrumentation [package] [-f] 419 */ 420 private void runListInstrumentation() { 421 int flags = 0; // flags != 0 is only used to request meta-data 422 boolean showPackage = false; 423 String targetPackage = null; 424 425 try { 426 String opt; 427 while ((opt=nextArg()) != null) { 428 if (opt.equals("-f")) { 429 showPackage = true; 430 } else if (opt.charAt(0) != '-') { 431 targetPackage = opt; 432 } else { 433 System.err.println("Error: Unknown option: " + opt); 434 showUsage(); 435 return; 436 } 437 } 438 } catch (RuntimeException ex) { 439 System.err.println("Error: " + ex.toString()); 440 showUsage(); 441 return; 442 } 443 444 try { 445 List<InstrumentationInfo> list = mPm.queryInstrumentation(targetPackage, flags); 446 447 // Sort by target package 448 Collections.sort(list, new Comparator<InstrumentationInfo>() { 449 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) { 450 return o1.targetPackage.compareTo(o2.targetPackage); 451 } 452 }); 453 454 int count = (list != null) ? list.size() : 0; 455 for (int p = 0; p < count; p++) { 456 InstrumentationInfo ii = list.get(p); 457 System.out.print("instrumentation:"); 458 if (showPackage) { 459 System.out.print(ii.sourceDir); 460 System.out.print("="); 461 } 462 ComponentName cn = new ComponentName(ii.packageName, ii.name); 463 System.out.print(cn.flattenToShortString()); 464 System.out.print(" (target="); 465 System.out.print(ii.targetPackage); 466 System.out.println(")"); 467 } 468 } catch (RemoteException e) { 469 System.err.println(e.toString()); 470 System.err.println(PM_NOT_RUNNING_ERR); 471 } 472 } 473 474 /** 475 * Lists all the known permission groups. 476 */ 477 private void runListPermissionGroups() { 478 try { 479 List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0); 480 481 int count = pgs.size(); 482 for (int p = 0 ; p < count ; p++) { 483 PermissionGroupInfo pgi = pgs.get(p); 484 System.out.print("permission group:"); 485 System.out.println(pgi.name); 486 } 487 } catch (RemoteException e) { 488 System.err.println(e.toString()); 489 System.err.println(PM_NOT_RUNNING_ERR); 490 } 491 } 492 493 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) { 494 if (nonLocalized != null) { 495 return nonLocalized.toString(); 496 } 497 if (res != 0) { 498 Resources r = getResources(pii); 499 if (r != null) { 500 return r.getString(res); 501 } 502 } 503 return null; 504 } 505 506 /** 507 * Lists all the permissions in a group. 508 */ 509 private void runListPermissions() { 510 try { 511 boolean labels = false; 512 boolean groups = false; 513 boolean userOnly = false; 514 boolean summary = false; 515 boolean dangerousOnly = false; 516 String opt; 517 while ((opt=nextOption()) != null) { 518 if (opt.equals("-f")) { 519 labels = true; 520 } else if (opt.equals("-g")) { 521 groups = true; 522 } else if (opt.equals("-s")) { 523 groups = true; 524 labels = true; 525 summary = true; 526 } else if (opt.equals("-u")) { 527 userOnly = true; 528 } else if (opt.equals("-d")) { 529 dangerousOnly = true; 530 } else { 531 System.err.println("Error: Unknown option: " + opt); 532 showUsage(); 533 return; 534 } 535 } 536 537 String grp = nextOption(); 538 ArrayList<String> groupList = new ArrayList<String>(); 539 if (groups) { 540 List<PermissionGroupInfo> infos = 541 mPm.getAllPermissionGroups(0); 542 for (int i=0; i<infos.size(); i++) { 543 groupList.add(infos.get(i).name); 544 } 545 groupList.add(null); 546 } else { 547 groupList.add(grp); 548 } 549 550 if (dangerousOnly) { 551 System.out.println("Dangerous Permissions:"); 552 System.out.println(""); 553 doListPermissions(groupList, groups, labels, summary, 554 PermissionInfo.PROTECTION_DANGEROUS, 555 PermissionInfo.PROTECTION_DANGEROUS); 556 if (userOnly) { 557 System.out.println("Normal Permissions:"); 558 System.out.println(""); 559 doListPermissions(groupList, groups, labels, summary, 560 PermissionInfo.PROTECTION_NORMAL, 561 PermissionInfo.PROTECTION_NORMAL); 562 } 563 } else if (userOnly) { 564 System.out.println("Dangerous and Normal Permissions:"); 565 System.out.println(""); 566 doListPermissions(groupList, groups, labels, summary, 567 PermissionInfo.PROTECTION_NORMAL, 568 PermissionInfo.PROTECTION_DANGEROUS); 569 } else { 570 System.out.println("All Permissions:"); 571 System.out.println(""); 572 doListPermissions(groupList, groups, labels, summary, 573 -10000, 10000); 574 } 575 } catch (RemoteException e) { 576 System.err.println(e.toString()); 577 System.err.println(PM_NOT_RUNNING_ERR); 578 } 579 } 580 581 private void doListPermissions(ArrayList<String> groupList, 582 boolean groups, boolean labels, boolean summary, 583 int startProtectionLevel, int endProtectionLevel) 584 throws RemoteException { 585 for (int i=0; i<groupList.size(); i++) { 586 String groupName = groupList.get(i); 587 String prefix = ""; 588 if (groups) { 589 if (i > 0) System.out.println(""); 590 if (groupName != null) { 591 PermissionGroupInfo pgi = mPm.getPermissionGroupInfo( 592 groupName, 0); 593 if (summary) { 594 Resources res = getResources(pgi); 595 if (res != null) { 596 System.out.print(loadText(pgi, pgi.labelRes, 597 pgi.nonLocalizedLabel) + ": "); 598 } else { 599 System.out.print(pgi.name + ": "); 600 601 } 602 } else { 603 System.out.println((labels ? "+ " : "") 604 + "group:" + pgi.name); 605 if (labels) { 606 System.out.println(" package:" + pgi.packageName); 607 Resources res = getResources(pgi); 608 if (res != null) { 609 System.out.println(" label:" 610 + loadText(pgi, pgi.labelRes, 611 pgi.nonLocalizedLabel)); 612 System.out.println(" description:" 613 + loadText(pgi, pgi.descriptionRes, 614 pgi.nonLocalizedDescription)); 615 } 616 } 617 } 618 } else { 619 System.out.println(((labels && !summary) 620 ? "+ " : "") + "ungrouped:"); 621 } 622 prefix = " "; 623 } 624 List<PermissionInfo> ps = mPm.queryPermissionsByGroup( 625 groupList.get(i), 0); 626 int count = ps.size(); 627 boolean first = true; 628 for (int p = 0 ; p < count ; p++) { 629 PermissionInfo pi = ps.get(p); 630 if (groups && groupName == null && pi.group != null) { 631 continue; 632 } 633 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; 634 if (base < startProtectionLevel 635 || base > endProtectionLevel) { 636 continue; 637 } 638 if (summary) { 639 if (first) { 640 first = false; 641 } else { 642 System.out.print(", "); 643 } 644 Resources res = getResources(pi); 645 if (res != null) { 646 System.out.print(loadText(pi, pi.labelRes, 647 pi.nonLocalizedLabel)); 648 } else { 649 System.out.print(pi.name); 650 } 651 } else { 652 System.out.println(prefix + (labels ? "+ " : "") 653 + "permission:" + pi.name); 654 if (labels) { 655 System.out.println(prefix + " package:" + pi.packageName); 656 Resources res = getResources(pi); 657 if (res != null) { 658 System.out.println(prefix + " label:" 659 + loadText(pi, pi.labelRes, 660 pi.nonLocalizedLabel)); 661 System.out.println(prefix + " description:" 662 + loadText(pi, pi.descriptionRes, 663 pi.nonLocalizedDescription)); 664 } 665 System.out.println(prefix + " protectionLevel:" 666 + PermissionInfo.protectionToString(pi.protectionLevel)); 667 } 668 } 669 } 670 671 if (summary) { 672 System.out.println(""); 673 } 674 } 675 } 676 677 private void runPath() { 678 String pkg = nextArg(); 679 if (pkg == null) { 680 System.err.println("Error: no package specified"); 681 showUsage(); 682 return; 683 } 684 displayPackageFilePath(pkg); 685 } 686 687 class PackageInstallObserver extends IPackageInstallObserver.Stub { 688 boolean finished; 689 int result; 690 691 public void packageInstalled(String name, int status) { 692 synchronized( this) { 693 finished = true; 694 result = status; 695 notifyAll(); 696 } 697 } 698 } 699 700 /** 701 * Converts a failure code into a string by using reflection to find a matching constant 702 * in PackageManager. 703 */ 704 private String installFailureToString(int result) { 705 Field[] fields = PackageManager.class.getFields(); 706 for (Field f: fields) { 707 if (f.getType() == int.class) { 708 int modifiers = f.getModifiers(); 709 // only look at public final static fields. 710 if (((modifiers & Modifier.FINAL) != 0) && 711 ((modifiers & Modifier.PUBLIC) != 0) && 712 ((modifiers & Modifier.STATIC) != 0)) { 713 String fieldName = f.getName(); 714 if (fieldName.startsWith("INSTALL_FAILED_") || 715 fieldName.startsWith("INSTALL_PARSE_FAILED_")) { 716 // get the int value and compare it to result. 717 try { 718 if (result == f.getInt(null)) { 719 return fieldName; 720 } 721 } catch (IllegalAccessException e) { 722 // this shouldn't happen since we only look for public static fields. 723 } 724 } 725 } 726 } 727 } 728 729 // couldn't find a matching constant? return the value 730 return Integer.toString(result); 731 } 732 733 private void runSetInstallLocation() { 734 int loc; 735 736 String arg = nextArg(); 737 if (arg == null) { 738 System.err.println("Error: no install location specified."); 739 showUsage(); 740 return; 741 } 742 try { 743 loc = Integer.parseInt(arg); 744 } catch (NumberFormatException e) { 745 System.err.println("Error: install location has to be a number."); 746 showUsage(); 747 return; 748 } 749 try { 750 if (!mPm.setInstallLocation(loc)) { 751 System.err.println("Error: install location has to be a number."); 752 showUsage(); 753 } 754 } catch (RemoteException e) { 755 System.err.println(e.toString()); 756 System.err.println(PM_NOT_RUNNING_ERR); 757 } 758 } 759 760 private void runGetInstallLocation() { 761 try { 762 int loc = mPm.getInstallLocation(); 763 String locStr = "invalid"; 764 if (loc == PackageHelper.APP_INSTALL_AUTO) { 765 locStr = "auto"; 766 } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) { 767 locStr = "internal"; 768 } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) { 769 locStr = "external"; 770 } 771 System.out.println(loc + "[" + locStr + "]"); 772 } catch (RemoteException e) { 773 System.err.println(e.toString()); 774 System.err.println(PM_NOT_RUNNING_ERR); 775 } 776 } 777 778 private void runInstall() { 779 int installFlags = 0; 780 String installerPackageName = null; 781 782 String opt; 783 784 String algo = null; 785 byte[] iv = null; 786 byte[] key = null; 787 788 String macAlgo = null; 789 byte[] macKey = null; 790 byte[] tag = null; 791 String originatingUriString = null; 792 String referrer = null; 793 794 while ((opt=nextOption()) != null) { 795 if (opt.equals("-l")) { 796 installFlags |= PackageManager.INSTALL_FORWARD_LOCK; 797 } else if (opt.equals("-r")) { 798 installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 799 } else if (opt.equals("-i")) { 800 installerPackageName = nextOptionData(); 801 if (installerPackageName == null) { 802 System.err.println("Error: no value specified for -i"); 803 showUsage(); 804 return; 805 } 806 } else if (opt.equals("-t")) { 807 installFlags |= PackageManager.INSTALL_ALLOW_TEST; 808 } else if (opt.equals("-s")) { 809 // Override if -s option is specified. 810 installFlags |= PackageManager.INSTALL_EXTERNAL; 811 } else if (opt.equals("-f")) { 812 // Override if -s option is specified. 813 installFlags |= PackageManager.INSTALL_INTERNAL; 814 } else if (opt.equals("--algo")) { 815 algo = nextOptionData(); 816 if (algo == null) { 817 System.err.println("Error: must supply argument for --algo"); 818 showUsage(); 819 return; 820 } 821 } else if (opt.equals("--iv")) { 822 iv = hexToBytes(nextOptionData()); 823 if (iv == null) { 824 System.err.println("Error: must supply argument for --iv"); 825 showUsage(); 826 return; 827 } 828 } else if (opt.equals("--key")) { 829 key = hexToBytes(nextOptionData()); 830 if (key == null) { 831 System.err.println("Error: must supply argument for --key"); 832 showUsage(); 833 return; 834 } 835 } else if (opt.equals("--macalgo")) { 836 macAlgo = nextOptionData(); 837 if (macAlgo == null) { 838 System.err.println("Error: must supply argument for --macalgo"); 839 showUsage(); 840 return; 841 } 842 } else if (opt.equals("--mackey")) { 843 macKey = hexToBytes(nextOptionData()); 844 if (macKey == null) { 845 System.err.println("Error: must supply argument for --mackey"); 846 showUsage(); 847 return; 848 } 849 } else if (opt.equals("--tag")) { 850 tag = hexToBytes(nextOptionData()); 851 if (tag == null) { 852 System.err.println("Error: must supply argument for --tag"); 853 showUsage(); 854 return; 855 } 856 } else if (opt.equals("--originating-uri")) { 857 originatingUriString = nextOptionData(); 858 if (originatingUriString == null) { 859 System.err.println("Error: must supply argument for --originating-uri"); 860 showUsage(); 861 return; 862 } 863 } else if (opt.equals("--referrer")) { 864 referrer = nextOptionData(); 865 if (referrer == null) { 866 System.err.println("Error: must supply argument for --referrer"); 867 showUsage(); 868 return; 869 } 870 } else { 871 System.err.println("Error: Unknown option: " + opt); 872 showUsage(); 873 return; 874 } 875 } 876 877 final ContainerEncryptionParams encryptionParams; 878 if (algo != null || iv != null || key != null || macAlgo != null || macKey != null 879 || tag != null) { 880 if (algo == null || iv == null || key == null) { 881 System.err.println("Error: all of --algo, --iv, and --key must be specified"); 882 showUsage(); 883 return; 884 } 885 886 if (macAlgo != null || macKey != null || tag != null) { 887 if (macAlgo == null || macKey == null || tag == null) { 888 System.err.println("Error: all of --macalgo, --mackey, and --tag must " 889 + "be specified"); 890 showUsage(); 891 return; 892 } 893 } 894 895 try { 896 final SecretKey encKey = new SecretKeySpec(key, "RAW"); 897 898 final SecretKey macSecretKey; 899 if (macKey == null || macKey.length == 0) { 900 macSecretKey = null; 901 } else { 902 macSecretKey = new SecretKeySpec(macKey, "RAW"); 903 } 904 905 encryptionParams = new ContainerEncryptionParams(algo, new IvParameterSpec(iv), 906 encKey, macAlgo, null, macSecretKey, tag, -1, -1, -1); 907 } catch (InvalidAlgorithmParameterException e) { 908 e.printStackTrace(); 909 return; 910 } 911 } else { 912 encryptionParams = null; 913 } 914 915 final Uri apkURI; 916 final Uri verificationURI; 917 final Uri originatingURI; 918 final Uri referrerURI; 919 920 if (originatingUriString != null) { 921 originatingURI = Uri.parse(originatingUriString); 922 } else { 923 originatingURI = null; 924 } 925 926 if (referrer != null) { 927 referrerURI = Uri.parse(referrer); 928 } else { 929 referrerURI = null; 930 } 931 932 // Populate apkURI, must be present 933 final String apkFilePath = nextArg(); 934 System.err.println("\tpkg: " + apkFilePath); 935 if (apkFilePath != null) { 936 apkURI = Uri.fromFile(new File(apkFilePath)); 937 } else { 938 System.err.println("Error: no package specified"); 939 showUsage(); 940 return; 941 } 942 943 // Populate verificationURI, optionally present 944 final String verificationFilePath = nextArg(); 945 if (verificationFilePath != null) { 946 System.err.println("\tver: " + verificationFilePath); 947 verificationURI = Uri.fromFile(new File(verificationFilePath)); 948 } else { 949 verificationURI = null; 950 } 951 952 PackageInstallObserver obs = new PackageInstallObserver(); 953 try { 954 VerificationParams verificationParams = new VerificationParams(verificationURI, 955 originatingURI, referrerURI, null); 956 957 mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags, 958 installerPackageName, verificationParams, encryptionParams); 959 960 synchronized (obs) { 961 while (!obs.finished) { 962 try { 963 obs.wait(); 964 } catch (InterruptedException e) { 965 } 966 } 967 if (obs.result == PackageManager.INSTALL_SUCCEEDED) { 968 System.out.println("Success"); 969 } else { 970 System.err.println("Failure [" 971 + installFailureToString(obs.result) 972 + "]"); 973 } 974 } 975 } catch (RemoteException e) { 976 System.err.println(e.toString()); 977 System.err.println(PM_NOT_RUNNING_ERR); 978 } 979 } 980 981 /** 982 * Convert a string containing hex-encoded bytes to a byte array. 983 * 984 * @param input String containing hex-encoded bytes 985 * @return input as an array of bytes 986 */ 987 private byte[] hexToBytes(String input) { 988 if (input == null) { 989 return null; 990 } 991 992 final int inputLength = input.length(); 993 if ((inputLength % 2) != 0) { 994 System.err.print("Invalid length; must be multiple of 2"); 995 return null; 996 } 997 998 final int byteLength = inputLength / 2; 999 final byte[] output = new byte[byteLength]; 1000 1001 int inputIndex = 0; 1002 int byteIndex = 0; 1003 while (inputIndex < inputLength) { 1004 output[byteIndex++] = (byte) Integer.parseInt( 1005 input.substring(inputIndex, inputIndex + 2), 16); 1006 inputIndex += 2; 1007 } 1008 1009 return output; 1010 } 1011 1012 public void runCreateUser() { 1013 // Need to be run as root 1014 if (Process.myUid() != ROOT_UID) { 1015 System.err.println("Error: create-user must be run as root"); 1016 return; 1017 } 1018 String name; 1019 String arg = nextArg(); 1020 if (arg == null) { 1021 System.err.println("Error: no user name specified."); 1022 showUsage(); 1023 return; 1024 } 1025 name = arg; 1026 try { 1027 if (mUm.createUser(name, 0) == null) { 1028 System.err.println("Error: couldn't create User."); 1029 showUsage(); 1030 } 1031 } catch (RemoteException e) { 1032 System.err.println(e.toString()); 1033 System.err.println(PM_NOT_RUNNING_ERR); 1034 } 1035 1036 } 1037 1038 public void runRemoveUser() { 1039 // Need to be run as root 1040 if (Process.myUid() != ROOT_UID) { 1041 System.err.println("Error: remove-user must be run as root"); 1042 return; 1043 } 1044 int userId; 1045 String arg = nextArg(); 1046 if (arg == null) { 1047 System.err.println("Error: no user id specified."); 1048 showUsage(); 1049 return; 1050 } 1051 try { 1052 userId = Integer.parseInt(arg); 1053 } catch (NumberFormatException e) { 1054 System.err.println("Error: user id has to be a number."); 1055 showUsage(); 1056 return; 1057 } 1058 try { 1059 if (!mUm.removeUser(userId)) { 1060 System.err.println("Error: couldn't remove user."); 1061 showUsage(); 1062 } 1063 } catch (RemoteException e) { 1064 System.err.println(e.toString()); 1065 System.err.println(PM_NOT_RUNNING_ERR); 1066 } 1067 } 1068 1069 public void runListUsers() { 1070 // Need to be run as root 1071 if (Process.myUid() != ROOT_UID) { 1072 System.err.println("Error: list-users must be run as root"); 1073 return; 1074 } 1075 try { 1076 List<UserInfo> users = mUm.getUsers(); 1077 if (users == null) { 1078 System.err.println("Error: couldn't get users"); 1079 } else { 1080 System.out.println("Users:"); 1081 for (int i = 0; i < users.size(); i++) { 1082 System.out.println("\t" + users.get(i).toString()); 1083 } 1084 } 1085 } catch (RemoteException e) { 1086 System.err.println(e.toString()); 1087 System.err.println(PM_NOT_RUNNING_ERR); 1088 } 1089 } 1090 class PackageDeleteObserver extends IPackageDeleteObserver.Stub { 1091 boolean finished; 1092 boolean result; 1093 1094 public void packageDeleted(String packageName, int returnCode) { 1095 synchronized (this) { 1096 finished = true; 1097 result = returnCode == PackageManager.DELETE_SUCCEEDED; 1098 notifyAll(); 1099 } 1100 } 1101 } 1102 1103 private void runUninstall() { 1104 int unInstallFlags = 0; 1105 1106 String opt = nextOption(); 1107 if (opt != null && opt.equals("-k")) { 1108 unInstallFlags = PackageManager.DONT_DELETE_DATA; 1109 } 1110 1111 String pkg = nextArg(); 1112 if (pkg == null) { 1113 System.err.println("Error: no package specified"); 1114 showUsage(); 1115 return; 1116 } 1117 boolean result = deletePackage(pkg, unInstallFlags); 1118 if (result) { 1119 System.out.println("Success"); 1120 } else { 1121 System.out.println("Failure"); 1122 } 1123 } 1124 1125 private boolean deletePackage(String pkg, int unInstallFlags) { 1126 PackageDeleteObserver obs = new PackageDeleteObserver(); 1127 try { 1128 mPm.deletePackage(pkg, obs, unInstallFlags); 1129 1130 synchronized (obs) { 1131 while (!obs.finished) { 1132 try { 1133 obs.wait(); 1134 } catch (InterruptedException e) { 1135 } 1136 } 1137 } 1138 } catch (RemoteException e) { 1139 System.err.println(e.toString()); 1140 System.err.println(PM_NOT_RUNNING_ERR); 1141 } 1142 return obs.result; 1143 } 1144 1145 static class ClearDataObserver extends IPackageDataObserver.Stub { 1146 boolean finished; 1147 boolean result; 1148 1149 @Override 1150 public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { 1151 synchronized (this) { 1152 finished = true; 1153 result = succeeded; 1154 notifyAll(); 1155 } 1156 } 1157 1158 } 1159 1160 private void runClear() { 1161 String pkg = nextArg(); 1162 if (pkg == null) { 1163 System.err.println("Error: no package specified"); 1164 showUsage(); 1165 return; 1166 } 1167 1168 ClearDataObserver obs = new ClearDataObserver(); 1169 try { 1170 if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, 1171 Binder.getOrigCallingUser())) { 1172 System.err.println("Failed"); 1173 } 1174 1175 synchronized (obs) { 1176 while (!obs.finished) { 1177 try { 1178 obs.wait(); 1179 } catch (InterruptedException e) { 1180 } 1181 } 1182 } 1183 1184 if (obs.result) { 1185 System.err.println("Success"); 1186 } else { 1187 System.err.println("Failed"); 1188 } 1189 } catch (RemoteException e) { 1190 System.err.println(e.toString()); 1191 System.err.println(PM_NOT_RUNNING_ERR); 1192 } 1193 } 1194 1195 private static String enabledSettingToString(int state) { 1196 switch (state) { 1197 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT: 1198 return "default"; 1199 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED: 1200 return "enabled"; 1201 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: 1202 return "disabled"; 1203 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER: 1204 return "disabled-user"; 1205 } 1206 return "unknown"; 1207 } 1208 1209 private boolean isNumber(String s) { 1210 try { 1211 Integer.parseInt(s); 1212 } catch (NumberFormatException nfe) { 1213 return false; 1214 } 1215 return true; 1216 } 1217 1218 private void runSetEnabledSetting(int state) { 1219 int userId = 0; 1220 String option = nextOption(); 1221 if (option != null && option.equals("--user")) { 1222 String optionData = nextOptionData(); 1223 if (optionData == null || !isNumber(optionData)) { 1224 System.err.println("Error: no USER_ID specified"); 1225 showUsage(); 1226 return; 1227 } else { 1228 userId = Integer.parseInt(optionData); 1229 } 1230 } 1231 1232 String pkg = nextArg(); 1233 if (pkg == null) { 1234 System.err.println("Error: no package or component specified"); 1235 showUsage(); 1236 return; 1237 } 1238 ComponentName cn = ComponentName.unflattenFromString(pkg); 1239 if (cn == null) { 1240 try { 1241 mPm.setApplicationEnabledSetting(pkg, state, 0, userId); 1242 System.err.println("Package " + pkg + " new state: " 1243 + enabledSettingToString( 1244 mPm.getApplicationEnabledSetting(pkg, userId))); 1245 } catch (RemoteException e) { 1246 System.err.println(e.toString()); 1247 System.err.println(PM_NOT_RUNNING_ERR); 1248 } 1249 } else { 1250 try { 1251 mPm.setComponentEnabledSetting(cn, state, 0, userId); 1252 System.err.println("Component " + cn.toShortString() + " new state: " 1253 + enabledSettingToString( 1254 mPm.getComponentEnabledSetting(cn, userId))); 1255 } catch (RemoteException e) { 1256 System.err.println(e.toString()); 1257 System.err.println(PM_NOT_RUNNING_ERR); 1258 } 1259 } 1260 } 1261 1262 private void runGrantRevokePermission(boolean grant) { 1263 String pkg = nextArg(); 1264 if (pkg == null) { 1265 System.err.println("Error: no package specified"); 1266 showUsage(); 1267 return; 1268 } 1269 String perm = nextArg(); 1270 if (perm == null) { 1271 System.err.println("Error: no permission specified"); 1272 showUsage(); 1273 return; 1274 } 1275 try { 1276 if (grant) { 1277 mPm.grantPermission(pkg, perm); 1278 } else { 1279 mPm.revokePermission(pkg, perm); 1280 } 1281 } catch (RemoteException e) { 1282 System.err.println(e.toString()); 1283 System.err.println(PM_NOT_RUNNING_ERR); 1284 } catch (IllegalArgumentException e) { 1285 System.err.println("Bad argument: " + e.toString()); 1286 showUsage(); 1287 } catch (SecurityException e) { 1288 System.err.println("Operation not allowed: " + e.toString()); 1289 } 1290 } 1291 1292 private void runSetPermissionEnforced() { 1293 final String permission = nextArg(); 1294 if (permission == null) { 1295 System.err.println("Error: no permission specified"); 1296 showUsage(); 1297 return; 1298 } 1299 final String enforcedRaw = nextArg(); 1300 if (enforcedRaw == null) { 1301 System.err.println("Error: no enforcement specified"); 1302 showUsage(); 1303 return; 1304 } 1305 final boolean enforced = Boolean.parseBoolean(enforcedRaw); 1306 try { 1307 mPm.setPermissionEnforced(permission, enforced); 1308 } catch (RemoteException e) { 1309 System.err.println(e.toString()); 1310 System.err.println(PM_NOT_RUNNING_ERR); 1311 } catch (IllegalArgumentException e) { 1312 System.err.println("Bad argument: " + e.toString()); 1313 showUsage(); 1314 } catch (SecurityException e) { 1315 System.err.println("Operation not allowed: " + e.toString()); 1316 } 1317 } 1318 1319 static class ClearCacheObserver extends IPackageDataObserver.Stub { 1320 boolean finished; 1321 boolean result; 1322 1323 @Override 1324 public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { 1325 synchronized (this) { 1326 finished = true; 1327 result = succeeded; 1328 notifyAll(); 1329 } 1330 } 1331 1332 } 1333 1334 private void runTrimCaches() { 1335 String size = nextArg(); 1336 if (size == null) { 1337 System.err.println("Error: no size specified"); 1338 showUsage(); 1339 return; 1340 } 1341 int len = size.length(); 1342 long multiplier = 1; 1343 if (len > 1) { 1344 char c = size.charAt(len-1); 1345 if (c == 'K' || c == 'k') { 1346 multiplier = 1024L; 1347 } else if (c == 'M' || c == 'm') { 1348 multiplier = 1024L*1024L; 1349 } else if (c == 'G' || c == 'g') { 1350 multiplier = 1024L*1024L*1024L; 1351 } else { 1352 System.err.println("Invalid suffix: " + c); 1353 showUsage(); 1354 return; 1355 } 1356 size = size.substring(0, len-1); 1357 } 1358 long sizeVal; 1359 try { 1360 sizeVal = Long.parseLong(size) * multiplier; 1361 } catch (NumberFormatException e) { 1362 System.err.println("Error: expected number at: " + size); 1363 showUsage(); 1364 return; 1365 } 1366 ClearDataObserver obs = new ClearDataObserver(); 1367 try { 1368 mPm.freeStorageAndNotify(sizeVal, obs); 1369 synchronized (obs) { 1370 while (!obs.finished) { 1371 try { 1372 obs.wait(); 1373 } catch (InterruptedException e) { 1374 } 1375 } 1376 } 1377 } catch (RemoteException e) { 1378 System.err.println(e.toString()); 1379 System.err.println(PM_NOT_RUNNING_ERR); 1380 } catch (IllegalArgumentException e) { 1381 System.err.println("Bad argument: " + e.toString()); 1382 showUsage(); 1383 } catch (SecurityException e) { 1384 System.err.println("Operation not allowed: " + e.toString()); 1385 } 1386 } 1387 1388 /** 1389 * Displays the package file for a package. 1390 * @param pckg 1391 */ 1392 private void displayPackageFilePath(String pckg) { 1393 try { 1394 PackageInfo info = mPm.getPackageInfo(pckg, 0, 0); 1395 if (info != null && info.applicationInfo != null) { 1396 System.out.print("package:"); 1397 System.out.println(info.applicationInfo.sourceDir); 1398 } 1399 } catch (RemoteException e) { 1400 System.err.println(e.toString()); 1401 System.err.println(PM_NOT_RUNNING_ERR); 1402 } 1403 } 1404 1405 private Resources getResources(PackageItemInfo pii) { 1406 Resources res = mResourceCache.get(pii.packageName); 1407 if (res != null) return res; 1408 1409 try { 1410 ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0, 0); 1411 AssetManager am = new AssetManager(); 1412 am.addAssetPath(ai.publicSourceDir); 1413 res = new Resources(am, null, null); 1414 mResourceCache.put(pii.packageName, res); 1415 return res; 1416 } catch (RemoteException e) { 1417 System.err.println(e.toString()); 1418 System.err.println(PM_NOT_RUNNING_ERR); 1419 return null; 1420 } 1421 } 1422 1423 private String nextOption() { 1424 if (mNextArg >= mArgs.length) { 1425 return null; 1426 } 1427 String arg = mArgs[mNextArg]; 1428 if (!arg.startsWith("-")) { 1429 return null; 1430 } 1431 mNextArg++; 1432 if (arg.equals("--")) { 1433 return null; 1434 } 1435 if (arg.length() > 1 && arg.charAt(1) != '-') { 1436 if (arg.length() > 2) { 1437 mCurArgData = arg.substring(2); 1438 return arg.substring(0, 2); 1439 } else { 1440 mCurArgData = null; 1441 return arg; 1442 } 1443 } 1444 mCurArgData = null; 1445 return arg; 1446 } 1447 1448 private String nextOptionData() { 1449 if (mCurArgData != null) { 1450 return mCurArgData; 1451 } 1452 if (mNextArg >= mArgs.length) { 1453 return null; 1454 } 1455 String data = mArgs[mNextArg]; 1456 mNextArg++; 1457 return data; 1458 } 1459 1460 private String nextArg() { 1461 if (mNextArg >= mArgs.length) { 1462 return null; 1463 } 1464 String arg = mArgs[mNextArg]; 1465 mNextArg++; 1466 return arg; 1467 } 1468 1469 private static void showUsage() { 1470 System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [FILTER]"); 1471 System.err.println(" pm list permission-groups"); 1472 System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]"); 1473 System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]"); 1474 System.err.println(" pm list features"); 1475 System.err.println(" pm list libraries"); 1476 System.err.println(" pm path PACKAGE"); 1477 System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]"); 1478 System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]"); 1479 System.err.println(" [--originating-uri <URI>] [--referrer <URI>] PATH"); 1480 System.err.println(" pm uninstall [-k] PACKAGE"); 1481 System.err.println(" pm clear PACKAGE"); 1482 System.err.println(" pm enable PACKAGE_OR_COMPONENT"); 1483 System.err.println(" pm disable PACKAGE_OR_COMPONENT"); 1484 System.err.println(" pm disable-user PACKAGE_OR_COMPONENT"); 1485 System.err.println(" pm grant PACKAGE PERMISSION"); 1486 System.err.println(" pm revoke PACKAGE PERMISSION"); 1487 System.err.println(" pm set-install-location [0/auto] [1/internal] [2/external]"); 1488 System.err.println(" pm get-install-location"); 1489 System.err.println(" pm set-permission-enforced PERMISSION [true|false]"); 1490 System.err.println(" pm trim-caches DESIRED_FREE_SPACE"); 1491 System.err.println(""); 1492 System.err.println("pm list packages: prints all packages, optionally only"); 1493 System.err.println(" those whose package name contains the text in FILTER. Options:"); 1494 System.err.println(" -f: see their associated file."); 1495 System.err.println(" -d: filter to only show disbled packages."); 1496 System.err.println(" -e: filter to only show enabled packages."); 1497 System.err.println(" -s: filter to only show system packages."); 1498 System.err.println(" -3: filter to only show third party packages."); 1499 System.err.println(" -i: see the installer for the packages."); 1500 System.err.println(" -u: also include uninstalled packages."); 1501 System.err.println(""); 1502 System.err.println("pm list permission-groups: prints all known permission groups."); 1503 System.err.println(""); 1504 System.err.println("pm list permissions: prints all known permissions, optionally only"); 1505 System.err.println(" those in GROUP. Options:"); 1506 System.err.println(" -g: organize by group."); 1507 System.err.println(" -f: print all information."); 1508 System.err.println(" -s: short summary."); 1509 System.err.println(" -d: only list dangerous permissions."); 1510 System.err.println(" -u: list only the permissions users will see."); 1511 System.err.println(""); 1512 System.err.println("pm list instrumentation: use to list all test packages; optionally"); 1513 System.err.println(" supply <TARGET-PACKAGE> to list the test packages for a particular"); 1514 System.err.println(" application. Options:"); 1515 System.err.println(" -f: list the .apk file for the test package."); 1516 System.err.println(""); 1517 System.err.println("pm list features: prints all features of the system."); 1518 System.err.println(""); 1519 System.err.println("pm path: print the path to the .apk of the given PACKAGE."); 1520 System.err.println(""); 1521 System.err.println("pm install: installs a package to the system. Options:"); 1522 System.err.println(" -l: install the package with FORWARD_LOCK."); 1523 System.err.println(" -r: reinstall an exisiting app, keeping its data."); 1524 System.err.println(" -t: allow test .apks to be installed."); 1525 System.err.println(" -i: specify the installer package name."); 1526 System.err.println(" -s: install package on sdcard."); 1527 System.err.println(" -f: install package on internal flash."); 1528 System.err.println(""); 1529 System.err.println("pm uninstall: removes a package from the system. Options:"); 1530 System.err.println(" -k: keep the data and cache directories around after package removal."); 1531 System.err.println(""); 1532 System.err.println("pm clear: deletes all data associated with a package."); 1533 System.err.println(""); 1534 System.err.println("pm enable, disable, disable-user: these commands change the enabled state"); 1535 System.err.println(" of a given package or component (written as \"package/class\")."); 1536 System.err.println(""); 1537 System.err.println("pm grant, revoke: these commands either grant or revoke permissions"); 1538 System.err.println(" to applications. Only optional permissions the application has"); 1539 System.err.println(" declared can be granted or revoked."); 1540 System.err.println(""); 1541 System.err.println("pm get-install-location: returns the current install location."); 1542 System.err.println(" 0 [auto]: Let system decide the best location"); 1543 System.err.println(" 1 [internal]: Install on internal device storage"); 1544 System.err.println(" 2 [external]: Install on external media"); 1545 System.err.println(""); 1546 System.err.println("pm set-install-location: changes the default install location."); 1547 System.err.println(" NOTE: this is only intended for debugging; using this can cause"); 1548 System.err.println(" applications to break and other undersireable behavior."); 1549 System.err.println(" 0 [auto]: Let system decide the best location"); 1550 System.err.println(" 1 [internal]: Install on internal device storage"); 1551 System.err.println(" 2 [external]: Install on external media"); 1552 System.err.println(""); 1553 System.err.println("pm trim-caches: trim cache files to reach the given free space."); 1554 } 1555} 1556