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