summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dario Freni <dariofreni@google.com> 2018-12-12 11:55:01 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2018-12-12 11:55:01 +0000
commitec06c2536023f207d1c900c544932cc46699af66 (patch)
treec7a0777ed1a05d55e5beb61643d991eb507b55a6
parentab11e004490229e41cbd3cc31361bb67bb8a3e07 (diff)
parentaac4ba4b24424479aa3ce9522e7f775e0c3e67ae (diff)
Merge "Add Mock APIs for staged installs."
-rw-r--r--api/current.txt4
-rw-r--r--core/java/android/content/pm/IPackageInstaller.aidl2
-rw-r--r--core/java/android/content/pm/IPackageInstallerSession.aidl3
-rw-r--r--core/java/android/content/pm/PackageInstaller.java55
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java34
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java19
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java5
7 files changed, 120 insertions, 2 deletions
diff --git a/api/current.txt b/api/current.txt
index 4804136173f1..e43007e0b4de 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11235,6 +11235,7 @@ package android.content.pm {
method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllSessions();
method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions();
method public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int);
+ method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getStagedSessions();
method public android.content.pm.PackageInstaller.Session openSession(int) throws java.io.IOException;
method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
@@ -11273,6 +11274,7 @@ package android.content.pm {
method public java.lang.String[] getNames() throws java.io.IOException;
method public int getParentSessionId();
method public boolean isMultiPackage();
+ method public boolean isStaged();
method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
method public void removeChildSessionId(int);
@@ -11311,6 +11313,7 @@ package android.content.pm {
method public boolean isActive();
method public boolean isMultiPackage();
method public boolean isSealed();
+ method public boolean isStaged();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR;
field public static final int INVALID_ID = -1; // 0xffffffff
@@ -11329,6 +11332,7 @@ package android.content.pm {
method public void setOriginatingUri(android.net.Uri);
method public void setReferrerUri(android.net.Uri);
method public void setSize(long);
+ method public void setStaged();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionParams> CREATOR;
field public static final int MODE_FULL_INSTALL = 1; // 0x1
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index ecc8cd678af1..a251c0036a78 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -42,6 +42,8 @@ interface IPackageInstaller {
ParceledListSlice getAllSessions(int userId);
ParceledListSlice getMySessions(String installerPackageName, int userId);
+ ParceledListSlice getStagedSessions();
+
void registerCallback(IPackageInstallerCallback callback, int userId);
void unregisterCallback(IPackageInstallerCallback callback);
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index cef21f607e5f..04e15c7957bd 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -38,9 +38,12 @@ interface IPackageInstallerSession {
void commit(in IntentSender statusReceiver, boolean forTransferred);
void transfer(in String packageName);
void abandon();
+
boolean isMultiPackage();
int[] getChildSessionIds();
void addChildSessionId(in int sessionId);
void removeChildSessionId(in int sessionId);
int getParentSessionId();
+
+ boolean isStaged();
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 07672d979cf5..96c30f156105 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -463,6 +463,18 @@ public class PackageInstaller {
}
/**
+ * Return list of all staged install sessions.
+ */
+ public @NonNull List<SessionInfo> getStagedSessions() {
+ try {
+ // TODO: limit this to the mUserId?
+ return mInstaller.getStagedSessions().getList();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Uninstall the given package, removing it completely from the device. This
* method is available to:
* <ul>
@@ -779,6 +791,11 @@ public class PackageInstaller {
* individual session IDs can be added with {@link #addChildSessionId(int)}
* and commit of the multi-package session will result in all child sessions
* being committed atomically.
+ * <p>
+ * If a package requires to be installed only at reboot, the session should
+ * be marked as a staged session by calling {@link SessionParams#setStaged()}
+ * with {@code true}. This can also apply to a multi-package session, in
+ * which case all the packages in the session will be applied at reboot.
*/
public static class Session implements Closeable {
/** {@hide} */
@@ -1105,6 +1122,17 @@ public class PackageInstaller {
}
/**
+ * @return {@code true} if this session will be staged and applied at next reboot.
+ */
+ public boolean isStaged() {
+ try {
+ return mSession.isStaged();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @return the session ID of the multi-package session that this belongs to or
* {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session.
*/
@@ -1227,6 +1255,8 @@ public class PackageInstaller {
public String installerPackageName;
/** {@hide} */
public boolean isMultiPackage;
+ /** {@hide} */
+ public boolean isStaged;
/**
* Construct parameters for a new package install session.
@@ -1257,6 +1287,7 @@ public class PackageInstaller {
grantedRuntimePermissions = source.readStringArray();
installerPackageName = source.readString();
isMultiPackage = source.readBoolean();
+ isStaged = source.readBoolean();
}
/**
@@ -1471,6 +1502,17 @@ public class PackageInstaller {
this.isMultiPackage = true;
}
+ /**
+ * Set this session to be staged to be installed at reboot.
+ *
+ * Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be
+ * multi-package. In that case, if any of the children sessions fail to install at reboot,
+ * all the other children sessions are aborted as well.
+ */
+ public void setStaged() {
+ this.isStaged = true;
+ }
+
/** {@hide} */
public void dump(IndentingPrintWriter pw) {
pw.printPair("mode", mode);
@@ -1488,6 +1530,7 @@ public class PackageInstaller {
pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions);
pw.printPair("installerPackageName", installerPackageName);
pw.printPair("isMultiPackage", isMultiPackage);
+ pw.printPair("isStaged", isStaged);
pw.println();
}
@@ -1514,6 +1557,7 @@ public class PackageInstaller {
dest.writeStringArray(grantedRuntimePermissions);
dest.writeString(installerPackageName);
dest.writeBoolean(isMultiPackage);
+ dest.writeBoolean(isStaged);
}
public static final Parcelable.Creator<SessionParams>
@@ -1593,6 +1637,8 @@ public class PackageInstaller {
/** {@hide} */
public boolean isMultiPackage;
/** {@hide} */
+ public boolean isStaged;
+ /** {@hide} */
public int parentSessionId = INVALID_ID;
/** {@hide} */
public int[] childSessionIds = NO_SESSIONS;
@@ -1625,6 +1671,7 @@ public class PackageInstaller {
grantedRuntimePermissions = source.readStringArray();
installFlags = source.readInt();
isMultiPackage = source.readBoolean();
+ isStaged = source.readBoolean();
parentSessionId = source.readInt();
childSessionIds = source.createIntArray();
if (childSessionIds == null) {
@@ -1892,6 +1939,13 @@ public class PackageInstaller {
}
/**
+ * Returns true if this session is a staged session which will be applied at next reboot.
+ */
+ public boolean isStaged() {
+ return isStaged;
+ }
+
+ /**
* Returns the parent multi-package session ID if this session belongs to one,
* {@link #INVALID_ID} otherwise.
*/
@@ -1935,6 +1989,7 @@ public class PackageInstaller {
dest.writeStringArray(grantedRuntimePermissions);
dest.writeInt(installFlags);
dest.writeBoolean(isMultiPackage);
+ dest.writeBoolean(isStaged);
dest.writeInt(parentSessionId);
dest.writeIntArray(childSessionIds);
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 2e9a71a178fb..57922d052984 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -164,6 +164,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
@GuardedBy("mSessions")
private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>();
+ // STOPSHIP: This is a temporary mock implementation of staged sessions. This variable
+ // shouldn't be needed at all.
+ @GuardedBy("mStagedSessions")
+ private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>();
+
/** Historical sessions kept around for debugging purposes */
@GuardedBy("mSessions")
private final List<String> mHistoricalSessions = new ArrayList<>();
@@ -536,6 +541,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
synchronized (mSessions) {
mSessions.put(sessionId, session);
}
+ if (params.isStaged) {
+ synchronized (mStagedSessions) {
+ mStagedSessions.put(sessionId, session);
+ }
+ }
mCallbacks.notifySessionCreated(session.sessionId, session.userId);
writeSessionsAsync();
@@ -666,6 +676,18 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
@Override
+ public ParceledListSlice<SessionInfo> getStagedSessions() {
+ final List<SessionInfo> result = new ArrayList<>();
+ synchronized (mStagedSessions) {
+ for (int i = 0; i < mStagedSessions.size(); i++) {
+ final PackageInstallerSession session = mStagedSessions.valueAt(i);
+ result.add(session.generateInfo(false));
+ }
+ }
+ return new ParceledListSlice<>(result);
+ }
+
+ @Override
public ParceledListSlice<SessionInfo> getAllSessions(int userId) {
mPermissionManager.enforceCrossUserPermission(
Binder.getCallingUid(), userId, true, false, "getAllSessions");
@@ -1110,6 +1132,18 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
mInstallHandler.post(new Runnable() {
@Override
public void run() {
+ // TODO: remove this mock implementation.
+ if (session.isStaged()) {
+ // If the session is aborted, don't keep it in memory. Only store
+ // sessions successfully staged.
+ if (!success) {
+ synchronized (mStagedSessions) {
+ mStagedSessions.remove(session.sessionId);
+ }
+ } else {
+ return;
+ }
+ }
synchronized (mSessions) {
mSessions.remove(session.sessionId);
addHistoricalSessionLocked(session);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index ea190a7301fc..26a92a4cdde4 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -125,7 +125,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
- private static final String TAG = "PackageInstaller";
+ private static final String TAG = "PackageInstallerSession";
private static final boolean LOGD = true;
private static final String REMOVE_SPLIT_MARKER_EXTENSION = ".removed";
@@ -147,6 +147,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String ATTR_SEALED = "sealed";
private static final String ATTR_MULTI_PACKAGE = "multiPackage";
private static final String ATTR_PARENT_SESSION_ID = "parentSessionId";
+ private static final String ATTR_STAGED_SESSION = "stagedSession";
private static final String ATTR_MODE = "mode";
private static final String ATTR_INSTALL_FLAGS = "installFlags";
private static final String ATTR_INSTALL_LOCATION = "installLocation";
@@ -463,6 +464,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
info.grantedRuntimePermissions = params.grantedRuntimePermissions;
info.installFlags = params.installFlags;
info.isMultiPackage = params.isMultiPackage;
+ info.isStaged = params.isStaged;
info.parentSessionId = mParentSessionId;
info.childSessionIds = mChildSessionIds.copyKeys();
if (info.childSessionIds == null) {
@@ -1047,6 +1049,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (committingSession == null) {
return;
}
+ if (isStaged()) {
+ // STOPSHIP: implement staged sessions
+ dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
+ return;
+ }
if (isMultiPackage()) {
final int[] childSessionIds = getChildSessionIds();
List<PackageManagerService.ActiveInstallSession> childSessions =
@@ -1816,6 +1823,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
@Override
+ public boolean isStaged() {
+ return params.isStaged;
+ }
+
+ @Override
public int[] getChildSessionIds() {
final int[] childSessionIds = mChildSessionIds.copyKeys();
if (childSessionIds != null) {
@@ -1838,6 +1850,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
session.setParentSessionId(this.sessionId);
+ // TODO: sanity check, if parent session is staged then child session should be
+ // marked as staged.
addChildSessionIdInternal(sessionId);
}
}
@@ -1975,6 +1989,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
pw.printPair("mFinalStatus", mFinalStatus);
pw.printPair("mFinalMessage", mFinalMessage);
pw.printPair("params.isMultiPackage", params.isMultiPackage);
+ pw.printPair("params.isStaged", params.isStaged);
pw.println();
pw.decreaseIndent();
@@ -2026,6 +2041,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
writeBooleanAttribute(out, ATTR_SEALED, isSealed());
writeBooleanAttribute(out, ATTR_MULTI_PACKAGE, params.isMultiPackage);
+ writeBooleanAttribute(out, ATTR_STAGED_SESSION, params.isStaged);
// TODO(patb,109941548): avoid writing to xml and instead infer / validate this after
// we've read all sessions.
writeIntAttribute(out, ATTR_PARENT_SESSION_ID, mParentSessionId);
@@ -2140,6 +2156,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final SessionParams params = new SessionParams(
SessionParams.MODE_INVALID);
params.isMultiPackage = readBooleanAttribute(in, ATTR_MULTI_PACKAGE, false);
+ params.isStaged = readBooleanAttribute(in, ATTR_STAGED_SESSION, false);
params.mode = readIntAttribute(in, ATTR_MODE);
params.installFlags = readIntAttribute(in, ATTR_INSTALL_FLAGS);
params.installLocation = readIntAttribute(in, ATTR_INSTALL_LOCATION);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 77f8c3a0308a..ee9c5ce4a854 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2284,6 +2284,9 @@ class PackageManagerShellCommand extends ShellCommand {
case "--multi-package":
sessionParams.setMultiPackage();
break;
+ case "--staged":
+ sessionParams.setStaged();
+ break;
default:
throw new IllegalArgumentException("Unknown option " + opt);
}
@@ -2853,7 +2856,7 @@ class PackageManagerShellCommand extends ShellCommand {
pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
pw.println(" [--preload] [--instantapp] [--full] [--dont-kill]");
pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [--apex] [-S BYTES]");
- pw.println(" [--multi-package]");
+ pw.println(" [--multi-package] [--staged]");
pw.println(" Like \"install\", but starts an install session. Use \"install-write\"");
pw.println(" to push data into the session, and \"install-commit\" to finish.");
pw.println("");