Merge "API Update: extra_is_bubbled -> Activity#isLaunchedFromBubble" into sc-dev

This commit is contained in:
Mady Mellor
2021-04-12 14:53:01 +00:00
committed by Android (Google) Code Review
15 changed files with 107 additions and 37 deletions

View File

@@ -3960,6 +3960,7 @@ package android.app {
method public boolean isImmersive(); method public boolean isImmersive();
method public boolean isInMultiWindowMode(); method public boolean isInMultiWindowMode();
method public boolean isInPictureInPictureMode(); method public boolean isInPictureInPictureMode();
method public boolean isLaunchedFromBubble();
method public boolean isLocalVoiceInteractionSupported(); method public boolean isLocalVoiceInteractionSupported();
method public boolean isTaskRoot(); method public boolean isTaskRoot();
method public boolean isVoiceInteraction(); method public boolean isVoiceInteraction();
@@ -11222,7 +11223,6 @@ package android.content {
field public static final String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS"; field public static final String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
field public static final String EXTRA_INSTALLER_PACKAGE_NAME = "android.intent.extra.INSTALLER_PACKAGE_NAME"; field public static final String EXTRA_INSTALLER_PACKAGE_NAME = "android.intent.extra.INSTALLER_PACKAGE_NAME";
field public static final String EXTRA_INTENT = "android.intent.extra.INTENT"; field public static final String EXTRA_INTENT = "android.intent.extra.INTENT";
field public static final String EXTRA_IS_BUBBLED = "android.intent.extra.IS_BUBBLED";
field public static final String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT"; field public static final String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
field public static final String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY"; field public static final String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
field public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID"; field public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID";

View File

@@ -137,6 +137,7 @@ package android.app {
method public void setLaunchActivityType(int); method public void setLaunchActivityType(int);
method public void setLaunchTaskId(int); method public void setLaunchTaskId(int);
method public void setLaunchWindowingMode(int); method public void setLaunchWindowingMode(int);
method public void setLaunchedFromBubble(boolean);
method public void setTaskAlwaysOnTop(boolean); method public void setTaskAlwaysOnTop(boolean);
method public void setTaskOverlay(boolean, boolean); method public void setTaskOverlay(boolean, boolean);
} }

View File

@@ -899,6 +899,9 @@ public class Activity extends ContextThemeWrapper
/** The options for scene transition. */ /** The options for scene transition. */
ActivityOptions mPendingOptions; ActivityOptions mPendingOptions;
/** Whether this activity was launched from a bubble. **/
boolean mLaunchedFromBubble;
private static final class ManagedCursor { private static final class ManagedCursor {
ManagedCursor(Cursor cursor) { ManagedCursor(Cursor cursor) {
mCursor = cursor; mCursor = cursor;
@@ -6790,6 +6793,25 @@ public class Activity extends ContextThemeWrapper
return getSharedPreferences(getLocalClassName(), mode); return getSharedPreferences(getLocalClassName(), mode);
} }
/**
* Indicates whether this activity is launched from a bubble. A bubble is a floating shortcut
* on the screen that expands to show an activity.
*
* If your activity can be used normally or as a bubble, you might use this method to check
* if the activity is bubbled to modify any behaviour that might be different between the
* normal activity and the bubbled activity. For example, if you normally cancel the
* notification associated with the activity when you open the activity, you might not want to
* do that when you're bubbled as that would remove the bubble.
*
* @return {@code true} if the activity is launched from a bubble.
*
* @see Notification.Builder#setBubbleMetadata(Notification.BubbleMetadata)
* @see Notification.BubbleMetadata.Builder#Builder(String)
*/
public boolean isLaunchedFromBubble() {
return mLaunchedFromBubble;
}
private void ensureSearchManager() { private void ensureSearchManager() {
if (mSearchManager != null) { if (mSearchManager != null) {
return; return;

View File

@@ -323,6 +323,9 @@ public class ActivityOptions {
/** See {@link #setRemoveWithTaskOrganizer(boolean)}. */ /** See {@link #setRemoveWithTaskOrganizer(boolean)}. */
private static final String KEY_REMOVE_WITH_TASK_ORGANIZER = private static final String KEY_REMOVE_WITH_TASK_ORGANIZER =
"android.activity.removeWithTaskOrganizer"; "android.activity.removeWithTaskOrganizer";
/** See {@link #setLaunchedFromBubble(boolean)}. */
private static final String KEY_LAUNCHED_FROM_BUBBLE =
"android.activity.launchTypeBubble";
/** /**
* @see #setLaunchCookie * @see #setLaunchCookie
@@ -410,6 +413,7 @@ public class ActivityOptions {
private boolean mOverrideTaskTransition; private boolean mOverrideTaskTransition;
private int mSplashScreenThemeResId; private int mSplashScreenThemeResId;
private boolean mRemoveWithTaskOrganizer; private boolean mRemoveWithTaskOrganizer;
private boolean mLaunchedFromBubble;
/** /**
* Create an ActivityOptions specifying a custom animation to run when * Create an ActivityOptions specifying a custom animation to run when
@@ -1161,6 +1165,7 @@ public class ActivityOptions {
mOverrideTaskTransition = opts.getBoolean(KEY_OVERRIDE_TASK_TRANSITION); mOverrideTaskTransition = opts.getBoolean(KEY_OVERRIDE_TASK_TRANSITION);
mSplashScreenThemeResId = opts.getInt(KEY_SPLASH_SCREEN_THEME); mSplashScreenThemeResId = opts.getInt(KEY_SPLASH_SCREEN_THEME);
mRemoveWithTaskOrganizer = opts.getBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER); mRemoveWithTaskOrganizer = opts.getBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER);
mLaunchedFromBubble = opts.getBoolean(KEY_LAUNCHED_FROM_BUBBLE);
} }
/** /**
@@ -1646,6 +1651,23 @@ public class ActivityOptions {
return mRemoveWithTaskOrganizer; return mRemoveWithTaskOrganizer;
} }
/**
* Sets whether this activity is launched from a bubble.
* @hide
*/
@TestApi
public void setLaunchedFromBubble(boolean fromBubble) {
mLaunchedFromBubble = fromBubble;
}
/**
* @return whether the activity was launched from a bubble.
* @hide
*/
public boolean getLaunchedFromBubble() {
return mLaunchedFromBubble;
}
/** /**
* Update the current values in this ActivityOptions from those supplied * Update the current values in this ActivityOptions from those supplied
* in <var>otherOptions</var>. Any values * in <var>otherOptions</var>. Any values
@@ -1883,6 +1905,9 @@ public class ActivityOptions {
if (mRemoveWithTaskOrganizer) { if (mRemoveWithTaskOrganizer) {
b.putBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER, mRemoveWithTaskOrganizer); b.putBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER, mRemoveWithTaskOrganizer);
} }
if (mLaunchedFromBubble) {
b.putBoolean(KEY_LAUNCHED_FROM_BUBBLE, mLaunchedFromBubble);
}
return b; return b;
} }

View File

@@ -594,6 +594,9 @@ public final class ActivityThread extends ClientTransactionHandler
*/ */
FixedRotationAdjustments mPendingFixedRotationAdjustments; FixedRotationAdjustments mPendingFixedRotationAdjustments;
/** Whether this activiy was launched from a bubble. */
boolean mLaunchedFromBubble;
@LifecycleState @LifecycleState
private int mLifecycleState = PRE_ON_CREATE; private int mLifecycleState = PRE_ON_CREATE;
@@ -613,7 +616,7 @@ public final class ActivityThread extends ClientTransactionHandler
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions, List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client, boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client,
IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments, IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments,
IBinder shareableActivityToken) { IBinder shareableActivityToken, boolean launchedFromBubble) {
this.token = token; this.token = token;
this.assistToken = assistToken; this.assistToken = assistToken;
this.shareableActivityToken = shareableActivityToken; this.shareableActivityToken = shareableActivityToken;
@@ -634,6 +637,7 @@ public final class ActivityThread extends ClientTransactionHandler
compatInfo); compatInfo);
mActivityOptions = activityOptions; mActivityOptions = activityOptions;
mPendingFixedRotationAdjustments = fixedRotationAdjustments; mPendingFixedRotationAdjustments = fixedRotationAdjustments;
mLaunchedFromBubble = launchedFromBubble;
init(); init();
} }
@@ -3549,6 +3553,7 @@ public final class ActivityThread extends ClientTransactionHandler
activity.mPendingOptions = r.mActivityOptions; activity.mPendingOptions = r.mActivityOptions;
r.mActivityOptions = null; r.mActivityOptions = null;
} }
activity.mLaunchedFromBubble = r.mLaunchedFromBubble;
activity.mCalled = false; activity.mCalled = false;
if (r.isPersistable()) { if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);

View File

@@ -10205,13 +10205,8 @@ public class Notification implements Parcelable
* <p>The shortcut activity will be used when the bubble is expanded. This will display * <p>The shortcut activity will be used when the bubble is expanded. This will display
* the shortcut activity in a floating window over the existing foreground activity.</p> * the shortcut activity in a floating window over the existing foreground activity.</p>
* *
* <p>When the shortcut is displayed in a bubble, there will be an intent * <p>When the activity is launched from a bubble,
* extra set on the activity, {@link Intent#EXTRA_IS_BUBBLED} * {@link Activity#isLaunchedFromBubble()} will return with {@code true}.
* with {@code true}. You may check this in the onCreate of your activity via:
*
* <pre class="prettyprint">
* boolean isBubbled = getIntent().getBooleanExtra(Intent.EXTRA_IS_BUBBLED, false);
* </pre>
* </p> * </p>
* *
* <p>If the shortcut has not been published when the bubble notification is sent, * <p>If the shortcut has not been published when the bubble notification is sent,
@@ -10242,13 +10237,8 @@ public class Notification implements Parcelable
* app content in a floating window over the existing foreground activity. The intent * app content in a floating window over the existing foreground activity. The intent
* should point to a resizable activity. </p> * should point to a resizable activity. </p>
* *
* <p>When the activity is displayed in a bubble, there will be an intent * <p>When the activity is launched from a bubble,
* extra set on the activity, {@link Intent#EXTRA_IS_BUBBLED} * {@link Activity#isLaunchedFromBubble()} will return with {@code true}.
* with {@code true}. You may check this in the onCreate of your activity via:
*
* <pre class="prettyprint">
* boolean isBubbled = getIntent().getBooleanExtra(Intent.EXTRA_IS_BUBBLED, false);
* </pre>
* </p> * </p>
* *
* @throws NullPointerException if intent is null. * @throws NullPointerException if intent is null.

View File

@@ -72,6 +72,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
private ProfilerInfo mProfilerInfo; private ProfilerInfo mProfilerInfo;
private IBinder mAssistToken; private IBinder mAssistToken;
private IBinder mShareableActivityToken; private IBinder mShareableActivityToken;
private boolean mLaunchedFromBubble;
/** /**
* It is only non-null if the process is the first time to launch activity. It is only an * It is only non-null if the process is the first time to launch activity. It is only an
* optimization for quick look up of the interface so the field is ignored for comparison. * optimization for quick look up of the interface so the field is ignored for comparison.
@@ -96,7 +97,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo, ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo, mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken); client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken,
mLaunchedFromBubble);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */); client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
} }
@@ -120,7 +122,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions, List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken, boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
IActivityClientController activityClientController, IActivityClientController activityClientController,
FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken) { FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken,
boolean launchedFromBubble) {
LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class); LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
if (instance == null) { if (instance == null) {
instance = new LaunchActivityItem(); instance = new LaunchActivityItem();
@@ -128,7 +131,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer, setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer,
voiceInteractor, procState, state, persistentState, pendingResults, voiceInteractor, procState, state, persistentState, pendingResults,
pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken, pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken,
activityClientController, fixedRotationAdjustments, shareableActivityToken); activityClientController, fixedRotationAdjustments, shareableActivityToken,
launchedFromBubble);
return instance; return instance;
} }
@@ -136,7 +140,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
@Override @Override
public void recycle() { public void recycle() {
setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null, setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null,
null, false, null, null, null, null, null); null, false, null, null, null, null, null, false);
ObjectPool.recycle(this); ObjectPool.recycle(this);
} }
@@ -166,6 +170,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
dest.writeStrongInterface(mActivityClientController); dest.writeStrongInterface(mActivityClientController);
dest.writeTypedObject(mFixedRotationAdjustments, flags); dest.writeTypedObject(mFixedRotationAdjustments, flags);
dest.writeStrongBinder(mShareableActivityToken); dest.writeStrongBinder(mShareableActivityToken);
dest.writeBoolean(mLaunchedFromBubble);
} }
/** Read from Parcel. */ /** Read from Parcel. */
@@ -183,7 +188,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
in.readTypedObject(ProfilerInfo.CREATOR), in.readTypedObject(ProfilerInfo.CREATOR),
in.readStrongBinder(), in.readStrongBinder(),
IActivityClientController.Stub.asInterface(in.readStrongBinder()), IActivityClientController.Stub.asInterface(in.readStrongBinder()),
in.readTypedObject(FixedRotationAdjustments.CREATOR), in.readStrongBinder()); in.readTypedObject(FixedRotationAdjustments.CREATOR), in.readStrongBinder(),
in.readBoolean());
} }
public static final @NonNull Creator<LaunchActivityItem> CREATOR = public static final @NonNull Creator<LaunchActivityItem> CREATOR =
@@ -293,7 +299,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo, ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo,
IBinder assistToken, IActivityClientController activityClientController, IBinder assistToken, IActivityClientController activityClientController,
FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken) { FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken,
boolean launchedFromBubble) {
instance.mIntent = intent; instance.mIntent = intent;
instance.mIdent = ident; instance.mIdent = ident;
instance.mInfo = info; instance.mInfo = info;
@@ -314,5 +321,6 @@ public class LaunchActivityItem extends ClientTransactionItem {
instance.mActivityClientController = activityClientController; instance.mActivityClientController = activityClientController;
instance.mFixedRotationAdjustments = fixedRotationAdjustments; instance.mFixedRotationAdjustments = fixedRotationAdjustments;
instance.mShareableActivityToken = shareableActivityToken; instance.mShareableActivityToken = shareableActivityToken;
instance.mLaunchedFromBubble = launchedFromBubble;
} }
} }

