Allow to read all params used to create session.
So that they can be verified by the app calling commit().
This really only makes sense if the app calling commit is different from
the app that created the session.
Bug: 37281396
Test: cts-tradefed run cts-dev -m CtsContentTestCases --test=android.content.pm.cts.InstallSessionTransferTest
Installed and uninstalled packages via the PackageInstaller app
Change-Id: I5c954ca59b7582555bea847f3ddbba0aeefba301
diff --git a/api/current.txt b/api/current.txt
index 5f17b8a..2097444 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10524,10 +10524,16 @@
method public android.graphics.Bitmap getAppIcon();
method public java.lang.CharSequence getAppLabel();
method public java.lang.String getAppPackageName();
+ method public int getInstallLocation();
method public int getInstallReason();
method public java.lang.String getInstallerPackageName();
+ method public int getMode();
+ method public int getOriginatingUid();
+ method public android.net.Uri getOriginatingUri();
method public float getProgress();
+ method public android.net.Uri getReferrerUri();
method public int getSessionId();
+ method public long getSize();
method public boolean isActive();
method public boolean isSealed();
method public void writeToParcel(android.os.Parcel, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index cd8d054..6da5140 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -11202,13 +11202,26 @@
public static class PackageInstaller.SessionInfo implements android.os.Parcelable {
method public android.content.Intent createDetailsIntent();
method public int describeContents();
+ method public boolean getAllocateAggressive();
+ method public boolean getAllowDowngrade();
method public android.graphics.Bitmap getAppIcon();
method public java.lang.CharSequence getAppLabel();
method public java.lang.String getAppPackageName();
+ method public boolean getDontKillApp();
+ method public java.lang.String[] getGrantedRuntimePermissions();
+ method public boolean getInstallAsFullApp(boolean);
+ method public boolean getInstallAsInstantApp(boolean);
+ method public boolean getInstallAsVirtualPreload();
+ method public int getInstallLocation();
method public int getInstallReason();
method public java.lang.String getInstallerPackageName();
+ method public int getMode();
+ method public int getOriginatingUid();
+ method public android.net.Uri getOriginatingUri();
method public float getProgress();
+ method public android.net.Uri getReferrerUri();
method public int getSessionId();
+ method public long getSize();
method public boolean isActive();
method public boolean isSealed();
method public void writeToParcel(android.os.Parcel, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index f846205..7690a55 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -10562,10 +10562,16 @@
method public android.graphics.Bitmap getAppIcon();
method public java.lang.CharSequence getAppLabel();
method public java.lang.String getAppPackageName();
+ method public int getInstallLocation();
method public int getInstallReason();
method public java.lang.String getInstallerPackageName();
+ method public int getMode();
+ method public int getOriginatingUid();
+ method public android.net.Uri getOriginatingUri();
method public float getProgress();
+ method public android.net.Uri getReferrerUri();
method public int getSessionId();
+ method public long getSize();
method public boolean isActive();
method public boolean isSealed();
method public void writeToParcel(android.os.Parcel, int);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 38b3487..f4fdcaa 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1103,6 +1103,26 @@
}
/**
+ * Check if there are hidden options set.
+ *
+ * <p>Hidden options are those options that cannot be verified via public or system-api
+ * methods on {@link SessionInfo}.
+ *
+ * @return {@code true} if any hidden option is set.
+ *
+ * @hide
+ */
+ public boolean areHiddenOptionsSet() {
+ return (installFlags & (PackageManager.INSTALL_ALLOW_DOWNGRADE
+ | PackageManager.INSTALL_DONT_KILL_APP
+ | PackageManager.INSTALL_INSTANT_APP
+ | PackageManager.INSTALL_FULL_APP
+ | PackageManager.INSTALL_VIRTUAL_PRELOAD
+ | PackageManager.INSTALL_ALLOCATE_AGGRESSIVE)) != installFlags
+ || abiOverride != null || volumeUuid != null;
+ }
+
+ /**
* Provide value of {@link PackageInfo#installLocation}, which may be used
* to determine where the app will be staged. Defaults to
* {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}.
@@ -1362,6 +1382,19 @@
public CharSequence appLabel;
/** {@hide} */
+ public int installLocation;
+ /** {@hide} */
+ public Uri originatingUri;
+ /** {@hide} */
+ public int originatingUid;
+ /** {@hide} */
+ public Uri referrerUri;
+ /** {@hide} */
+ public String[] grantedRuntimePermissions;
+ /** {@hide} */
+ public int installFlags;
+
+ /** {@hide} */
public SessionInfo() {
}
@@ -1380,6 +1413,13 @@
appPackageName = source.readString();
appIcon = source.readParcelable(null);
appLabel = source.readString();
+
+ installLocation = source.readInt();
+ originatingUri = source.readParcelable(null);
+ originatingUid = source.readInt();
+ referrerUri = source.readParcelable(null);
+ grantedRuntimePermissions = source.readStringArray();
+ installFlags = source.readInt();
}
/**
@@ -1503,6 +1543,130 @@
return intent;
}
+ /**
+ * Get the mode of the session as set in the constructor of the {@link SessionParams}.
+ *
+ * @return One of {@link SessionParams#MODE_FULL_INSTALL}
+ * or {@link SessionParams#MODE_INHERIT_EXISTING}
+ */
+ public int getMode() {
+ return mode;
+ }
+
+ /**
+ * Get the value set in {@link SessionParams#setInstallLocation(int)}.
+ */
+ public int getInstallLocation() {
+ return installLocation;
+ }
+
+ /**
+ * Get the value as set in {@link SessionParams#setSize(long)}.
+ *
+ * <p>The value is a hint and does not have to match the actual size.
+ */
+ public long getSize() {
+ return sizeBytes;
+ }
+
+ /**
+ * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}.
+ */
+ public @Nullable Uri getOriginatingUri() {
+ return originatingUri;
+ }
+
+ /**
+ * Get the value set in {@link SessionParams#setOriginatingUid(int)}.
+ */
+ public int getOriginatingUid() {
+ return originatingUid;
+ }
+
+ /**
+ * Get the value set in {@link SessionParams#setReferrerUri(Uri)}
+ */
+ public @Nullable Uri getReferrerUri() {
+ return referrerUri;
+ }
+
+ /**
+ * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @Nullable String[] getGrantedRuntimePermissions() {
+ return grantedRuntimePermissions;
+ }
+
+ /**
+ * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean getAllowDowngrade() {
+ return (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
+ }
+
+ /**
+ * Get the value set in {@link SessionParams#setDontKillApp(boolean)}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean getDontKillApp() {
+ return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0;
+ }
+
+ /**
+ * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code true},
+ * return true. If it was called with {@code false} or if it was not called return false.
+ *
+ * @hide
+ *
+ * @see #getInstallAsFullApp
+ */
+ @SystemApi
+ public boolean getInstallAsInstantApp(boolean isInstantApp) {
+ return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
+ }
+
+ /**
+ * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code false},
+ * return true. If it was called with {@code true} or if it was not called return false.
+ *
+ * @hide
+ *
+ * @see #getInstallAsInstantApp
+ */
+ @SystemApi
+ public boolean getInstallAsFullApp(boolean isInstantApp) {
+ return (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
+ }
+
+ /**
+ * Get if {@link SessionParams#setInstallAsVirtualPreload()} was called.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean getInstallAsVirtualPreload() {
+ return (installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0;
+ }
+
+ /**
+ * Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean getAllocateAggressive() {
+ return (installFlags & PackageManager.INSTALL_ALLOCATE_AGGRESSIVE) != 0;
+ }
+
+
/** {@hide} */
@Deprecated
public @Nullable Intent getDetailsIntent() {
@@ -1529,6 +1693,13 @@
dest.writeString(appPackageName);
dest.writeParcelable(appIcon, flags);
dest.writeString(appLabel != null ? appLabel.toString() : null);
+
+ dest.writeInt(installLocation);
+ dest.writeParcelable(originatingUri, flags);
+ dest.writeInt(originatingUid);
+ dest.writeParcelable(referrerUri, flags);
+ dest.writeStringArray(grantedRuntimePermissions);
+ dest.writeInt(installFlags);
}
public static final Parcelable.Creator<SessionInfo>
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 2655b1c..0fd696f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -388,6 +388,13 @@
info.appIcon = params.appIcon;
}
info.appLabel = params.appLabel;
+
+ info.installLocation = params.installLocation;
+ info.originatingUri = params.originatingUri;
+ info.originatingUid = params.originatingUid;
+ info.referrerUri = params.referrerUri;
+ info.grantedRuntimePermissions = params.grantedRuntimePermissions;
+ info.installFlags = params.installFlags;
}
return info;
}
@@ -760,6 +767,12 @@
params.appPackageName, PackageManager.GET_SIGNATURES
| PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
+ // Only install flags that can be verified by the app the session is transferred to are
+ // allowed. The parameters can be read via PackageInstaller.SessionInfo.
+ if (!params.areHiddenOptionsSet()) {
+ throw new SecurityException("Can only transfer sessions that use public options");
+ }
+
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
assertPreparedAndNotSealedLocked("transfer");