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