View File

@@ -6177,16 +6177,6 @@ public class Intent implements Parcelable, Cloneable {
*/ */
public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON"; public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON";
/**
* A boolean extra indicating whether an activity is bubbled. Set on the shortcut or
* pending intent provided for the bubble. If the extra is not present or false, then it is not
* bubbled.
*
* @see android.app.Notification.Builder#setBubbleMetadata(Notification.BubbleMetadata)
* @see android.app.Notification.BubbleMetadata.Builder#Builder(String)
*/
public static final String EXTRA_IS_BUBBLED = "android.intent.extra.IS_BUBBLED";
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Intent flags (see mFlags variable). // Intent flags (see mFlags variable).

View File

@@ -111,6 +111,7 @@ class TestUtils {
private IBinder mAssistToken; private IBinder mAssistToken;
private IBinder mShareableActivityToken; private IBinder mShareableActivityToken;
private FixedRotationAdjustments mFixedRotationAdjustments; private FixedRotationAdjustments mFixedRotationAdjustments;
private boolean mLaunchedFromBubble;
LaunchActivityItemBuilder setIntent(Intent intent) { LaunchActivityItemBuilder setIntent(Intent intent) {
mIntent = intent; mIntent = intent;
@@ -207,13 +208,18 @@ class TestUtils {
return this; return this;
} }
LaunchActivityItemBuilder setLaunchedFromBubble(boolean launchedFromBubble) {
mLaunchedFromBubble = launchedFromBubble;
return this;
}
LaunchActivityItem build() { LaunchActivityItem build() {
return LaunchActivityItem.obtain(mIntent, mIdent, mInfo, return LaunchActivityItem.obtain(mIntent, mIdent, mInfo,
mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor,
mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents, mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents,
mActivityOptions, mIsForward, mProfilerInfo, mAssistToken, mActivityOptions, mIsForward, mProfilerInfo, mAssistToken,
null /* activityClientController */, mFixedRotationAdjustments, null /* activityClientController */, mFixedRotationAdjustments,
mShareableActivityToken); mShareableActivityToken, mLaunchedFromBubble);
} }
} }
} }

