Merge changes from topic "wait-for-staged-session"
am: 5a8283d7fd
Change-Id: I5b63c45dbc6340fe58b070a0ab19e3be87ad6128
This commit is contained in:
@@ -93,9 +93,11 @@ import android.text.TextUtils;
|
|||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.PrintWriterPrinter;
|
import android.util.PrintWriterPrinter;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import com.android.internal.content.PackageHelper;
|
import com.android.internal.content.PackageHelper;
|
||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.SystemConfig;
|
import com.android.server.SystemConfig;
|
||||||
|
|
||||||
@@ -129,6 +131,7 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
private static final String STDIN_PATH = "-";
|
private static final String STDIN_PATH = "-";
|
||||||
/** Path where ART profiles snapshots are dumped for the shell user */
|
/** Path where ART profiles snapshots are dumped for the shell user */
|
||||||
private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
|
private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
|
||||||
|
private static final int DEFAULT_WAIT_MS = 60 * 1000;
|
||||||
|
|
||||||
final IPackageManager mInterface;
|
final IPackageManager mInterface;
|
||||||
final private WeakHashMap<String, Resources> mResourceCache =
|
final private WeakHashMap<String, Resources> mResourceCache =
|
||||||
@@ -269,7 +272,7 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
case "get-harmful-app-warning":
|
case "get-harmful-app-warning":
|
||||||
return runGetHarmfulAppWarning();
|
return runGetHarmfulAppWarning();
|
||||||
case "get-stagedsessions":
|
case "get-stagedsessions":
|
||||||
return getStagedSessions();
|
return runListStagedSessions();
|
||||||
case "uninstall-system-updates":
|
case "uninstall-system-updates":
|
||||||
return uninstallSystemUpdates();
|
return uninstallSystemUpdates();
|
||||||
case "rollback-app":
|
case "rollback-app":
|
||||||
@@ -341,28 +344,6 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getStagedSessions() {
|
|
||||||
final PrintWriter pw = getOutPrintWriter();
|
|
||||||
try {
|
|
||||||
List<SessionInfo> stagedSessionsList =
|
|
||||||
mInterface.getPackageInstaller().getStagedSessions().getList();
|
|
||||||
for (SessionInfo session: stagedSessionsList) {
|
|
||||||
pw.println("appPackageName = " + session.getAppPackageName()
|
|
||||||
+ "; sessionId = " + session.getSessionId()
|
|
||||||
+ "; isStaged = " + session.isStaged()
|
|
||||||
+ "; isStagedSessionReady = " + session.isStagedSessionReady()
|
|
||||||
+ "; isStagedSessionApplied = " + session.isStagedSessionApplied()
|
|
||||||
+ "; isStagedSessionFailed = " + session.isStagedSessionFailed() + ";");
|
|
||||||
}
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
pw.println("Failure ["
|
|
||||||
+ e.getClass().getName() + " - "
|
|
||||||
+ e.getMessage() + "]");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int uninstallSystemUpdates() {
|
private int uninstallSystemUpdates() {
|
||||||
final PrintWriter pw = getOutPrintWriter();
|
final PrintWriter pw = getOutPrintWriter();
|
||||||
List<String> failedUninstalls = new LinkedList<>();
|
List<String> failedUninstalls = new LinkedList<>();
|
||||||
@@ -535,6 +516,8 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
return runListPermissionGroups();
|
return runListPermissionGroups();
|
||||||
case "permissions":
|
case "permissions":
|
||||||
return runListPermissions();
|
return runListPermissions();
|
||||||
|
case "staged-sessions":
|
||||||
|
return runListStagedSessions();
|
||||||
case "users":
|
case "users":
|
||||||
ServiceManager.getService("user").shellCommand(
|
ServiceManager.getService("user").shellCommand(
|
||||||
getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
|
getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
|
||||||
@@ -871,6 +854,103 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class SessionDump {
|
||||||
|
boolean onlyParent; // Show parent sessions only
|
||||||
|
boolean onlyReady; // Show only staged sessions that are in ready state
|
||||||
|
boolean onlySessionId; // Show sessionId only
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the provided flag is a session flag and given SessionDump was updated
|
||||||
|
private boolean setSessionFlag(String flag, SessionDump sessionDump) {
|
||||||
|
switch (flag) {
|
||||||
|
case "--only-parent":
|
||||||
|
sessionDump.onlyParent = true;
|
||||||
|
break;
|
||||||
|
case "--only-ready":
|
||||||
|
sessionDump.onlyReady = true;
|
||||||
|
break;
|
||||||
|
case "--only-sessionid":
|
||||||
|
sessionDump.onlySessionId = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int runListStagedSessions() {
|
||||||
|
final IndentingPrintWriter pw = new IndentingPrintWriter(
|
||||||
|
getOutPrintWriter(), /* singleIndent */ " ", /* wrapLength */ 120);
|
||||||
|
|
||||||
|
SessionDump sessionDump = new SessionDump();
|
||||||
|
String opt;
|
||||||
|
while ((opt = getNextOption()) != null) {
|
||||||
|
if (!setSessionFlag(opt, sessionDump)) {
|
||||||
|
pw.println("Error: Unknown option: " + opt);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<SessionInfo> stagedSessions =
|
||||||
|
mInterface.getPackageInstaller().getStagedSessions().getList();
|
||||||
|
printSessionList(pw, stagedSessions, sessionDump);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
pw.println("Failure ["
|
||||||
|
+ e.getClass().getName() + " - "
|
||||||
|
+ e.getMessage() + "]");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions,
|
||||||
|
SessionDump sessionDump) {
|
||||||
|
final SparseArray<SessionInfo> sessionById = new SparseArray<>(stagedSessions.size());
|
||||||
|
for (SessionInfo session : stagedSessions) {
|
||||||
|
sessionById.put(session.getSessionId(), session);
|
||||||
|
}
|
||||||
|
for (SessionInfo session: stagedSessions) {
|
||||||
|
if (sessionDump.onlyReady && !session.isStagedSessionReady()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (session.getParentSessionId() != SessionInfo.INVALID_ID) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printSession(pw, session, sessionDump);
|
||||||
|
if (session.isMultiPackage() && !sessionDump.onlyParent) {
|
||||||
|
pw.increaseIndent();
|
||||||
|
final int[] childIds = session.getChildSessionIds();
|
||||||
|
for (int i = 0; i < childIds.length; i++) {
|
||||||
|
final SessionInfo childSession = sessionById.get(childIds[i]);
|
||||||
|
if (childSession == null) {
|
||||||
|
if (sessionDump.onlySessionId) {
|
||||||
|
pw.println(childIds[i]);
|
||||||
|
} else {
|
||||||
|
pw.println("sessionId = " + childIds[i] + "; not found");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printSession(pw, childSession, sessionDump);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pw.decreaseIndent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump) {
|
||||||
|
if (sessionDump.onlySessionId) {
|
||||||
|
pw.println(session.getSessionId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pw.println("sessionId = " + session.getSessionId()
|
||||||
|
+ "; appPackageName = " + session.getAppPackageName()
|
||||||
|
+ "; isStaged = " + session.isStaged()
|
||||||
|
+ "; isReady = " + session.isStagedSessionReady()
|
||||||
|
+ "; isApplied = " + session.isStagedSessionApplied()
|
||||||
|
+ "; isFailed = " + session.isStagedSessionFailed() + ";");
|
||||||
|
}
|
||||||
|
|
||||||
private Intent parseIntentAndUser() throws URISyntaxException {
|
private Intent parseIntentAndUser() throws URISyntaxException {
|
||||||
mTargetUser = UserHandle.USER_CURRENT;
|
mTargetUser = UserHandle.USER_CURRENT;
|
||||||
mBrief = false;
|
mBrief = false;
|
||||||
@@ -1078,6 +1158,45 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
abandonSession = false;
|
abandonSession = false;
|
||||||
|
|
||||||
|
if (!params.sessionParams.isStaged || !params.waitForStagedSessionReady) {
|
||||||
|
pw.println("Success");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long timeoutMs = params.timeoutMs <= 0
|
||||||
|
? DEFAULT_WAIT_MS
|
||||||
|
: params.timeoutMs;
|
||||||
|
PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
|
||||||
|
.getSessionInfo(sessionId);
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
long endTime = currentTime + timeoutMs;
|
||||||
|
// Using a loop instead of BroadcastReceiver since we can receive session update
|
||||||
|
// broadcast only if packageInstallerName is "android". We can't always force
|
||||||
|
// "android" as packageIntallerName, e.g, rollback auto implies
|
||||||
|
// "-i com.android.shell".
|
||||||
|
while (currentTime < endTime) {
|
||||||
|
if (si != null
|
||||||
|
&& (si.isStagedSessionReady() || si.isStagedSessionFailed())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SystemClock.sleep(Math.min(endTime - currentTime, 100));
|
||||||
|
currentTime = System.currentTimeMillis();
|
||||||
|
si = mInterface.getPackageInstaller().getSessionInfo(sessionId);
|
||||||
|
}
|
||||||
|
if (si == null) {
|
||||||
|
pw.println("Failure [failed to retrieve SessionInfo]");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!si.isStagedSessionReady() && !si.isStagedSessionFailed()) {
|
||||||
|
pw.println("Failure [timed out after " + timeoutMs + " ms]");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!si.isStagedSessionReady()) {
|
||||||
|
pw.println("Error [" + si.getStagedSessionErrorCode() + "] ["
|
||||||
|
+ si.getStagedSessionErrorMessage() + "]");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
pw.println("Success");
|
pw.println("Success");
|
||||||
return 0;
|
return 0;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -2368,6 +2487,8 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
SessionParams sessionParams;
|
SessionParams sessionParams;
|
||||||
String installerPackageName;
|
String installerPackageName;
|
||||||
int userId = UserHandle.USER_ALL;
|
int userId = UserHandle.USER_ALL;
|
||||||
|
boolean waitForStagedSessionReady = false;
|
||||||
|
long timeoutMs = DEFAULT_WAIT_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InstallParams makeInstallParams() {
|
private InstallParams makeInstallParams() {
|
||||||
@@ -2493,6 +2614,14 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
}
|
}
|
||||||
sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
|
sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
|
||||||
break;
|
break;
|
||||||
|
case "--wait":
|
||||||
|
params.waitForStagedSessionReady = true;
|
||||||
|
try {
|
||||||
|
params.timeoutMs = Long.parseLong(peekNextArg());
|
||||||
|
getNextArg();
|
||||||
|
} catch (NumberFormatException ignore) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unknown option " + opt);
|
throw new IllegalArgumentException("Unknown option " + opt);
|
||||||
}
|
}
|
||||||
@@ -3023,6 +3152,12 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
pw.println(" -d: only list dangerous permissions");
|
pw.println(" -d: only list dangerous permissions");
|
||||||
pw.println(" -u: list only the permissions users will see");
|
pw.println(" -u: list only the permissions users will see");
|
||||||
pw.println("");
|
pw.println("");
|
||||||
|
pw.println(" list staged-sessions [--only-ready] [--only-sessionid] [--only-parent]");
|
||||||
|
pw.println(" Displays list of all staged sessions on device.");
|
||||||
|
pw.println(" --only-ready: show only staged sessions that are ready");
|
||||||
|
pw.println(" --only-sessionid: show only sessionId of each session");
|
||||||
|
pw.println(" --only-parent: hide all children sessions");
|
||||||
|
pw.println("");
|
||||||
pw.println(" resolve-activity [--brief] [--components] [--query-flags FLAGS]");
|
pw.println(" resolve-activity [--brief] [--components] [--query-flags FLAGS]");
|
||||||
pw.println(" [--user USER_ID] INTENT");
|
pw.println(" [--user USER_ID] INTENT");
|
||||||
pw.println(" Prints the activity that resolves to the given INTENT.");
|
pw.println(" Prints the activity that resolves to the given INTENT.");
|
||||||
@@ -3045,7 +3180,8 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
|
pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
|
||||||
pw.println(" [--preload] [--instantapp] [--full] [--dont-kill]");
|
pw.println(" [--preload] [--instantapp] [--full] [--dont-kill]");
|
||||||
pw.println(" [--enable-rollback]");
|
pw.println(" [--enable-rollback]");
|
||||||
pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES] [--apex]");
|
pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
|
||||||
|
pw.println(" [--apex] [--wait TIMEOUT]");
|
||||||
pw.println(" [PATH|-]");
|
pw.println(" [PATH|-]");
|
||||||
pw.println(" Install an application. Must provide the apk data to install, either as a");
|
pw.println(" Install an application. Must provide the apk data to install, either as a");
|
||||||
pw.println(" file path or '-' to read from stdin. Options are:");
|
pw.println(" file path or '-' to read from stdin. Options are:");
|
||||||
@@ -3075,6 +3211,9 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
pw.println(" 3=device setup, 4=user request");
|
pw.println(" 3=device setup, 4=user request");
|
||||||
pw.println(" --force-uuid: force install on to disk volume with given UUID");
|
pw.println(" --force-uuid: force install on to disk volume with given UUID");
|
||||||
pw.println(" --apex: install an .apex file, not an .apk");
|
pw.println(" --apex: install an .apex file, not an .apk");
|
||||||
|
pw.println(" --wait: when performing staged install, wait TIMEOUT milliseconds");
|
||||||
|
pw.println(" for pre-reboot verification to complete. If TIMEOUT is not");
|
||||||
|
pw.println(" specified it will wait for " + DEFAULT_WAIT_MS + " milliseconds.");
|
||||||
pw.println("");
|
pw.println("");
|
||||||
pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
|
pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
|
||||||
pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
|
pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
|
||||||
@@ -3257,7 +3396,7 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
pw.println(" uninstall-system-updates");
|
pw.println(" uninstall-system-updates");
|
||||||
pw.println(" Remove updates to all system applications and fall back to their /system " +
|
pw.println(" Remove updates to all system applications and fall back to their /system " +
|
||||||
"version.");
|
"version.");
|
||||||
pw.println();
|
pw.println("");
|
||||||
pw.println(" get-moduleinfo [--all | --installed] [module-name]");
|
pw.println(" get-moduleinfo [--all | --installed] [module-name]");
|
||||||
pw.println(" Displays module info. If module-name is specified only that info is shown");
|
pw.println(" Displays module info. If module-name is specified only that info is shown");
|
||||||
pw.println(" By default, without any argument only installed modules are shown.");
|
pw.println(" By default, without any argument only installed modules are shown.");
|
||||||
|
|||||||
Reference in New Issue
Block a user