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