View File

@@ -298,7 +298,8 @@ public class ActivityThreadClientTest {
null /* pendingResults */, null /* pendingNewIntents */, null /* pendingResults */, null /* pendingNewIntents */,
null /* activityOptions */, true /* isForward */, null /* profilerInfo */, null /* activityOptions */, true /* isForward */, null /* profilerInfo */,
mThread /* client */, null /* asssitToken */, mThread /* client */, null /* asssitToken */,
null /* fixedRotationAdjustments */, null /* shareableActivityToken */); null /* fixedRotationAdjustments */, null /* shareableActivityToken */,
false /* launchedFromBubble */);
} }
@Override @Override

View File

@@ -154,6 +154,7 @@ public class BubbleExpandedView extends LinearLayout {
} }
try { try {
options.setTaskAlwaysOnTop(true); options.setTaskAlwaysOnTop(true);
options.setLaunchedFromBubble(true);
if (!mIsOverflow && mBubble.hasMetadataShortcutId()) { if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
options.setApplyActivityFlagsForBubbles(true); options.setApplyActivityFlagsForBubbles(true);
mTaskView.startShortcutActivity(mBubble.getShortcutInfo(), mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
@@ -163,7 +164,6 @@ public class BubbleExpandedView extends LinearLayout {
// Apply flags to make behaviour match documentLaunchMode=always. // Apply flags to make behaviour match documentLaunchMode=always.
fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT); fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
fillInIntent.putExtra(Intent.EXTRA_IS_BUBBLED, true);
if (mBubble != null) { if (mBubble != null) {
mBubble.setIntentActive(); mBubble.setIntentActive();
} }

View File

@@ -978,7 +978,6 @@ public class LauncherAppsService extends SystemService {
// Flag for bubble to make behaviour match documentLaunchMode=always. // Flag for bubble to make behaviour match documentLaunchMode=always.
intents[0].addFlags(FLAG_ACTIVITY_NEW_DOCUMENT); intents[0].addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
intents[0].putExtra(Intent.EXTRA_IS_BUBBLED, true);
} }
intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

View File

@@ -561,6 +561,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// The locusId associated with this activity, if set. // The locusId associated with this activity, if set.
private LocusId mLocusId; private LocusId mLocusId;
// Whether the activity was launched from a bubble.
private boolean mLaunchedFromBubble;
private SizeConfigurationBuckets mSizeConfigurations; private SizeConfigurationBuckets mSizeConfigurations;
/** /**
@@ -4218,7 +4221,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
} }
} }
boolean getLaunchedFromBubble() {
return mLaunchedFromBubble;
}
private void setOptions(@NonNull ActivityOptions options) { private void setOptions(@NonNull ActivityOptions options) {
mLaunchedFromBubble = options.getLaunchedFromBubble();
mPendingOptions = options; mPendingOptions = options;
if (options.getAnimationType() == ANIM_REMOTE_ANIMATION) { if (options.getAnimationType() == ANIM_REMOTE_ANIMATION) {
mPendingRemoteAnimation = options.getRemoteAnimationAdapter(); mPendingRemoteAnimation = options.getRemoteAnimationAdapter();

View File

@@ -826,7 +826,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
r.getSavedState(), r.getPersistentSavedState(), results, newIntents, r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
r.takeOptions(), dc.isNextTransitionForward(), r.takeOptions(), dc.isNextTransitionForward(),
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController, proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken)); r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken,
r.getLaunchedFromBubble()));
// Set desired final state. // Set desired final state.
final ActivityLifecycleItem lifecycleItem; final ActivityLifecycleItem lifecycleItem;

View File

@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.Manifest.permission.STATUS_BAR_SERVICE;
import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -278,6 +279,19 @@ public class SafeActivityOptions {
Slog.w(TAG, msg); Slog.w(TAG, msg);
throw new SecurityException(msg); throw new SecurityException(msg);
} }
// If launched from bubble is specified, then ensure that the caller is system or sysui.
if (options.getLaunchedFromBubble() && callingUid != Process.SYSTEM_UID) {
final int statusBarPerm = ActivityTaskManagerService.checkPermission(
STATUS_BAR_SERVICE, callingPid, callingUid);
if (statusBarPerm == PERMISSION_DENIED) {
final String msg = "Permission Denial: starting " + getIntentString(intent)
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ") with launchedFromBubble=true";
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
}
} }
private String getIntentString(Intent intent) { private String getIntentString(Intent intent) {