diff options
Diffstat (limited to 'cmds/pm')
-rw-r--r-- | cmds/pm/src/com/android/commands/pm/Pm.java | 655 |
1 files changed, 448 insertions, 207 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index c10c959..5249065 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -18,16 +18,23 @@ package com.android.commands.pm; import android.app.ActivityManager; import android.app.ActivityManagerNative; +import android.app.IActivityManager; +import android.app.PackageInstallObserver; import android.content.ComponentName; +import android.content.IIntentReceiver; +import android.content.IIntentSender; +import android.content.Intent; +import android.content.IntentSender; 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.IPackageInstaller; import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; +import android.content.pm.PackageInstaller.SessionInfo; +import android.content.pm.PackageInstaller.SessionParams; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; @@ -39,30 +46,43 @@ import android.content.res.AssetManager; import android.content.res.Resources; import android.net.Uri; import android.os.Build; +import android.os.Bundle; import android.os.IUserManager; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.content.PackageHelper; +import com.android.internal.util.ArrayUtils; +import com.android.internal.util.SizedInputStream; + +import libcore.io.IoUtils; import java.io.File; import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; 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; - -import com.android.internal.content.PackageHelper; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.TimeUnit; public final class Pm { + private static final String TAG = "Pm"; + IPackageManager mPm; + IPackageInstaller mInstaller; IUserManager mUm; private WeakHashMap<String, Resources> mResourceCache @@ -76,10 +96,18 @@ public final class Pm { "Error: Could not access the Package Manager. Is the system running?"; public static void main(String[] args) { - new Pm().run(args); + try { + new Pm().run(args); + } catch (Exception e) { + Log.e(TAG, "Error", e); + System.err.println("Error: " + e); + if (e instanceof RemoteException) { + System.err.println(PM_NOT_RUNNING_ERR); + } + } } - public void run(String[] args) { + public void run(String[] args) throws IOException, RemoteException { boolean validCommand = false; if (args.length < 1) { showUsage(); @@ -92,6 +120,7 @@ public final class Pm { System.err.println(PM_NOT_RUNNING_ERR); return; } + mInstaller = mPm.getPackageInstaller(); mArgs = args; String op = args[0]; @@ -117,6 +146,31 @@ public final class Pm { return; } + if ("install-create".equals(op)) { + runInstallCreate(); + return; + } + + if ("install-write".equals(op)) { + runInstallWrite(); + return; + } + + if ("install-commit".equals(op)) { + runInstallCommit(); + return; + } + + if ("install-abandon".equals(op) || "install-destroy".equals(op)) { + runInstallAbandon(); + return; + } + + if ("set-installer".equals(op)) { + runSetInstaller(); + return; + } + if ("uninstall".equals(op)) { runUninstall(); return; @@ -147,13 +201,13 @@ public final class Pm { return; } - if ("block".equals(op)) { - runSetBlockedSetting(true); + if ("hide".equals(op)) { + runSetHiddenSetting(true); return; } - if ("unblock".equals(op)) { - runSetBlockedSetting(false); + if ("unhide".equals(op)) { + runSetHiddenSetting(false); return; } @@ -202,6 +256,11 @@ public final class Pm { return; } + if ("force-dex-opt".equals(op)) { + runForceDexOpt(); + return; + } + try { if (args.length == 1) { if (args[0].equalsIgnoreCase("-l")) { @@ -701,14 +760,23 @@ public final class Pm { ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg); } - class PackageInstallObserver extends IPackageInstallObserver.Stub { + class LocalPackageInstallObserver extends PackageInstallObserver { boolean finished; int result; + String extraPermission; + String extraPackage; - public void packageInstalled(String name, int status) { - synchronized( this) { + @Override + public void onPackageInstalled(String name, int status, String msg, Bundle extras) { + synchronized (this) { finished = true; result = status; + if (status == PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION) { + extraPermission = extras.getString( + PackageManager.EXTRA_FAILURE_EXISTING_PERMISSION); + extraPackage = extras.getString( + PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE); + } notifyAll(); } } @@ -718,7 +786,8 @@ public final class Pm { * Converts a failure code into a string by using reflection to find a matching constant * in PackageManager. */ - private String installFailureToString(int result) { + private String installFailureToString(LocalPackageInstallObserver obs) { + final int result = obs.result; Field[] fields = PackageManager.class.getFields(); for (Field f: fields) { if (f.getType() == int.class) { @@ -733,7 +802,16 @@ public final class Pm { // get the int value and compare it to result. try { if (result == f.getInt(null)) { - return fieldName; + StringBuilder sb = new StringBuilder(64); + sb.append(fieldName); + if (obs.extraPermission != null) { + sb.append(" perm="); + sb.append(obs.extraPermission); + } + if (obs.extraPackage != null) { + sb.append(" pkg=" + obs.extraPackage); + } + return sb.toString(); } } catch (IllegalAccessException e) { // this shouldn't happen since we only look for public static fields. @@ -790,18 +868,12 @@ public final class Pm { } private void runInstall() { - int installFlags = PackageManager.INSTALL_ALL_USERS; + int installFlags = 0; + int userId = UserHandle.USER_ALL; 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; String abi = null; @@ -827,42 +899,6 @@ public final class Pm { 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) { @@ -876,70 +912,20 @@ public final class Pm { return; } } else if (opt.equals("--abi")) { - abi = nextOptionData(); - if (abi == null) { - System.err.println("Error: must supply argument for --abi"); - return; - } + abi = checkAbiArgument(nextOptionData()); + } else if (opt.equals("--user")) { + userId = Integer.parseInt(nextOptionData()); } else { System.err.println("Error: Unknown option: " + opt); return; } } - if (abi != null) { - final String[] supportedAbis = Build.SUPPORTED_ABIS; - boolean matched = false; - for (String supportedAbi : supportedAbis) { - if (supportedAbi.equals(abi)) { - matched = true; - break; - } - } - - if (!matched) { - System.err.println("Error: abi " + abi + " not supported on this device."); - return; - } + if (userId == UserHandle.USER_ALL) { + userId = UserHandle.USER_OWNER; + installFlags |= PackageManager.INSTALL_ALL_USERS; } - 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; @@ -959,9 +945,7 @@ public final class Pm { // Populate apkURI, must be present final String apkFilePath = nextArg(); System.err.println("\tpkg: " + apkFilePath); - if (apkFilePath != null) { - apkURI = Uri.fromFile(new File(apkFilePath)); - } else { + if (apkFilePath == null) { System.err.println("Error: no package specified"); return; } @@ -975,14 +959,13 @@ public final class Pm { verificationURI = null; } - PackageInstallObserver obs = new PackageInstallObserver(); + LocalPackageInstallObserver obs = new LocalPackageInstallObserver(); try { VerificationParams verificationParams = new VerificationParams(verificationURI, originatingURI, referrerURI, VerificationParams.NO_UID, null); - mPm.installPackageWithVerificationEncryptionAndAbiOverride(apkURI, obs, - installFlags, installerPackageName, verificationParams, - encryptionParams, abi); + mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags, + installerPackageName, verificationParams, abi, userId); synchronized (obs) { while (!obs.finished) { @@ -995,7 +978,7 @@ public final class Pm { System.out.println("Success"); } else { System.err.println("Failure [" - + installFailureToString(obs.result) + + installFailureToString(obs) + "]"); } } @@ -1005,39 +988,200 @@ public final class Pm { } } - /** - * 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; + private void runInstallCreate() throws RemoteException { + int userId = UserHandle.USER_ALL; + String installerPackageName = null; + + final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL); + + String opt; + while ((opt = nextOption()) != null) { + if (opt.equals("-l")) { + params.installFlags |= PackageManager.INSTALL_FORWARD_LOCK; + } else if (opt.equals("-r")) { + params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; + } else if (opt.equals("-i")) { + installerPackageName = nextArg(); + if (installerPackageName == null) { + throw new IllegalArgumentException("Missing installer package"); + } + } else if (opt.equals("-t")) { + params.installFlags |= PackageManager.INSTALL_ALLOW_TEST; + } else if (opt.equals("-s")) { + params.installFlags |= PackageManager.INSTALL_EXTERNAL; + } else if (opt.equals("-f")) { + params.installFlags |= PackageManager.INSTALL_INTERNAL; + } else if (opt.equals("-d")) { + params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; + } else if (opt.equals("--originating-uri")) { + params.originatingUri = Uri.parse(nextOptionData()); + } else if (opt.equals("--referrer")) { + params.referrerUri = Uri.parse(nextOptionData()); + } else if (opt.equals("-p")) { + params.mode = SessionParams.MODE_INHERIT_EXISTING; + params.appPackageName = nextOptionData(); + if (params.appPackageName == null) { + throw new IllegalArgumentException("Missing inherit package name"); + } + } else if (opt.equals("-S")) { + params.setSize(Long.parseLong(nextOptionData())); + } else if (opt.equals("--abi")) { + params.abiOverride = checkAbiArgument(nextOptionData()); + } else if (opt.equals("--user")) { + userId = Integer.parseInt(nextOptionData()); + } else { + throw new IllegalArgumentException("Unknown option " + opt); + } } - final int inputLength = input.length(); - if ((inputLength % 2) != 0) { - System.err.print("Invalid length; must be multiple of 2"); - return null; + if (userId == UserHandle.USER_ALL) { + userId = UserHandle.USER_OWNER; + params.installFlags |= PackageManager.INSTALL_ALL_USERS; + } + + final int sessionId = mInstaller.createSession(params, installerPackageName, userId); + + // NOTE: adb depends on parsing this string + System.out.println("Success: created install session [" + sessionId + "]"); + } + + private void runInstallWrite() throws IOException, RemoteException { + long sizeBytes = -1; + + String opt; + while ((opt = nextOption()) != null) { + if (opt.equals("-S")) { + sizeBytes = Long.parseLong(nextOptionData()); + } else { + throw new IllegalArgumentException("Unknown option: " + opt); + } + } + + final int sessionId = Integer.parseInt(nextArg()); + final String splitName = nextArg(); + + String path = nextArg(); + if ("-".equals(path)) { + path = null; + } else if (path != null) { + final File file = new File(path); + if (file.isFile()) { + sizeBytes = file.length(); + } + } + + final SessionInfo info = mInstaller.getSessionInfo(sessionId); + + PackageInstaller.Session session = null; + InputStream in = null; + OutputStream out = null; + try { + session = new PackageInstaller.Session(mInstaller.openSession(sessionId)); + + if (path != null) { + in = new FileInputStream(path); + } else { + in = new SizedInputStream(System.in, sizeBytes); + } + out = session.openWrite(splitName, 0, sizeBytes); + + int total = 0; + byte[] buffer = new byte[65536]; + int c; + while ((c = in.read(buffer)) != -1) { + total += c; + out.write(buffer, 0, c); + + if (info.sizeBytes > 0) { + final float fraction = ((float) c / (float) info.sizeBytes); + session.addProgress(fraction); + } + } + session.fsync(out); + + System.out.println("Success: streamed " + total + " bytes"); + } finally { + IoUtils.closeQuietly(out); + IoUtils.closeQuietly(in); + IoUtils.closeQuietly(session); + } + } + + private void runInstallCommit() throws RemoteException { + final int sessionId = Integer.parseInt(nextArg()); + + PackageInstaller.Session session = null; + try { + session = new PackageInstaller.Session(mInstaller.openSession(sessionId)); + + final LocalIntentReceiver receiver = new LocalIntentReceiver(); + session.commit(receiver.getIntentSender()); + + final Intent result = receiver.getResult(); + final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, + PackageInstaller.STATUS_FAILURE); + if (status == PackageInstaller.STATUS_SUCCESS) { + System.out.println("Success"); + } else { + Log.e(TAG, "Failure details: " + result.getExtras()); + System.out.println("Failure [" + + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); + return; + } + } finally { + IoUtils.closeQuietly(session); + } + } + + private void runInstallAbandon() throws RemoteException { + final int sessionId = Integer.parseInt(nextArg()); + + PackageInstaller.Session session = null; + try { + session = new PackageInstaller.Session(mInstaller.openSession(sessionId)); + session.abandon(); + System.out.println("Success"); + } finally { + IoUtils.closeQuietly(session); } + } - final int byteLength = inputLength / 2; - final byte[] output = new byte[byteLength]; + private void runSetInstaller() throws RemoteException { + final String targetPackage = nextArg(); + final String installerPackageName = nextArg(); - int inputIndex = 0; - int byteIndex = 0; - while (inputIndex < inputLength) { - output[byteIndex++] = (byte) Integer.parseInt( - input.substring(inputIndex, inputIndex + 2), 16); - inputIndex += 2; + if (targetPackage == null || installerPackageName == null) { + throw new IllegalArgumentException( + "must provide both target and installer package names"); } - return output; + mPm.setInstallerPackageName(targetPackage, installerPackageName); + System.out.println("Success"); } public void runCreateUser() { String name; + int userId = -1; + int flags = 0; + String opt; + while ((opt = nextOption()) != null) { + if ("--profileOf".equals(opt)) { + String optionData = nextOptionData(); + if (optionData == null || !isNumber(optionData)) { + System.err.println("Error: no USER_ID specified"); + showUsage(); + return; + } else { + userId = Integer.parseInt(optionData); + } + } else if ("--managed".equals(opt)) { + flags |= UserInfo.FLAG_MANAGED_PROFILE; + } else { + System.err.println("Error: unknown option " + opt); + showUsage(); + return; + } + } String arg = nextArg(); if (arg == null) { System.err.println("Error: no user name specified."); @@ -1045,7 +1189,12 @@ public final class Pm { } name = arg; try { - final UserInfo info = mUm.createUser(name, 0); + UserInfo info = null; + if (userId < 0) { + info = mUm.createUser(name, flags); + } else { + info = mUm.createProfileForUser(name, flags, userId); + } if (info != null) { System.out.println("Success: created user id " + info.id); } else { @@ -1085,13 +1234,16 @@ public final class Pm { public void runListUsers() { try { + IActivityManager am = ActivityManagerNative.getDefault(); + 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()); + String running = am.isUserRunning(users.get(i).id, false) ? " running" : ""; + System.out.println("\t" + users.get(i).toString() + running); } } } catch (RemoteException e) { @@ -1104,26 +1256,32 @@ public final class Pm { 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(); - } + public void runForceDexOpt() { + final String packageName = nextArg(); + try { + mPm.forceDexOpt(packageName); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); } } - private void runUninstall() { - int unInstallFlags = PackageManager.DELETE_ALL_USERS; + private void runUninstall() throws RemoteException { + int flags = 0; + int userId = UserHandle.USER_ALL; String opt; while ((opt=nextOption()) != null) { if (opt.equals("-k")) { - unInstallFlags |= PackageManager.DELETE_KEEP_DATA; + flags |= PackageManager.DELETE_KEEP_DATA; + } else if (opt.equals("--user")) { + String param = nextArg(); + if (isNumber(param)) { + userId = Integer.parseInt(param); + } else { + showUsage(); + System.err.println("Error: Invalid user: " + param); + return; + } } else { System.err.println("Error: Unknown option: " + opt); return; @@ -1136,32 +1294,46 @@ public final class Pm { showUsage(); return; } - boolean result = deletePackage(pkg, unInstallFlags); - if (result) { - System.out.println("Success"); + + if (userId == UserHandle.USER_ALL) { + userId = UserHandle.USER_OWNER; + flags |= PackageManager.DELETE_ALL_USERS; } else { - System.out.println("Failure"); + PackageInfo info; + try { + info = mPm.getPackageInfo(pkg, 0, userId); + } catch (RemoteException e) { + System.err.println(e.toString()); + System.err.println(PM_NOT_RUNNING_ERR); + return; + } + if (info == null) { + System.err.println("Failure - not installed for " + userId); + return; + } + final boolean isSystem = + (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + // If we are being asked to delete a system app for just one + // user set flag so it disables rather than reverting to system + // version of the app. + if (isSystem) { + flags |= PackageManager.DELETE_SYSTEM_APP; + } } - } - private boolean deletePackage(String pkg, int unInstallFlags) { - PackageDeleteObserver obs = new PackageDeleteObserver(); - try { - mPm.deletePackageAsUser(pkg, obs, UserHandle.USER_OWNER, unInstallFlags); + final LocalIntentReceiver receiver = new LocalIntentReceiver(); + mInstaller.uninstall(pkg, flags, receiver.getIntentSender(), userId); - 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); + final Intent result = receiver.getResult(); + final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, + PackageInstaller.STATUS_FAILURE); + if (status == PackageInstaller.STATUS_SUCCESS) { + System.out.println("Success"); + } else { + Log.e(TAG, "Failure details: " + result.getExtras()); + System.out.println("Failure [" + + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); } - return obs.result; } static class ClearDataObserver extends IPackageDataObserver.Stub { @@ -1176,7 +1348,6 @@ public final class Pm { notifyAll(); } } - } private void runClear() { @@ -1293,7 +1464,7 @@ public final class Pm { } } - private void runSetBlockedSetting(boolean state) { + private void runSetHiddenSetting(boolean state) { int userId = 0; String option = nextOption(); if (option != null && option.equals("--user")) { @@ -1314,9 +1485,9 @@ public final class Pm { return; } try { - mPm.setApplicationBlockedSettingAsUser(pkg, state, userId); - System.err.println("Package " + pkg + " new blocked state: " - + mPm.getApplicationBlockedSettingAsUser(pkg, userId)); + mPm.setApplicationHiddenSettingAsUser(pkg, state, userId); + System.err.println("Package " + pkg + " new hidden state: " + + mPm.getApplicationHiddenSettingAsUser(pkg, userId)); } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); @@ -1459,6 +1630,12 @@ public final class Pm { if (info != null && info.applicationInfo != null) { System.out.print("package:"); System.out.println(info.applicationInfo.sourceDir); + if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) { + for (String splitSourceDir : info.applicationInfo.splitSourceDirs) { + System.out.print("package:"); + System.out.println(splitSourceDir); + } + } } } catch (RemoteException e) { System.err.println(e.toString()); @@ -1484,6 +1661,54 @@ public final class Pm { } } + private static String checkAbiArgument(String abi) { + if (TextUtils.isEmpty(abi)) { + throw new IllegalArgumentException("Missing ABI argument"); + } + + if ("-".equals(abi)) { + return abi; + } + + final String[] supportedAbis = Build.SUPPORTED_ABIS; + for (String supportedAbi : supportedAbis) { + if (supportedAbi.equals(abi)) { + return abi; + } + } + + throw new IllegalArgumentException("ABI " + abi + " not supported on this device"); + } + + private static class LocalIntentReceiver { + private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>(); + + private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() { + @Override + public int send(int code, Intent intent, String resolvedType, + IIntentReceiver finishedReceiver, String requiredPermission) { + try { + mResult.offer(intent, 5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + return 0; + } + }; + + public IntentSender getIntentSender() { + return new IntentSender((IIntentSender) mLocalSender); + } + + public Intent getResult() { + try { + return mResult.take(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + private String nextOption() { if (mNextArg >= mArgs.length) { return null; @@ -1540,24 +1765,27 @@ public final class Pm { System.err.println(" pm list users"); System.err.println(" pm path PACKAGE"); System.err.println(" pm dump 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 install [-lrtsfd] [-i PACKAGE] [PATH]"); + System.err.println(" pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]"); + System.err.println(" pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]"); + System.err.println(" pm install-commit SESSION_ID"); + System.err.println(" pm install-abandon SESSION_ID"); + System.err.println(" pm uninstall [-k] [--user USER_ID] PACKAGE"); + System.err.println(" pm set-installer PACKAGE INSTALLER"); 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 disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT"); - System.err.println(" pm block [--user USER_ID] PACKAGE_OR_COMPONENT"); - System.err.println(" pm unblock [--user USER_ID] PACKAGE_OR_COMPONENT"); + System.err.println(" pm hide [--user USER_ID] PACKAGE_OR_COMPONENT"); + System.err.println(" pm unhide [--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 create-user [--profileOf USER_ID] [--managed] USER_NAME"); System.err.println(" pm remove-user USER_ID"); System.err.println(" pm get-max-users"); System.err.println(""); @@ -1592,16 +1820,28 @@ public final class Pm { 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 dump: print system state associated w ith the given PACKAGE."); + System.err.println("pm dump: print system state associated with the given PACKAGE."); + System.err.println(""); + System.err.println("pm install: install a single legacy package"); + System.err.println("pm install-create: create an install session"); + System.err.println(" -l: forward lock application"); + System.err.println(" -r: replace existing application"); + System.err.println(" -t: allow test packages"); + System.err.println(" -i: specify the installer package name"); + System.err.println(" -s: install application on sdcard"); + System.err.println(" -f: install application on internal flash"); + System.err.println(" -d: allow version code downgrade"); + System.err.println(" -p: partial application install"); + System.err.println(" -S: size in bytes of entire session"); 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("pm install-write: write a package into existing session; path may"); + System.err.println(" be '-' to read from stdin"); + System.err.println(" -S: size in bytes of package, required for stdin"); + System.err.println(""); + System.err.println("pm install-commit: perform install of fully staged session"); + System.err.println("pm install-abandon: abandon session"); + System.err.println(""); + System.err.println("pm set-installer: set installer package name"); 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."); @@ -1635,5 +1875,6 @@ public final class Pm { 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"); + System.err.println(""); } } |