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