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