Pm.java revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
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 android.content.pm.ApplicationInfo; 20import android.content.pm.IPackageDeleteObserver; 21import android.content.pm.IPackageInstallObserver; 22import android.content.pm.IPackageManager; 23import android.content.pm.PackageInfo; 24import android.content.pm.PackageItemInfo; 25import android.content.pm.PackageManager; 26import android.content.pm.PackageParser; 27import android.content.pm.PermissionGroupInfo; 28import android.content.pm.PermissionInfo; 29import android.content.res.AssetManager; 30import android.content.res.Resources; 31import android.net.Uri; 32import android.os.RemoteException; 33import android.os.ServiceManager; 34 35import java.io.File; 36import java.lang.ref.WeakReference; 37import java.util.ArrayList; 38import java.util.List; 39import java.util.WeakHashMap; 40 41public final class Pm { 42 IPackageManager mPm; 43 44 private WeakHashMap<String, Resources> mResourceCache 45 = new WeakHashMap<String, Resources>(); 46 47 private String[] mArgs; 48 private int mNextArg; 49 private String mCurArgData; 50 51 public static void main(String[] args) { 52 new Pm().run(args); 53 } 54 55 public void run(String[] args) { 56 boolean validCommand = false; 57 if (args.length < 1) { 58 showUsage(); 59 return; 60 } 61 62 mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 63 if (mPm == null) { 64 System.err.println("Error Type 1: Could not access the Package Manager!"); 65 showUsage(); 66 return; 67 } 68 69 mArgs = args; 70 String op = args[0]; 71 mNextArg = 1; 72 73 if ("list".equals(op)) { 74 runList(); 75 return; 76 } 77 78 if ("path".equals(op)) { 79 runPath(); 80 return; 81 } 82 83 if ("install".equals(op)) { 84 runInstall(); 85 return; 86 } 87 88 if ("uninstall".equals(op)) { 89 runUninstall(); 90 return; 91 } 92 93 try { 94 if (args.length == 1) { 95 if (args[0].equalsIgnoreCase("-l")) { 96 validCommand = true; 97 runListPackages(false); 98 } else if (args[0].equalsIgnoreCase("-lf")){ 99 validCommand = true; 100 runListPackages(true); 101 } 102 } else if (args.length == 2) { 103 if (args[0].equalsIgnoreCase("-p")) { 104 validCommand = true; 105 displayPackageFilePath(args[1]); 106 } 107 } 108 } finally { 109 if (validCommand == false) { 110 showUsage(); 111 } 112 } 113 } 114 115 /** 116 * Execute the list sub-command. 117 */ 118 private void runList() { 119 String type = nextArg(); 120 if (type == null) { 121 System.err.println("Error: didn't specify type of data to list"); 122 showUsage(); 123 return; 124 } 125 if ("package".equals(type) || "packages".equals(type)) { 126 runListPackages(false); 127 } else if ("permission-groups".equals(type)) { 128 runListPermissionGroups(); 129 } else if ("permissions".equals(type)) { 130 runListPermissions(); 131 } else { 132 System.err.println("Error: unknown list type '" + type + "'"); 133 showUsage(); 134 } 135 } 136 137 /** 138 * Lists all the installed packages. 139 */ 140 private void runListPackages(boolean showApplicationPackage) { 141 try { 142 String opt; 143 while ((opt=nextOption()) != null) { 144 if (opt.equals("-l")) { 145 // old compat 146 } else if (opt.equals("-lf")) { 147 showApplicationPackage = true; 148 } else if (opt.equals("-f")) { 149 showApplicationPackage = true; 150 } else { 151 System.err.println("Error: Unknown option: " + opt); 152 showUsage(); 153 return; 154 } 155 } 156 } catch (RuntimeException ex) { 157 System.err.println("Error: " + ex.toString()); 158 showUsage(); 159 return; 160 } 161 162 try { 163 List<PackageInfo> packages = mPm.getInstalledPackages(0 /* all */); 164 165 int count = packages.size(); 166 for (int p = 0 ; p < count ; p++) { 167 PackageInfo info = packages.get(p); 168 System.out.print("package:"); 169 if (showApplicationPackage) { 170 System.out.print(info.applicationInfo.sourceDir); 171 System.out.print("="); 172 } 173 System.out.println(info.packageName); 174 } 175 } catch (RemoteException e) { 176 } 177 } 178 179 /** 180 * Lists all the known permission groups. 181 */ 182 private void runListPermissionGroups() { 183 try { 184 List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0); 185 186 int count = pgs.size(); 187 for (int p = 0 ; p < count ; p++) { 188 PermissionGroupInfo pgi = pgs.get(p); 189 System.out.print("permission group:"); 190 System.out.println(pgi.name); 191 } 192 } catch (RemoteException e) { 193 } 194 } 195 196 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) { 197 if (nonLocalized != null) { 198 return nonLocalized.toString(); 199 } 200 Resources r = getResources(pii); 201 if (r != null) { 202 return r.getString(res); 203 } 204 return null; 205 } 206 207 /** 208 * Lists all the permissions in a group. 209 */ 210 private void runListPermissions() { 211 try { 212 boolean labels = false; 213 boolean groups = false; 214 boolean userOnly = false; 215 boolean summary = false; 216 boolean dangerousOnly = false; 217 String opt; 218 while ((opt=nextOption()) != null) { 219 if (opt.equals("-f")) { 220 labels = true; 221 } else if (opt.equals("-g")) { 222 groups = true; 223 } else if (opt.equals("-s")) { 224 groups = true; 225 labels = true; 226 summary = true; 227 } else if (opt.equals("-u")) { 228 userOnly = true; 229 } else if (opt.equals("-d")) { 230 dangerousOnly = true; 231 } else { 232 System.err.println("Error: Unknown option: " + opt); 233 showUsage(); 234 return; 235 } 236 } 237 238 String grp = nextOption(); 239 ArrayList<String> groupList = new ArrayList<String>(); 240 if (groups) { 241 List<PermissionGroupInfo> infos = 242 mPm.getAllPermissionGroups(0); 243 for (int i=0; i<infos.size(); i++) { 244 groupList.add(infos.get(i).name); 245 } 246 groupList.add(null); 247 } else { 248 groupList.add(grp); 249 } 250 251 if (dangerousOnly) { 252 System.out.println("Dangerous Permissions:"); 253 System.out.println(""); 254 doListPermissions(groupList, groups, labels, summary, 255 PermissionInfo.PROTECTION_DANGEROUS, 256 PermissionInfo.PROTECTION_DANGEROUS); 257 if (userOnly) { 258 System.out.println("Normal Permissions:"); 259 System.out.println(""); 260 doListPermissions(groupList, groups, labels, summary, 261 PermissionInfo.PROTECTION_NORMAL, 262 PermissionInfo.PROTECTION_NORMAL); 263 } 264 } else if (userOnly) { 265 System.out.println("Dangerous and Normal Permissions:"); 266 System.out.println(""); 267 doListPermissions(groupList, groups, labels, summary, 268 PermissionInfo.PROTECTION_NORMAL, 269 PermissionInfo.PROTECTION_DANGEROUS); 270 } else { 271 System.out.println("All Permissions:"); 272 System.out.println(""); 273 doListPermissions(groupList, groups, labels, summary, 274 -10000, 10000); 275 } 276 } catch (RemoteException e) { 277 } 278 } 279 280 private void doListPermissions(ArrayList<String> groupList, 281 boolean groups, boolean labels, boolean summary, 282 int startProtectionLevel, int endProtectionLevel) 283 throws RemoteException { 284 for (int i=0; i<groupList.size(); i++) { 285 String groupName = groupList.get(i); 286 String prefix = ""; 287 if (groups) { 288 if (i > 0) System.out.println(""); 289 if (groupName != null) { 290 PermissionGroupInfo pgi = mPm.getPermissionGroupInfo( 291 groupName, 0); 292 if (summary) { 293 Resources res = getResources(pgi); 294 if (res != null) { 295 System.out.print(loadText(pgi, pgi.labelRes, 296 pgi.nonLocalizedLabel) + ": "); 297 } else { 298 System.out.print(pgi.name + ": "); 299 300 } 301 } else { 302 System.out.println((labels ? "+ " : "") 303 + "group:" + pgi.name); 304 if (labels) { 305 System.out.println(" package:" + pgi.packageName); 306 Resources res = getResources(pgi); 307 if (res != null) { 308 System.out.println(" label:" 309 + loadText(pgi, pgi.labelRes, 310 pgi.nonLocalizedLabel)); 311 System.out.println(" description:" 312 + loadText(pgi, pgi.descriptionRes, 313 pgi.nonLocalizedDescription)); 314 } 315 } 316 } 317 } else { 318 System.out.println(((labels && !summary) 319 ? "+ " : "") + "ungrouped:"); 320 } 321 prefix = " "; 322 } 323 List<PermissionInfo> ps = mPm.queryPermissionsByGroup( 324 groupList.get(i), 0); 325 int count = ps.size(); 326 boolean first = true; 327 for (int p = 0 ; p < count ; p++) { 328 PermissionInfo pi = ps.get(p); 329 if (groups && groupName == null && pi.group != null) { 330 continue; 331 } 332 if (pi.protectionLevel < startProtectionLevel 333 || pi.protectionLevel > endProtectionLevel) { 334 continue; 335 } 336 if (summary) { 337 if (first) { 338 first = false; 339 } else { 340 System.out.print(", "); 341 } 342 Resources res = getResources(pi); 343 if (res != null) { 344 System.out.print(loadText(pi, pi.labelRes, 345 pi.nonLocalizedLabel)); 346 } else { 347 System.out.print(pi.name); 348 } 349 } else { 350 System.out.println(prefix + (labels ? "+ " : "") 351 + "permission:" + pi.name); 352 if (labels) { 353 System.out.println(prefix + " package:" + pi.packageName); 354 Resources res = getResources(pi); 355 if (res != null) { 356 System.out.println(prefix + " label:" 357 + loadText(pi, pi.labelRes, 358 pi.nonLocalizedLabel)); 359 System.out.println(prefix + " description:" 360 + loadText(pi, pi.descriptionRes, 361 pi.nonLocalizedDescription)); 362 } 363 String protLevel = "unknown"; 364 switch(pi.protectionLevel) { 365 case PermissionInfo.PROTECTION_DANGEROUS: 366 protLevel = "dangerous"; 367 break; 368 case PermissionInfo.PROTECTION_NORMAL: 369 protLevel = "normal"; 370 break; 371 case PermissionInfo.PROTECTION_SIGNATURE: 372 protLevel = "signature"; 373 break; 374 case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM: 375 protLevel = "signatureOrSystem"; 376 break; 377 } 378 System.out.println(prefix + " protectionLevel:" + protLevel); 379 } 380 } 381 } 382 383 if (summary) { 384 System.out.println(""); 385 } 386 } 387 } 388 389 private void runPath() { 390 String pkg = nextArg(); 391 if (pkg == null) { 392 System.err.println("Error: no package specified"); 393 showUsage(); 394 return; 395 } 396 displayPackageFilePath(pkg); 397 } 398 399 class PackageInstallObserver extends IPackageInstallObserver.Stub { 400 boolean finished; 401 int result; 402 403 public void packageInstalled(String name, int status) { 404 synchronized( this) { 405 finished = true; 406 result = status; 407 notifyAll(); 408 } 409 } 410 } 411 412 private String installFailureToString(int result) { 413 String s; 414 switch (result) { 415 case PackageManager.INSTALL_FAILED_ALREADY_EXISTS: 416 s = "INSTALL_FAILED_ALREADY_EXISTS"; 417 break; 418 case PackageManager.INSTALL_FAILED_INVALID_APK: 419 s = "INSTALL_FAILED_INVALID_APK"; 420 break; 421 case PackageManager.INSTALL_FAILED_INVALID_URI: 422 s = "INSTALL_FAILED_INVALID_URI"; 423 break; 424 case PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE: 425 s = "INSTALL_FAILED_INSUFFICIENT_STORAGE"; 426 break; 427 case PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE: 428 s = "INSTALL_FAILED_DUPLICATE_PACKAGE"; 429 break; 430 case PackageManager.INSTALL_FAILED_NO_SHARED_USER: 431 s = "INSTALL_FAILED_NO_SHARED_USER"; 432 break; 433 case PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE: 434 s = "INSTALL_FAILED_UPDATE_INCOMPATIBLE"; 435 break; 436 case PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE: 437 s = "INSTALL_FAILED_SHARED_USER_INCOMPATIBLE"; 438 break; 439 case PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY: 440 s = "INSTALL_FAILED_MISSING_SHARED_LIBRARY"; 441 break; 442 case PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE: 443 s = "INSTALL_FAILED_REPLACE_COULDNT_DELETE"; 444 break; 445 case PackageManager.INSTALL_PARSE_FAILED_NOT_APK: 446 s = "INSTALL_PARSE_FAILED_NOT_APK"; 447 break; 448 case PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST: 449 s = "INSTALL_PARSE_FAILED_BAD_MANIFEST"; 450 break; 451 case PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION: 452 s = "INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION"; 453 break; 454 case PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES: 455 s = "INSTALL_PARSE_FAILED_NO_CERTIFICATES"; 456 break; 457 case PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES: 458 s = "INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES"; 459 break; 460 case PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING: 461 s = "INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING"; 462 break; 463 case PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME: 464 s = "INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME"; 465 break; 466 case PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID: 467 s = "INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID"; 468 break; 469 case PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: 470 s = "INSTALL_PARSE_FAILED_MANIFEST_MALFORMED"; 471 break; 472 case PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY: 473 s = "INSTALL_PARSE_FAILED_MANIFEST_EMPTY"; 474 break; 475 default: 476 s = Integer.toString(result); 477 break; 478 } 479 return s; 480 } 481 482 private void runInstall() { 483 int installFlags = 0; 484 485 String opt; 486 while ((opt=nextOption()) != null) { 487 if (opt.equals("-l")) { 488 installFlags |= PackageManager.FORWARD_LOCK_PACKAGE; 489 } else if (opt.equals("-r")) { 490 installFlags |= PackageManager.REPLACE_EXISTING_PACKAGE; 491 } else { 492 System.err.println("Error: Unknown option: " + opt); 493 showUsage(); 494 return; 495 } 496 } 497 498 String apkFilePath = nextArg(); 499 System.err.println("\tpkg: " + apkFilePath); 500 if (apkFilePath == null) { 501 System.err.println("Error: no package specified"); 502 showUsage(); 503 return; 504 } 505 506 PackageInstallObserver obs = new PackageInstallObserver(); 507 try { 508 mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags); 509 510 synchronized (obs) { 511 while (!obs.finished) { 512 try { 513 obs.wait(); 514 } catch (InterruptedException e) { 515 } 516 } 517 if (obs.result == PackageManager.INSTALL_SUCCEEDED) { 518 System.out.println("Success"); 519 } else { 520 System.err.println("Failure [" 521 + installFailureToString(obs.result) 522 + "]"); 523 } 524 } 525 } catch (RemoteException e) { 526 } 527 } 528 529 class PackageDeleteObserver extends IPackageDeleteObserver.Stub { 530 boolean finished; 531 boolean result; 532 533 public void packageDeleted(boolean succeeded) { 534 synchronized (this) { 535 finished = true; 536 result = succeeded; 537 notifyAll(); 538 } 539 } 540 } 541 542 private void runUninstall() { 543 int unInstallFlags = 0; 544 545 String opt = nextOption(); 546 if (opt != null && opt.equals("-k")) { 547 unInstallFlags = PackageManager.DONT_DELETE_DATA; 548 } 549 550 String pkg = nextArg(); 551 if (pkg == null) { 552 System.err.println("Error: no package specified"); 553 showUsage(); 554 return; 555 } 556 boolean result = deletePackage(pkg, unInstallFlags); 557 if (result) { 558 System.out.println("Success"); 559 } else { 560 System.out.println("Failure"); 561 } 562 } 563 564 private boolean deletePackage(String pkg, int unInstallFlags) { 565 PackageDeleteObserver obs = new PackageDeleteObserver(); 566 try { 567 mPm.deletePackage(pkg, obs, unInstallFlags); 568 569 synchronized (obs) { 570 while (!obs.finished) { 571 try { 572 obs.wait(); 573 } catch (InterruptedException e) { 574 } 575 } 576 } 577 } catch (RemoteException e) { 578 } 579 return obs.result; 580 } 581 582 /** 583 * Displays the package file for a package. 584 * @param pckg 585 */ 586 private void displayPackageFilePath(String pckg) { 587 try { 588 PackageInfo info = mPm.getPackageInfo(pckg, 0); 589 if (info != null && info.applicationInfo != null) { 590 System.out.print("package:"); 591 System.out.println(info.applicationInfo.sourceDir); 592 } 593 } catch (RemoteException e) { 594 } 595 } 596 597 private Resources getResources(PackageItemInfo pii) { 598 Resources res = mResourceCache.get(pii.packageName); 599 if (res != null) return res; 600 601 try { 602 ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0); 603 AssetManager am = new AssetManager(); 604 am.addAssetPath(ai.publicSourceDir); 605 res = new Resources(am, null, null); 606 mResourceCache.put(pii.packageName, res); 607 return res; 608 } catch (RemoteException e) { 609 System.err.println("Package manager gone!"); 610 return null; 611 } 612 } 613 614 private String nextOption() { 615 if (mNextArg >= mArgs.length) { 616 return null; 617 } 618 String arg = mArgs[mNextArg]; 619 if (!arg.startsWith("-")) { 620 return null; 621 } 622 mNextArg++; 623 if (arg.equals("--")) { 624 return null; 625 } 626 if (arg.length() > 1 && arg.charAt(1) != '-') { 627 if (arg.length() > 2) { 628 mCurArgData = arg.substring(2); 629 return arg.substring(0, 2); 630 } else { 631 mCurArgData = null; 632 return arg; 633 } 634 } 635 mCurArgData = null; 636 return arg; 637 } 638 639 private String nextOptionData() { 640 if (mCurArgData != null) { 641 return mCurArgData; 642 } 643 if (mNextArg >= mArgs.length) { 644 return null; 645 } 646 String data = mArgs[mNextArg]; 647 mNextArg++; 648 return data; 649 } 650 651 private String nextArg() { 652 if (mNextArg >= mArgs.length) { 653 return null; 654 } 655 String arg = mArgs[mNextArg]; 656 mNextArg++; 657 return arg; 658 } 659 660 private static void showUsage() { 661 System.err.println("usage: pm [list|path|install|uninstall]"); 662 System.err.println(" pm list packages [-f]"); 663 System.err.println(" pm list permission-groups"); 664 System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]"); 665 System.err.println(" pm path PACKAGE"); 666 System.err.println(" pm install [-l] [-r] PATH"); 667 System.err.println(" pm uninstall [-k] PACKAGE"); 668 System.err.println(""); 669 System.err.println("The list packages command prints all packages. Use"); 670 System.err.println("the -f option to see their associated file."); 671 System.err.println(""); 672 System.err.println("The list permission-groups command prints all known"); 673 System.err.println("permission groups."); 674 System.err.println(""); 675 System.err.println("The list permissions command prints all known"); 676 System.err.println("permissions, optionally only those in GROUP. Use"); 677 System.err.println("the -g option to organize by group. Use"); 678 System.err.println("the -f option to print all information. Use"); 679 System.err.println("the -s option for a short summary. Use"); 680 System.err.println("the -d option to only list dangerous permissions. Use"); 681 System.err.println("the -u option to list only the permissions users will see."); 682 System.err.println(""); 683 System.err.println("The path command prints the path to the .apk of a package."); 684 System.err.println(""); 685 System.err.println("The install command installs a package to the system. Use"); 686 System.err.println("the -l option to install the package with FORWARD_LOCK. Use"); 687 System.err.println("the -r option to reinstall an exisiting app, keeping its data."); 688 System.err.println(""); 689 System.err.println("The uninstall command removes a package from the system. Use"); 690 System.err.println("the -k option to keep the data and cache directories around"); 691 System.err.println("after the package removal."); 692 } 693} 694