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