diff --git a/api/current.txt b/api/current.txt index eeeb74a4d3a3f..90dca32414124 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4030,6 +4030,7 @@ package android.app { method public static android.app.ActivityOptions makeTaskLaunchBehind(); method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int); method public void requestUsageTimeReport(android.app.PendingIntent); + method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle); method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect); method public android.app.ActivityOptions setLaunchDisplayId(int); method public android.os.Bundle toBundle(); diff --git a/api/system-current.txt b/api/system-current.txt index 5395d02a32a61..4a6d6ad480325 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4179,6 +4179,7 @@ package android.app { method public static android.app.ActivityOptions makeTaskLaunchBehind(); method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int); method public void requestUsageTimeReport(android.app.PendingIntent); + method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle); method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect); method public android.app.ActivityOptions setLaunchDisplayId(int); method public android.os.Bundle toBundle(); diff --git a/api/test-current.txt b/api/test-current.txt index 4c53dc818c43e..e50fdde2d881a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4040,6 +4040,7 @@ package android.app { method public static android.app.ActivityOptions makeTaskLaunchBehind(); method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int); method public void requestUsageTimeReport(android.app.PendingIntent); + method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle); method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect); method public android.app.ActivityOptions setLaunchDisplayId(int); method public void setLaunchStackId(int); diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 63e8cc641ce98..3eec596fcb174 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -211,6 +211,9 @@ public class ActivityOptions { private static final String KEY_USAGE_TIME_REPORT = "android:activity.usageTimeReport"; private static final String KEY_ROTATION_ANIMATION_HINT = "android:activity.rotationAnimationHint"; + private static final String KEY_INSTANT_APP_VERIFICATION_BUNDLE + = "android:instantapps.installerbundle"; + /** @hide */ public static final int ANIM_NONE = 0; /** @hide */ @@ -264,6 +267,7 @@ public class ActivityOptions { private boolean mTaskOverlayCanResume; private AppTransitionAnimationSpec mAnimSpecs[]; private int mRotationAnimationHint = -1; + private Bundle mAppVerificationBundle; /** * Create an ActivityOptions specifying a custom animation to run when @@ -886,6 +890,7 @@ public class ActivityOptions { opts.getBinder(KEY_ANIMATION_FINISHED_LISTENER)); } mRotationAnimationHint = opts.getInt(KEY_ROTATION_ANIMATION_HINT); + mAppVerificationBundle = opts.getBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE); } /** @@ -1275,6 +1280,9 @@ public class ActivityOptions { b.putBinder(KEY_ANIMATION_FINISHED_LISTENER, mAnimationFinishedListener.asBinder()); } b.putInt(KEY_ROTATION_ANIMATION_HINT, mRotationAnimationHint); + if (mAppVerificationBundle != null) { + b.putBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE, mAppVerificationBundle); + } return b; } @@ -1342,6 +1350,30 @@ public class ActivityOptions { mRotationAnimationHint = hint; } + /** + * Pop the extra verification bundle for the installer. + * This removes the bundle from the ActivityOptions to make sure the installer bundle + * is only available once. + * @hide + */ + public Bundle popAppVerificationBundle() { + Bundle out = mAppVerificationBundle; + mAppVerificationBundle = null; + return out; + } + + /** + * Set the {@link Bundle} that is provided to the app installer for additional verification + * if the call to {@link Context#startActivity} results in an app being installed. + * + * This Bundle is not provided to any other app besides the installer. + */ + public ActivityOptions setAppVerificationBundle(Bundle bundle) { + mAppVerificationBundle = bundle; + return this; + + } + /** @hide */ @Override public String toString() { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 5f7947fea3332..737ccf269a92b 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -4421,6 +4421,21 @@ public class Intent implements Parcelable, Cloneable { */ public static final String EXTRA_VERSION_CODE = "android.intent.extra.VERSION_CODE"; + /** + * The app that triggered the ephemeral installation. + * @hide + */ + public static final String EXTRA_CALLING_PACKAGE + = "android.intent.extra.CALLING_PACKAGE"; + + /** + * Optional calling app provided bundle containing additional launch information the + * installer may use. + * @hide + */ + public static final String EXTRA_VERIFICATION_BUNDLE + = "android.intent.extra.VERIFICATION_BUNDLE"; + /** * A Bundle forming a mapping of potential target package names to different extras Bundles * to add to the default intent extras in {@link #EXTRA_INTENT} when used with diff --git a/core/java/android/content/pm/InstantAppRequest.java b/core/java/android/content/pm/InstantAppRequest.java index b45169d324be6..27d28287b6ae3 100644 --- a/core/java/android/content/pm/InstantAppRequest.java +++ b/core/java/android/content/pm/InstantAppRequest.java @@ -17,6 +17,7 @@ package android.content.pm; import android.content.Intent; +import android.os.Bundle; /** * Information needed to make an instant application resolution request. @@ -33,13 +34,18 @@ public final class InstantAppRequest { public final String callingPackage; /** ID of the user requesting the instant application */ public final int userId; + /** + * Optional extra bundle provided by the source application to the installer for additional + * verification. */ + public final Bundle verificationBundle; public InstantAppRequest(AuxiliaryResolveInfo responseObj, Intent origIntent, - String resolvedType, String callingPackage, int userId) { + String resolvedType, String callingPackage, int userId, Bundle verificationBundle) { this.responseObj = responseObj; this.origIntent = origIntent; this.resolvedType = resolvedType; this.callingPackage = callingPackage; this.userId = userId; + this.verificationBundle = verificationBundle; } -} \ No newline at end of file +} diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 7bfde751e1559..8e34728efcb16 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -19,6 +19,7 @@ package android.content.pm; import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; import android.util.SparseArray; import java.util.List; @@ -215,11 +216,13 @@ public abstract class PackageManagerInternal { * @param origIntent The original intent that triggered ephemeral resolution * @param resolvedType The resolved type of the intent * @param callingPackage The name of the package requesting the ephemeral application + * @param verificationBundle Optional bundle to pass to the installer for additional + * verification * @param userId The ID of the user that triggered ephemeral resolution */ public abstract void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, Intent origIntent, String resolvedType, String callingPackage, - int userId); + Bundle verificationBundle, int userId); /** * Grants access to the package metadata for an ephemeral application. diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 1f4b21b14ed59..ca842d5574d32 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -245,6 +245,9 @@ class ActivityStarter { ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask) { int err = ActivityManager.START_SUCCESS; + // Pull the optional Ephemeral Installer-only bundle out of the options early. + final Bundle verificationBundle + = options != null ? options.popAppVerificationBundle() : null; ProcessRecord callerApp = null; if (caller != null) { @@ -466,7 +469,7 @@ class ActivityStarter { // app [on install success]. if (rInfo != null && rInfo.auxiliaryInfo != null) { intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent, - callingPackage, resolvedType, userId); + callingPackage, verificationBundle, resolvedType, userId); resolvedType = null; callingUid = realCallingUid; callingPid = realCallingPid; @@ -522,14 +525,16 @@ class ActivityStarter { * Creates a launch intent for the given auxiliary resolution data. */ private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse, - Intent originalIntent, String callingPackage, String resolvedType, int userId) { + Intent originalIntent, String callingPackage, Bundle verificationBundle, + String resolvedType, int userId) { if (auxiliaryResponse.needsPhaseTwo) { // request phase two resolution mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo( - auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId); + auxiliaryResponse, originalIntent, resolvedType, callingPackage, + verificationBundle, userId); } return InstantAppResolver.buildEphemeralInstallerIntent(originalIntent, - callingPackage, resolvedType, userId, auxiliaryResponse.packageName, + callingPackage, verificationBundle, resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName, auxiliaryResponse.versionCode, auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo); } diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java index b56db047fd302..624d8c9ef13ea 100644 --- a/services/core/java/com/android/server/pm/InstantAppResolver.java +++ b/services/core/java/com/android/server/pm/InstantAppResolver.java @@ -41,6 +41,7 @@ import android.content.pm.InstantAppResolveInfo.InstantAppDigest; import android.metrics.LogMaker; import android.os.Binder; import android.os.Build; +import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; import android.util.Log; @@ -147,6 +148,7 @@ public abstract class InstantAppResolver { final Intent installerIntent = buildEphemeralInstallerIntent( requestObj.origIntent, requestObj.callingPackage, + requestObj.verificationBundle, requestObj.resolvedType, requestObj.userId, packageName, @@ -172,6 +174,7 @@ public abstract class InstantAppResolver { */ public static Intent buildEphemeralInstallerIntent(@NonNull Intent origIntent, @NonNull String callingPackage, + @Nullable Bundle verificationBundle, @NonNull String resolvedType, int userId, @NonNull String instantAppPackageName, @@ -234,6 +237,10 @@ public abstract class InstantAppResolver { intent.putExtra(Intent.EXTRA_PACKAGE_NAME, instantAppPackageName); intent.putExtra(Intent.EXTRA_SPLIT_NAME, instantAppSplitName); intent.putExtra(Intent.EXTRA_VERSION_CODE, versionCode); + intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage); + if (verificationBundle != null) { + intent.putExtra(Intent.EXTRA_VERIFICATION_BUNDLE, verificationBundle); + } } return intent; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 53fe2cab35060..28c88fa4eafb9 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -5820,10 +5820,10 @@ public class PackageManagerService extends IPackageManager.Stub private void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, Intent origIntent, String resolvedType, String callingPackage, - int userId) { + Bundle verificationBundle, int userId) { final Message msg = mHandler.obtainMessage(INSTANT_APP_RESOLUTION_PHASE_TWO, new InstantAppRequest(responseObj, origIntent, resolvedType, - callingPackage, userId)); + callingPackage, userId, verificationBundle)); mHandler.sendMessage(msg); } @@ -6372,7 +6372,7 @@ public class PackageManagerService extends IPackageManager.Stub Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral"); final InstantAppRequest requestObject = new InstantAppRequest( null /*responseObj*/, intent /*origIntent*/, resolvedType, - null /*callingPackage*/, userId); + null /*callingPackage*/, userId, null /*verificationBundle*/); final AuxiliaryResolveInfo auxiliaryResponse = InstantAppResolver.doInstantAppResolutionPhaseOne( mContext, mInstantAppResolverConnection, requestObject); @@ -23423,9 +23423,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); @Override public void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj, - Intent origIntent, String resolvedType, String callingPackage, int userId) { + Intent origIntent, String resolvedType, String callingPackage, + Bundle verificationBundle, int userId) { PackageManagerService.this.requestInstantAppResolutionPhaseTwo( - responseObj, origIntent, resolvedType, callingPackage, userId); + responseObj, origIntent, resolvedType, callingPackage, verificationBundle, + userId); } @Override