Created
September 8, 2015 10:08
-
-
Save qzchenwl/6d17db6c9e7dbbe65f47 to your computer and use it in GitHub Desktop.
frameworks/base/cmds/pm/src/com/android/commands/pm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2007 The Android Open Source Project | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package com.android.commands.pm; | |
import com.android.internal.content.PackageHelper; | |
import android.app.ActivityManagerNative; | |
import android.content.ComponentName; | |
import android.content.Intent; | |
import android.content.pm.ResolveInfo; | |
import android.content.pm.ApplicationInfo; | |
import android.content.pm.ContainerEncryptionParams; | |
import android.content.pm.FeatureInfo; | |
import android.content.pm.IPackageDataObserver; | |
import android.content.pm.IPackageDeleteObserver; | |
import android.content.pm.IPackageInstallObserver; | |
import android.content.pm.IPackageManager; | |
import android.content.pm.InstrumentationInfo; | |
import android.content.pm.PackageInfo; | |
import android.content.pm.PackageItemInfo; | |
import android.content.pm.PackageManager; | |
import android.content.pm.ParceledListSlice; | |
import android.content.pm.PermissionGroupInfo; | |
import android.content.pm.PermissionInfo; | |
import android.content.pm.UserInfo; | |
import android.content.pm.VerificationParams; | |
import android.content.res.AssetManager; | |
import android.content.res.Resources; | |
import android.net.Uri; | |
import android.os.IUserManager; | |
import android.os.RemoteException; | |
import android.os.ServiceManager; | |
import android.os.UserHandle; | |
import android.os.UserManager; | |
import java.io.File; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Modifier; | |
import java.security.InvalidAlgorithmParameterException; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.Comparator; | |
import java.util.List; | |
import java.util.WeakHashMap; | |
import javax.crypto.SecretKey; | |
import javax.crypto.spec.IvParameterSpec; | |
import javax.crypto.spec.SecretKeySpec; | |
public final class Pm { | |
IPackageManager mPm; | |
IUserManager mUm; | |
private WeakHashMap<String, Resources> mResourceCache | |
= new WeakHashMap<String, Resources>(); | |
private String[] mArgs; | |
private int mNextArg; | |
private String mCurArgData; | |
private static final String PM_NOT_RUNNING_ERR = | |
"Error: Could not access the Package Manager. Is the system running?"; | |
public static void main(String[] args) { | |
new Pm().run(args); | |
} | |
public void run(String[] args) { | |
boolean validCommand = false; | |
if (args.length < 1) { | |
showUsage(); | |
return; | |
} | |
mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user")); | |
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); | |
if (mPm == null) { | |
System.err.println(PM_NOT_RUNNING_ERR); | |
return; | |
} | |
mArgs = args; | |
String op = args[0]; | |
mNextArg = 1; | |
if ("list".equals(op)) { | |
runList(); | |
return; | |
} | |
if ("path".equals(op)) { | |
runPath(); | |
return; | |
} | |
if ("version-code".equals(op)) { | |
runVersionCode(); | |
return; | |
} | |
if ("launch-activity".equals(op)) { | |
runLaunchActivity(); | |
return; | |
} | |
if ("install".equals(op)) { | |
runInstall(); | |
return; | |
} | |
if ("uninstall".equals(op)) { | |
runUninstall(); | |
return; | |
} | |
if ("clear".equals(op)) { | |
runClear(); | |
return; | |
} | |
if ("enable".equals(op)) { | |
runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED); | |
return; | |
} | |
if ("disable".equals(op)) { | |
runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); | |
return; | |
} | |
if ("disable-user".equals(op)) { | |
runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER); | |
return; | |
} | |
if ("grant".equals(op)) { | |
runGrantRevokePermission(true); | |
return; | |
} | |
if ("revoke".equals(op)) { | |
runGrantRevokePermission(false); | |
return; | |
} | |
if ("set-permission-enforced".equals(op)) { | |
runSetPermissionEnforced(); | |
return; | |
} | |
if ("set-install-location".equals(op)) { | |
runSetInstallLocation(); | |
return; | |
} | |
if ("get-install-location".equals(op)) { | |
runGetInstallLocation(); | |
return; | |
} | |
if ("trim-caches".equals(op)) { | |
runTrimCaches(); | |
return; | |
} | |
if ("create-user".equals(op)) { | |
runCreateUser(); | |
return; | |
} | |
if ("remove-user".equals(op)) { | |
runRemoveUser(); | |
return; | |
} | |
if ("get-max-users".equals(op)) { | |
runGetMaxUsers(); | |
return; | |
} | |
try { | |
if (args.length == 1) { | |
if (args[0].equalsIgnoreCase("-l")) { | |
validCommand = true; | |
runListPackages(false); | |
} else if (args[0].equalsIgnoreCase("-lf")){ | |
validCommand = true; | |
runListPackages(true); | |
} | |
} else if (args.length == 2) { | |
if (args[0].equalsIgnoreCase("-p")) { | |
validCommand = true; | |
displayPackageFilePath(args[1]); | |
} | |
} | |
} finally { | |
if (validCommand == false) { | |
if (op != null) { | |
System.err.println("Error: unknown command '" + op + "'"); | |
} | |
showUsage(); | |
} | |
} | |
} | |
/** | |
* Execute the list sub-command. | |
* | |
* pm list [package | packages] | |
* pm list permission-groups | |
* pm list permissions | |
* pm list features | |
* pm list libraries | |
* pm list instrumentation | |
*/ | |
private void runList() { | |
String type = nextArg(); | |
if (type == null) { | |
System.err.println("Error: didn't specify type of data to list"); | |
return; | |
} | |
if ("package".equals(type) || "packages".equals(type)) { | |
runListPackages(false); | |
} else if ("permission-groups".equals(type)) { | |
runListPermissionGroups(); | |
} else if ("permissions".equals(type)) { | |
runListPermissions(); | |
} else if ("features".equals(type)) { | |
runListFeatures(); | |
} else if ("libraries".equals(type)) { | |
runListLibraries(); | |
} else if ("instrumentation".equals(type)) { | |
runListInstrumentation(); | |
} else if ("users".equals(type)) { | |
runListUsers(); | |
} else { | |
System.err.println("Error: unknown list type '" + type + "'"); | |
} | |
} | |
/** | |
* Lists all the installed packages. | |
*/ | |
private void runListPackages(boolean showApplicationPackage) { | |
int getFlags = 0; | |
boolean listDisabled = false, listEnabled = false; | |
boolean listSystem = false, listThirdParty = false; | |
boolean listInstaller = false; | |
int userId = UserHandle.USER_OWNER; | |
try { | |
String opt; | |
while ((opt=nextOption()) != null) { | |
if (opt.equals("-l")) { | |
// old compat | |
} else if (opt.equals("-lf")) { | |
showApplicationPackage = true; | |
} else if (opt.equals("-f")) { | |
showApplicationPackage = true; | |
} else if (opt.equals("-d")) { | |
listDisabled = true; | |
} else if (opt.equals("-e")) { | |
listEnabled = true; | |
} else if (opt.equals("-s")) { | |
listSystem = true; | |
} else if (opt.equals("-3")) { | |
listThirdParty = true; | |
} else if (opt.equals("-i")) { | |
listInstaller = true; | |
} else if (opt.equals("--user")) { | |
userId = Integer.parseInt(nextArg()); | |
} else if (opt.equals("-u")) { | |
getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES; | |
} else { | |
System.err.println("Error: Unknown option: " + opt); | |
return; | |
} | |
} | |
} catch (RuntimeException ex) { | |
System.err.println("Error: " + ex.toString()); | |
return; | |
} | |
String filter = nextArg(); | |
try { | |
final List<PackageInfo> packages = getInstalledPackages(mPm, getFlags, userId); | |
int count = packages.size(); | |
for (int p = 0 ; p < count ; p++) { | |
PackageInfo info = packages.get(p); | |
if (filter != null && !info.packageName.contains(filter)) { | |
continue; | |
} | |
final boolean isSystem = | |
(info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0; | |
if ((!listDisabled || !info.applicationInfo.enabled) && | |
(!listEnabled || info.applicationInfo.enabled) && | |
(!listSystem || isSystem) && | |
(!listThirdParty || !isSystem)) { | |
System.out.print("package:"); | |
if (showApplicationPackage) { | |
System.out.print(info.applicationInfo.sourceDir); | |
System.out.print("="); | |
} | |
System.out.print(info.packageName); | |
if (listInstaller) { | |
System.out.print(" installer="); | |
System.out.print(mPm.getInstallerPackageName(info.packageName)); | |
} | |
System.out.println(); | |
} | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
@SuppressWarnings("unchecked") | |
private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags, int userId) | |
throws RemoteException { | |
final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>(); | |
PackageInfo lastItem = null; | |
ParceledListSlice<PackageInfo> slice; | |
do { | |
final String lastKey = lastItem != null ? lastItem.packageName : null; | |
slice = pm.getInstalledPackages(flags, lastKey, userId); | |
lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR); | |
} while (!slice.isLastSlice()); | |
return packageInfos; | |
} | |
/** | |
* Lists all of the features supported by the current device. | |
* | |
* pm list features | |
*/ | |
private void runListFeatures() { | |
try { | |
List<FeatureInfo> list = new ArrayList<FeatureInfo>(); | |
FeatureInfo[] rawList = mPm.getSystemAvailableFeatures(); | |
for (int i=0; i<rawList.length; i++) { | |
list.add(rawList[i]); | |
} | |
// Sort by name | |
Collections.sort(list, new Comparator<FeatureInfo>() { | |
public int compare(FeatureInfo o1, FeatureInfo o2) { | |
if (o1.name == o2.name) return 0; | |
if (o1.name == null) return -1; | |
if (o2.name == null) return 1; | |
return o1.name.compareTo(o2.name); | |
} | |
}); | |
int count = (list != null) ? list.size() : 0; | |
for (int p = 0; p < count; p++) { | |
FeatureInfo fi = list.get(p); | |
System.out.print("feature:"); | |
if (fi.name != null) System.out.println(fi.name); | |
else System.out.println("reqGlEsVersion=0x" | |
+ Integer.toHexString(fi.reqGlEsVersion)); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
/** | |
* Lists all of the libraries supported by the current device. | |
* | |
* pm list libraries | |
*/ | |
private void runListLibraries() { | |
try { | |
List<String> list = new ArrayList<String>(); | |
String[] rawList = mPm.getSystemSharedLibraryNames(); | |
for (int i=0; i<rawList.length; i++) { | |
list.add(rawList[i]); | |
} | |
// Sort by name | |
Collections.sort(list, new Comparator<String>() { | |
public int compare(String o1, String o2) { | |
if (o1 == o2) return 0; | |
if (o1 == null) return -1; | |
if (o2 == null) return 1; | |
return o1.compareTo(o2); | |
} | |
}); | |
int count = (list != null) ? list.size() : 0; | |
for (int p = 0; p < count; p++) { | |
String lib = list.get(p); | |
System.out.print("library:"); | |
System.out.println(lib); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
/** | |
* Lists all of the installed instrumentation, or all for a given package | |
* | |
* pm list instrumentation [package] [-f] | |
*/ | |
private void runListInstrumentation() { | |
int flags = 0; // flags != 0 is only used to request meta-data | |
boolean showPackage = false; | |
String targetPackage = null; | |
try { | |
String opt; | |
while ((opt=nextArg()) != null) { | |
if (opt.equals("-f")) { | |
showPackage = true; | |
} else if (opt.charAt(0) != '-') { | |
targetPackage = opt; | |
} else { | |
System.err.println("Error: Unknown option: " + opt); | |
return; | |
} | |
} | |
} catch (RuntimeException ex) { | |
System.err.println("Error: " + ex.toString()); | |
return; | |
} | |
try { | |
List<InstrumentationInfo> list = mPm.queryInstrumentation(targetPackage, flags); | |
// Sort by target package | |
Collections.sort(list, new Comparator<InstrumentationInfo>() { | |
public int compare(InstrumentationInfo o1, InstrumentationInfo o2) { | |
return o1.targetPackage.compareTo(o2.targetPackage); | |
} | |
}); | |
int count = (list != null) ? list.size() : 0; | |
for (int p = 0; p < count; p++) { | |
InstrumentationInfo ii = list.get(p); | |
System.out.print("instrumentation:"); | |
if (showPackage) { | |
System.out.print(ii.sourceDir); | |
System.out.print("="); | |
} | |
ComponentName cn = new ComponentName(ii.packageName, ii.name); | |
System.out.print(cn.flattenToShortString()); | |
System.out.print(" (target="); | |
System.out.print(ii.targetPackage); | |
System.out.println(")"); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
/** | |
* Lists all the known permission groups. | |
*/ | |
private void runListPermissionGroups() { | |
try { | |
List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0); | |
int count = pgs.size(); | |
for (int p = 0 ; p < count ; p++) { | |
PermissionGroupInfo pgi = pgs.get(p); | |
System.out.print("permission group:"); | |
System.out.println(pgi.name); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) { | |
if (nonLocalized != null) { | |
return nonLocalized.toString(); | |
} | |
if (res != 0) { | |
Resources r = getResources(pii); | |
if (r != null) { | |
return r.getString(res); | |
} | |
} | |
return null; | |
} | |
/** | |
* Lists all the permissions in a group. | |
*/ | |
private void runListPermissions() { | |
try { | |
boolean labels = false; | |
boolean groups = false; | |
boolean userOnly = false; | |
boolean summary = false; | |
boolean dangerousOnly = false; | |
String opt; | |
while ((opt=nextOption()) != null) { | |
if (opt.equals("-f")) { | |
labels = true; | |
} else if (opt.equals("-g")) { | |
groups = true; | |
} else if (opt.equals("-s")) { | |
groups = true; | |
labels = true; | |
summary = true; | |
} else if (opt.equals("-u")) { | |
userOnly = true; | |
} else if (opt.equals("-d")) { | |
dangerousOnly = true; | |
} else { | |
System.err.println("Error: Unknown option: " + opt); | |
return; | |
} | |
} | |
String grp = nextOption(); | |
ArrayList<String> groupList = new ArrayList<String>(); | |
if (groups) { | |
List<PermissionGroupInfo> infos = | |
mPm.getAllPermissionGroups(0); | |
for (int i=0; i<infos.size(); i++) { | |
groupList.add(infos.get(i).name); | |
} | |
groupList.add(null); | |
} else { | |
groupList.add(grp); | |
} | |
if (dangerousOnly) { | |
System.out.println("Dangerous Permissions:"); | |
System.out.println(""); | |
doListPermissions(groupList, groups, labels, summary, | |
PermissionInfo.PROTECTION_DANGEROUS, | |
PermissionInfo.PROTECTION_DANGEROUS); | |
if (userOnly) { | |
System.out.println("Normal Permissions:"); | |
System.out.println(""); | |
doListPermissions(groupList, groups, labels, summary, | |
PermissionInfo.PROTECTION_NORMAL, | |
PermissionInfo.PROTECTION_NORMAL); | |
} | |
} else if (userOnly) { | |
System.out.println("Dangerous and Normal Permissions:"); | |
System.out.println(""); | |
doListPermissions(groupList, groups, labels, summary, | |
PermissionInfo.PROTECTION_NORMAL, | |
PermissionInfo.PROTECTION_DANGEROUS); | |
} else { | |
System.out.println("All Permissions:"); | |
System.out.println(""); | |
doListPermissions(groupList, groups, labels, summary, | |
-10000, 10000); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
private void doListPermissions(ArrayList<String> groupList, | |
boolean groups, boolean labels, boolean summary, | |
int startProtectionLevel, int endProtectionLevel) | |
throws RemoteException { | |
for (int i=0; i<groupList.size(); i++) { | |
String groupName = groupList.get(i); | |
String prefix = ""; | |
if (groups) { | |
if (i > 0) System.out.println(""); | |
if (groupName != null) { | |
PermissionGroupInfo pgi = mPm.getPermissionGroupInfo( | |
groupName, 0); | |
if (summary) { | |
Resources res = getResources(pgi); | |
if (res != null) { | |
System.out.print(loadText(pgi, pgi.labelRes, | |
pgi.nonLocalizedLabel) + ": "); | |
} else { | |
System.out.print(pgi.name + ": "); | |
} | |
} else { | |
System.out.println((labels ? "+ " : "") | |
+ "group:" + pgi.name); | |
if (labels) { | |
System.out.println(" package:" + pgi.packageName); | |
Resources res = getResources(pgi); | |
if (res != null) { | |
System.out.println(" label:" | |
+ loadText(pgi, pgi.labelRes, | |
pgi.nonLocalizedLabel)); | |
System.out.println(" description:" | |
+ loadText(pgi, pgi.descriptionRes, | |
pgi.nonLocalizedDescription)); | |
} | |
} | |
} | |
} else { | |
System.out.println(((labels && !summary) | |
? "+ " : "") + "ungrouped:"); | |
} | |
prefix = " "; | |
} | |
List<PermissionInfo> ps = mPm.queryPermissionsByGroup( | |
groupList.get(i), 0); | |
int count = ps.size(); | |
boolean first = true; | |
for (int p = 0 ; p < count ; p++) { | |
PermissionInfo pi = ps.get(p); | |
if (groups && groupName == null && pi.group != null) { | |
continue; | |
} | |
final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; | |
if (base < startProtectionLevel | |
|| base > endProtectionLevel) { | |
continue; | |
} | |
if (summary) { | |
if (first) { | |
first = false; | |
} else { | |
System.out.print(", "); | |
} | |
Resources res = getResources(pi); | |
if (res != null) { | |
System.out.print(loadText(pi, pi.labelRes, | |
pi.nonLocalizedLabel)); | |
} else { | |
System.out.print(pi.name); | |
} | |
} else { | |
System.out.println(prefix + (labels ? "+ " : "") | |
+ "permission:" + pi.name); | |
if (labels) { | |
System.out.println(prefix + " package:" + pi.packageName); | |
Resources res = getResources(pi); | |
if (res != null) { | |
System.out.println(prefix + " label:" | |
+ loadText(pi, pi.labelRes, | |
pi.nonLocalizedLabel)); | |
System.out.println(prefix + " description:" | |
+ loadText(pi, pi.descriptionRes, | |
pi.nonLocalizedDescription)); | |
} | |
System.out.println(prefix + " protectionLevel:" | |
+ PermissionInfo.protectionToString(pi.protectionLevel)); | |
} | |
} | |
} | |
if (summary) { | |
System.out.println(""); | |
} | |
} | |
} | |
private void runPath() { | |
String pkg = nextArg(); | |
if (pkg == null) { | |
System.err.println("Error: no package specified"); | |
return; | |
} | |
displayPackageFilePath(pkg); | |
} | |
private void runVersionCode() { | |
String pkg = nextArg(); | |
if (pkg == null) { | |
System.err.println("Error: no package specified"); | |
return; | |
} | |
displayPackageVersionCode(pkg); | |
} | |
private void runLaunchActivity() { | |
String pkg = nextArg(); | |
if (pkg == null) { | |
System.err.println("Error: no package specified"); | |
return; | |
} | |
displayPackageLaunchActivity(pkg); | |
} | |
class PackageInstallObserver extends IPackageInstallObserver.Stub { | |
boolean finished; | |
int result; | |
public void packageInstalled(String name, int status) { | |
synchronized( this) { | |
finished = true; | |
result = status; | |
notifyAll(); | |
} | |
} | |
} | |
/** | |
* Converts a failure code into a string by using reflection to find a matching constant | |
* in PackageManager. | |
*/ | |
private String installFailureToString(int result) { | |
Field[] fields = PackageManager.class.getFields(); | |
for (Field f: fields) { | |
if (f.getType() == int.class) { | |
int modifiers = f.getModifiers(); | |
// only look at public final static fields. | |
if (((modifiers & Modifier.FINAL) != 0) && | |
((modifiers & Modifier.PUBLIC) != 0) && | |
((modifiers & Modifier.STATIC) != 0)) { | |
String fieldName = f.getName(); | |
if (fieldName.startsWith("INSTALL_FAILED_") || | |
fieldName.startsWith("INSTALL_PARSE_FAILED_")) { | |
// get the int value and compare it to result. | |
try { | |
if (result == f.getInt(null)) { | |
return fieldName; | |
} | |
} catch (IllegalAccessException e) { | |
// this shouldn't happen since we only look for public static fields. | |
} | |
} | |
} | |
} | |
} | |
// couldn't find a matching constant? return the value | |
return Integer.toString(result); | |
} | |
private void runSetInstallLocation() { | |
int loc; | |
String arg = nextArg(); | |
if (arg == null) { | |
System.err.println("Error: no install location specified."); | |
return; | |
} | |
try { | |
loc = Integer.parseInt(arg); | |
} catch (NumberFormatException e) { | |
System.err.println("Error: install location has to be a number."); | |
return; | |
} | |
try { | |
if (!mPm.setInstallLocation(loc)) { | |
System.err.println("Error: install location has to be a number."); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
private void runGetInstallLocation() { | |
try { | |
int loc = mPm.getInstallLocation(); | |
String locStr = "invalid"; | |
if (loc == PackageHelper.APP_INSTALL_AUTO) { | |
locStr = "auto"; | |
} else if (loc == PackageHelper.APP_INSTALL_INTERNAL) { | |
locStr = "internal"; | |
} else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) { | |
locStr = "external"; | |
} | |
System.out.println(loc + "[" + locStr + "]"); | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
private void runInstall() { | |
int installFlags = PackageManager.INSTALL_ALL_USERS; | |
String installerPackageName = null; | |
String opt; | |
String algo = null; | |
byte[] iv = null; | |
byte[] key = null; | |
String macAlgo = null; | |
byte[] macKey = null; | |
byte[] tag = null; | |
String originatingUriString = null; | |
String referrer = null; | |
while ((opt=nextOption()) != null) { | |
if (opt.equals("-l")) { | |
installFlags |= PackageManager.INSTALL_FORWARD_LOCK; | |
} else if (opt.equals("-r")) { | |
installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; | |
} else if (opt.equals("-i")) { | |
installerPackageName = nextOptionData(); | |
if (installerPackageName == null) { | |
System.err.println("Error: no value specified for -i"); | |
return; | |
} | |
} else if (opt.equals("-t")) { | |
installFlags |= PackageManager.INSTALL_ALLOW_TEST; | |
} else if (opt.equals("-s")) { | |
// Override if -s option is specified. | |
installFlags |= PackageManager.INSTALL_EXTERNAL; | |
} else if (opt.equals("-f")) { | |
// Override if -s option is specified. | |
installFlags |= PackageManager.INSTALL_INTERNAL; | |
} else if (opt.equals("-d")) { | |
installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; | |
} else if (opt.equals("--algo")) { | |
algo = nextOptionData(); | |
if (algo == null) { | |
System.err.println("Error: must supply argument for --algo"); | |
return; | |
} | |
} else if (opt.equals("--iv")) { | |
iv = hexToBytes(nextOptionData()); | |
if (iv == null) { | |
System.err.println("Error: must supply argument for --iv"); | |
return; | |
} | |
} else if (opt.equals("--key")) { | |
key = hexToBytes(nextOptionData()); | |
if (key == null) { | |
System.err.println("Error: must supply argument for --key"); | |
return; | |
} | |
} else if (opt.equals("--macalgo")) { | |
macAlgo = nextOptionData(); | |
if (macAlgo == null) { | |
System.err.println("Error: must supply argument for --macalgo"); | |
return; | |
} | |
} else if (opt.equals("--mackey")) { | |
macKey = hexToBytes(nextOptionData()); | |
if (macKey == null) { | |
System.err.println("Error: must supply argument for --mackey"); | |
return; | |
} | |
} else if (opt.equals("--tag")) { | |
tag = hexToBytes(nextOptionData()); | |
if (tag == null) { | |
System.err.println("Error: must supply argument for --tag"); | |
return; | |
} | |
} else if (opt.equals("--originating-uri")) { | |
originatingUriString = nextOptionData(); | |
if (originatingUriString == null) { | |
System.err.println("Error: must supply argument for --originating-uri"); | |
return; | |
} | |
} else if (opt.equals("--referrer")) { | |
referrer = nextOptionData(); | |
if (referrer == null) { | |
System.err.println("Error: must supply argument for --referrer"); | |
return; | |
} | |
} else { | |
System.err.println("Error: Unknown option: " + opt); | |
return; | |
} | |
} | |
final ContainerEncryptionParams encryptionParams; | |
if (algo != null || iv != null || key != null || macAlgo != null || macKey != null | |
|| tag != null) { | |
if (algo == null || iv == null || key == null) { | |
System.err.println("Error: all of --algo, --iv, and --key must be specified"); | |
return; | |
} | |
if (macAlgo != null || macKey != null || tag != null) { | |
if (macAlgo == null || macKey == null || tag == null) { | |
System.err.println("Error: all of --macalgo, --mackey, and --tag must " | |
+ "be specified"); | |
return; | |
} | |
} | |
try { | |
final SecretKey encKey = new SecretKeySpec(key, "RAW"); | |
final SecretKey macSecretKey; | |
if (macKey == null || macKey.length == 0) { | |
macSecretKey = null; | |
} else { | |
macSecretKey = new SecretKeySpec(macKey, "RAW"); | |
} | |
encryptionParams = new ContainerEncryptionParams(algo, new IvParameterSpec(iv), | |
encKey, macAlgo, null, macSecretKey, tag, -1, -1, -1); | |
} catch (InvalidAlgorithmParameterException e) { | |
e.printStackTrace(); | |
return; | |
} | |
} else { | |
encryptionParams = null; | |
} | |
final Uri apkURI; | |
final Uri verificationURI; | |
final Uri originatingURI; | |
final Uri referrerURI; | |
if (originatingUriString != null) { | |
originatingURI = Uri.parse(originatingUriString); | |
} else { | |
originatingURI = null; | |
} | |
if (referrer != null) { | |
referrerURI = Uri.parse(referrer); | |
} else { | |
referrerURI = null; | |
} | |
// Populate apkURI, must be present | |
final String apkFilePath = nextArg(); | |
System.err.println("\tpkg: " + apkFilePath); | |
if (apkFilePath != null) { | |
apkURI = Uri.fromFile(new File(apkFilePath)); | |
} else { | |
System.err.println("Error: no package specified"); | |
return; | |
} | |
// Populate verificationURI, optionally present | |
final String verificationFilePath = nextArg(); | |
if (verificationFilePath != null) { | |
System.err.println("\tver: " + verificationFilePath); | |
verificationURI = Uri.fromFile(new File(verificationFilePath)); | |
} else { | |
verificationURI = null; | |
} | |
PackageInstallObserver obs = new PackageInstallObserver(); | |
try { | |
VerificationParams verificationParams = new VerificationParams(verificationURI, | |
originatingURI, referrerURI, VerificationParams.NO_UID, null); | |
mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags, | |
installerPackageName, verificationParams, encryptionParams); | |
synchronized (obs) { | |
while (!obs.finished) { | |
try { | |
obs.wait(); | |
} catch (InterruptedException e) { | |
} | |
} | |
if (obs.result == PackageManager.INSTALL_SUCCEEDED) { | |
System.out.println("Success"); | |
} else { | |
System.err.println("Failure [" | |
+ installFailureToString(obs.result) | |
+ "]"); | |
} | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
/** | |
* Convert a string containing hex-encoded bytes to a byte array. | |
* | |
* @param input String containing hex-encoded bytes | |
* @return input as an array of bytes | |
*/ | |
private byte[] hexToBytes(String input) { | |
if (input == null) { | |
return null; | |
} | |
final int inputLength = input.length(); | |
if ((inputLength % 2) != 0) { | |
System.err.print("Invalid length; must be multiple of 2"); | |
return null; | |
} | |
final int byteLength = inputLength / 2; | |
final byte[] output = new byte[byteLength]; | |
int inputIndex = 0; | |
int byteIndex = 0; | |
while (inputIndex < inputLength) { | |
output[byteIndex++] = (byte) Integer.parseInt( | |
input.substring(inputIndex, inputIndex + 2), 16); | |
inputIndex += 2; | |
} | |
return output; | |
} | |
public void runCreateUser() { | |
String name; | |
String arg = nextArg(); | |
if (arg == null) { | |
System.err.println("Error: no user name specified."); | |
return; | |
} | |
name = arg; | |
try { | |
final UserInfo info = mUm.createUser(name, 0); | |
if (info != null) { | |
System.out.println("Success: created user id " + info.id); | |
} else { | |
System.err.println("Error: couldn't create User."); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
public void runRemoveUser() { | |
int userId; | |
String arg = nextArg(); | |
if (arg == null) { | |
System.err.println("Error: no user id specified."); | |
return; | |
} | |
try { | |
userId = Integer.parseInt(arg); | |
} catch (NumberFormatException e) { | |
System.err.println("Error: user id '" + arg + "' is not a number."); | |
return; | |
} | |
try { | |
if (mUm.removeUser(userId)) { | |
System.out.println("Success: removed user"); | |
} else { | |
System.err.println("Error: couldn't remove user id " + userId); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
public void runListUsers() { | |
try { | |
List<UserInfo> users = mUm.getUsers(false); | |
if (users == null) { | |
System.err.println("Error: couldn't get users"); | |
} else { | |
System.out.println("Users:"); | |
for (int i = 0; i < users.size(); i++) { | |
System.out.println("\t" + users.get(i).toString()); | |
} | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
public void runGetMaxUsers() { | |
System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers()); | |
} | |
class PackageDeleteObserver extends IPackageDeleteObserver.Stub { | |
boolean finished; | |
boolean result; | |
public void packageDeleted(String packageName, int returnCode) { | |
synchronized (this) { | |
finished = true; | |
result = returnCode == PackageManager.DELETE_SUCCEEDED; | |
notifyAll(); | |
} | |
} | |
} | |
private void runUninstall() { | |
int unInstallFlags = PackageManager.DELETE_ALL_USERS; | |
String opt; | |
while ((opt=nextOption()) != null) { | |
if (opt.equals("-k")) { | |
unInstallFlags |= PackageManager.DELETE_KEEP_DATA; | |
} else { | |
System.err.println("Error: Unknown option: " + opt); | |
return; | |
} | |
} | |
String pkg = nextArg(); | |
if (pkg == null) { | |
System.err.println("Error: no package specified"); | |
showUsage(); | |
return; | |
} | |
boolean result = deletePackage(pkg, unInstallFlags); | |
if (result) { | |
System.out.println("Success"); | |
} else { | |
System.out.println("Failure"); | |
} | |
} | |
private boolean deletePackage(String pkg, int unInstallFlags) { | |
PackageDeleteObserver obs = new PackageDeleteObserver(); | |
try { | |
mPm.deletePackage(pkg, obs, unInstallFlags); | |
synchronized (obs) { | |
while (!obs.finished) { | |
try { | |
obs.wait(); | |
} catch (InterruptedException e) { | |
} | |
} | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
return obs.result; | |
} | |
static class ClearDataObserver extends IPackageDataObserver.Stub { | |
boolean finished; | |
boolean result; | |
@Override | |
public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { | |
synchronized (this) { | |
finished = true; | |
result = succeeded; | |
notifyAll(); | |
} | |
} | |
} | |
private void runClear() { | |
int userId = 0; | |
String option = nextOption(); | |
if (option != null && option.equals("--user")) { | |
String optionData = nextOptionData(); | |
if (optionData == null || !isNumber(optionData)) { | |
System.err.println("Error: no USER_ID specified"); | |
showUsage(); | |
return; | |
} else { | |
userId = Integer.parseInt(optionData); | |
} | |
} | |
String pkg = nextArg(); | |
if (pkg == null) { | |
System.err.println("Error: no package specified"); | |
showUsage(); | |
return; | |
} | |
ClearDataObserver obs = new ClearDataObserver(); | |
try { | |
if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, userId)) { | |
System.err.println("Failed"); | |
} | |
synchronized (obs) { | |
while (!obs.finished) { | |
try { | |
obs.wait(); | |
} catch (InterruptedException e) { | |
} | |
} | |
} | |
if (obs.result) { | |
System.err.println("Success"); | |
} else { | |
System.err.println("Failed"); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
private static String enabledSettingToString(int state) { | |
switch (state) { | |
case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT: | |
return "default"; | |
case PackageManager.COMPONENT_ENABLED_STATE_ENABLED: | |
return "enabled"; | |
case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: | |
return "disabled"; | |
case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER: | |
return "disabled-user"; | |
} | |
return "unknown"; | |
} | |
private static boolean isNumber(String s) { | |
try { | |
Integer.parseInt(s); | |
} catch (NumberFormatException nfe) { | |
return false; | |
} | |
return true; | |
} | |
private void runSetEnabledSetting(int state) { | |
int userId = 0; | |
String option = nextOption(); | |
if (option != null && option.equals("--user")) { | |
String optionData = nextOptionData(); | |
if (optionData == null || !isNumber(optionData)) { | |
System.err.println("Error: no USER_ID specified"); | |
showUsage(); | |
return; | |
} else { | |
userId = Integer.parseInt(optionData); | |
} | |
} | |
String pkg = nextArg(); | |
if (pkg == null) { | |
System.err.println("Error: no package or component specified"); | |
showUsage(); | |
return; | |
} | |
ComponentName cn = ComponentName.unflattenFromString(pkg); | |
if (cn == null) { | |
try { | |
mPm.setApplicationEnabledSetting(pkg, state, 0, userId); | |
System.err.println("Package " + pkg + " new state: " | |
+ enabledSettingToString( | |
mPm.getApplicationEnabledSetting(pkg, userId))); | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} else { | |
try { | |
mPm.setComponentEnabledSetting(cn, state, 0, userId); | |
System.err.println("Component " + cn.toShortString() + " new state: " | |
+ enabledSettingToString( | |
mPm.getComponentEnabledSetting(cn, userId))); | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
} | |
private void runGrantRevokePermission(boolean grant) { | |
String pkg = nextArg(); | |
if (pkg == null) { | |
System.err.println("Error: no package specified"); | |
showUsage(); | |
return; | |
} | |
String perm = nextArg(); | |
if (perm == null) { | |
System.err.println("Error: no permission specified"); | |
showUsage(); | |
return; | |
} | |
try { | |
if (grant) { | |
mPm.grantPermission(pkg, perm); | |
} else { | |
mPm.revokePermission(pkg, perm); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} catch (IllegalArgumentException e) { | |
System.err.println("Bad argument: " + e.toString()); | |
showUsage(); | |
} catch (SecurityException e) { | |
System.err.println("Operation not allowed: " + e.toString()); | |
} | |
} | |
private void runSetPermissionEnforced() { | |
final String permission = nextArg(); | |
if (permission == null) { | |
System.err.println("Error: no permission specified"); | |
showUsage(); | |
return; | |
} | |
final String enforcedRaw = nextArg(); | |
if (enforcedRaw == null) { | |
System.err.println("Error: no enforcement specified"); | |
showUsage(); | |
return; | |
} | |
final boolean enforced = Boolean.parseBoolean(enforcedRaw); | |
try { | |
mPm.setPermissionEnforced(permission, enforced); | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} catch (IllegalArgumentException e) { | |
System.err.println("Bad argument: " + e.toString()); | |
showUsage(); | |
} catch (SecurityException e) { | |
System.err.println("Operation not allowed: " + e.toString()); | |
} | |
} | |
static class ClearCacheObserver extends IPackageDataObserver.Stub { | |
boolean finished; | |
boolean result; | |
@Override | |
public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { | |
synchronized (this) { | |
finished = true; | |
result = succeeded; | |
notifyAll(); | |
} | |
} | |
} | |
private void runTrimCaches() { | |
String size = nextArg(); | |
if (size == null) { | |
System.err.println("Error: no size specified"); | |
showUsage(); | |
return; | |
} | |
int len = size.length(); | |
long multiplier = 1; | |
if (len > 1) { | |
char c = size.charAt(len-1); | |
if (c == 'K' || c == 'k') { | |
multiplier = 1024L; | |
} else if (c == 'M' || c == 'm') { | |
multiplier = 1024L*1024L; | |
} else if (c == 'G' || c == 'g') { | |
multiplier = 1024L*1024L*1024L; | |
} else { | |
System.err.println("Invalid suffix: " + c); | |
showUsage(); | |
return; | |
} | |
size = size.substring(0, len-1); | |
} | |
long sizeVal; | |
try { | |
sizeVal = Long.parseLong(size) * multiplier; | |
} catch (NumberFormatException e) { | |
System.err.println("Error: expected number at: " + size); | |
showUsage(); | |
return; | |
} | |
ClearDataObserver obs = new ClearDataObserver(); | |
try { | |
mPm.freeStorageAndNotify(sizeVal, obs); | |
synchronized (obs) { | |
while (!obs.finished) { | |
try { | |
obs.wait(); | |
} catch (InterruptedException e) { | |
} | |
} | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} catch (IllegalArgumentException e) { | |
System.err.println("Bad argument: " + e.toString()); | |
showUsage(); | |
} catch (SecurityException e) { | |
System.err.println("Operation not allowed: " + e.toString()); | |
} | |
} | |
/** | |
* Displays the package file for a package. | |
* @param pckg | |
*/ | |
private void displayPackageFilePath(String pckg) { | |
try { | |
PackageInfo info = mPm.getPackageInfo(pckg, 0, 0); | |
if (info != null && info.applicationInfo != null) { | |
System.out.print("package:"); | |
System.out.println(info.applicationInfo.sourceDir); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
/** | |
* Displays the version code for a package. | |
* @param pckg | |
*/ | |
private void displayPackageVersionCode(String pckg) { | |
try { | |
PackageInfo info = mPm.getPackageInfo(pckg, 0, 0); | |
if (info != null && info.applicationInfo != null) { | |
System.out.println(info.versionCode); | |
} | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
/** | |
* Displays the luncher for a package. | |
* @param pckg | |
* e.g. com.example.org/.MainActivity | |
*/ | |
private void displayPackageLaunchActivity(String pkg) { | |
try { | |
Intent i = new Intent(Intent.ACTION_MAIN); | |
i.addCategory(Intent.CATEGORY_LAUNCHER); | |
i.setPackage(pkg); | |
List<ResolveInfo> ris = mPm.queryIntentActivities(i, null, 0, 0); | |
if (ris == null || ris.size() <= 0) { | |
System.err.println("mPm.queryIntentActivities returns null"); | |
return; | |
} | |
System.out.println(ris.get(0).activityInfo.name); | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
} | |
} | |
private Resources getResources(PackageItemInfo pii) { | |
Resources res = mResourceCache.get(pii.packageName); | |
if (res != null) return res; | |
try { | |
ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0, 0); | |
AssetManager am = new AssetManager(); | |
am.addAssetPath(ai.publicSourceDir); | |
res = new Resources(am, null, null); | |
mResourceCache.put(pii.packageName, res); | |
return res; | |
} catch (RemoteException e) { | |
System.err.println(e.toString()); | |
System.err.println(PM_NOT_RUNNING_ERR); | |
return null; | |
} | |
} | |
private String nextOption() { | |
if (mNextArg >= mArgs.length) { | |
return null; | |
} | |
String arg = mArgs[mNextArg]; | |
if (!arg.startsWith("-")) { | |
return null; | |
} | |
mNextArg++; | |
if (arg.equals("--")) { | |
return null; | |
} | |
if (arg.length() > 1 && arg.charAt(1) != '-') { | |
if (arg.length() > 2) { | |
mCurArgData = arg.substring(2); | |
return arg.substring(0, 2); | |
} else { | |
mCurArgData = null; | |
return arg; | |
} | |
} | |
mCurArgData = null; | |
return arg; | |
} | |
private String nextOptionData() { | |
if (mCurArgData != null) { | |
return mCurArgData; | |
} | |
if (mNextArg >= mArgs.length) { | |
return null; | |
} | |
String data = mArgs[mNextArg]; | |
mNextArg++; | |
return data; | |
} | |
private String nextArg() { | |
if (mNextArg >= mArgs.length) { | |
return null; | |
} | |
String arg = mArgs[mNextArg]; | |
mNextArg++; | |
return arg; | |
} | |
private static void showUsage() { | |
System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]"); | |
System.err.println(" pm list permission-groups"); | |
System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]"); | |
System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]"); | |
System.err.println(" pm list features"); | |
System.err.println(" pm list libraries"); | |
System.err.println(" pm list users"); | |
System.err.println(" pm path PACKAGE"); | |
System.err.println(" pm version-code PACKAGE"); | |
System.err.println(" pm launch-activity PACKAGE"); | |
System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]"); | |
System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]"); | |
System.err.println(" [--originating-uri <URI>] [--referrer <URI>] PATH"); | |
System.err.println(" pm uninstall [-k] PACKAGE"); | |
System.err.println(" pm clear [--user USER_ID] PACKAGE"); | |
System.err.println(" pm enable [--user USER_ID] PACKAGE_OR_COMPONENT"); | |
System.err.println(" pm disable [--user USER_ID] PACKAGE_OR_COMPONENT"); | |
System.err.println(" pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT"); | |
System.err.println(" pm grant PACKAGE PERMISSION"); | |
System.err.println(" pm revoke PACKAGE PERMISSION"); | |
System.err.println(" pm set-install-location [0/auto] [1/internal] [2/external]"); | |
System.err.println(" pm get-install-location"); | |
System.err.println(" pm set-permission-enforced PERMISSION [true|false]"); | |
System.err.println(" pm trim-caches DESIRED_FREE_SPACE"); | |
System.err.println(" pm create-user USER_NAME"); | |
System.err.println(" pm remove-user USER_ID"); | |
System.err.println(" pm get-max-users"); | |
System.err.println(""); | |
System.err.println("pm list packages: prints all packages, optionally only"); | |
System.err.println(" those whose package name contains the text in FILTER. Options:"); | |
System.err.println(" -f: see their associated file."); | |
System.err.println(" -d: filter to only show disbled packages."); | |
System.err.println(" -e: filter to only show enabled packages."); | |
System.err.println(" -s: filter to only show system packages."); | |
System.err.println(" -3: filter to only show third party packages."); | |
System.err.println(" -i: see the installer for the packages."); | |
System.err.println(" -u: also include uninstalled packages."); | |
System.err.println(""); | |
System.err.println("pm list permission-groups: prints all known permission groups."); | |
System.err.println(""); | |
System.err.println("pm list permissions: prints all known permissions, optionally only"); | |
System.err.println(" those in GROUP. Options:"); | |
System.err.println(" -g: organize by group."); | |
System.err.println(" -f: print all information."); | |
System.err.println(" -s: short summary."); | |
System.err.println(" -d: only list dangerous permissions."); | |
System.err.println(" -u: list only the permissions users will see."); | |
System.err.println(""); | |
System.err.println("pm list instrumentation: use to list all test packages; optionally"); | |
System.err.println(" supply <TARGET-PACKAGE> to list the test packages for a particular"); | |
System.err.println(" application. Options:"); | |
System.err.println(" -f: list the .apk file for the test package."); | |
System.err.println(""); | |
System.err.println("pm list features: prints all features of the system."); | |
System.err.println(""); | |
System.err.println("pm list users: prints all users on the system."); | |
System.err.println(""); | |
System.err.println("pm path: print the path to the .apk of the given PACKAGE."); | |
System.err.println(""); | |
System.err.println("pm install: installs a package to the system. Options:"); | |
System.err.println(" -l: install the package with FORWARD_LOCK."); | |
System.err.println(" -r: reinstall an exisiting app, keeping its data."); | |
System.err.println(" -t: allow test .apks to be installed."); | |
System.err.println(" -i: specify the installer package name."); | |
System.err.println(" -s: install package on sdcard."); | |
System.err.println(" -f: install package on internal flash."); | |
System.err.println(" -d: allow version code downgrade."); | |
System.err.println(""); | |
System.err.println("pm uninstall: removes a package from the system. Options:"); | |
System.err.println(" -k: keep the data and cache directories around after package removal."); | |
System.err.println(""); | |
System.err.println("pm clear: deletes all data associated with a package."); | |
System.err.println(""); | |
System.err.println("pm enable, disable, disable-user: these commands change the enabled state"); | |
System.err.println(" of a given package or component (written as \"package/class\")."); | |
System.err.println(""); | |
System.err.println("pm grant, revoke: these commands either grant or revoke permissions"); | |
System.err.println(" to applications. Only optional permissions the application has"); | |
System.err.println(" declared can be granted or revoked."); | |
System.err.println(""); | |
System.err.println("pm get-install-location: returns the current install location."); | |
System.err.println(" 0 [auto]: Let system decide the best location"); | |
System.err.println(" 1 [internal]: Install on internal device storage"); | |
System.err.println(" 2 [external]: Install on external media"); | |
System.err.println(""); | |
System.err.println("pm set-install-location: changes the default install location."); | |
System.err.println(" NOTE: this is only intended for debugging; using this can cause"); | |
System.err.println(" applications to break and other undersireable behavior."); | |
System.err.println(" 0 [auto]: Let system decide the best location"); | |
System.err.println(" 1 [internal]: Install on internal device storage"); | |
System.err.println(" 2 [external]: Install on external media"); | |
System.err.println(""); | |
System.err.println("pm trim-caches: trim cache files to reach the given free space."); | |
System.err.println(""); | |
System.err.println("pm create-user: create a new user with the given USER_NAME,"); | |
System.err.println(" printing the new user identifier of the user."); | |
System.err.println(""); | |
System.err.println("pm remove-user: remove the user with the given USER_IDENTIFIER,"); | |
System.err.println(" deleting all data associated with that user"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment