Sending TaskFragment token to client for the launching activity
Activity#onCreate is called before receiving the TaskFragment appeared event in the client process. So, the client split controller created another split and resulted in unexpected behaviors. Bug: 194860679 Test: start activity to side Test: wm presubmit Change-Id: Iac34bd39376940c5c0224c8687ad9858a4190e20
This commit is contained in:
@@ -530,6 +530,8 @@ public final class ActivityThread extends ClientTransactionHandler
|
||||
// A reusable token for other purposes, e.g. content capture, translation. It shouldn't be
|
||||
// used without security checks
|
||||
public IBinder shareableActivityToken;
|
||||
// The token of the TaskFragment that embedded this activity.
|
||||
@Nullable public IBinder mTaskFragmentToken;
|
||||
int ident;
|
||||
@UnsupportedAppUsage
|
||||
Intent intent;
|
||||
@@ -623,7 +625,8 @@ public final class ActivityThread extends ClientTransactionHandler
|
||||
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
|
||||
boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client,
|
||||
IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments,
|
||||
IBinder shareableActivityToken, boolean launchedFromBubble) {
|
||||
IBinder shareableActivityToken, boolean launchedFromBubble,
|
||||
IBinder taskFragmentToken) {
|
||||
this.token = token;
|
||||
this.assistToken = assistToken;
|
||||
this.shareableActivityToken = shareableActivityToken;
|
||||
@@ -645,6 +648,7 @@ public final class ActivityThread extends ClientTransactionHandler
|
||||
mActivityOptions = activityOptions;
|
||||
mPendingFixedRotationAdjustments = fixedRotationAdjustments;
|
||||
mLaunchedFromBubble = launchedFromBubble;
|
||||
mTaskFragmentToken = taskFragmentToken;
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
|
||||
private IBinder mAssistToken;
|
||||
private IBinder mShareableActivityToken;
|
||||
private boolean mLaunchedFromBubble;
|
||||
private IBinder mTaskFragmentToken;
|
||||
/**
|
||||
* 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.
|
||||
@@ -86,7 +87,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
|
||||
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
|
||||
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
|
||||
client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken,
|
||||
mLaunchedFromBubble);
|
||||
mLaunchedFromBubble, mTaskFragmentToken);
|
||||
client.addLaunchingActivity(token, r);
|
||||
client.updateProcessState(mProcState, false);
|
||||
client.updatePendingConfiguration(mCurConfig);
|
||||
@@ -124,7 +125,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
|
||||
boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
|
||||
IActivityClientController activityClientController,
|
||||
FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken,
|
||||
boolean launchedFromBubble) {
|
||||
boolean launchedFromBubble, IBinder taskFragmentToken) {
|
||||
LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
|
||||
if (instance == null) {
|
||||
instance = new LaunchActivityItem();
|
||||
@@ -133,7 +134,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
|
||||
voiceInteractor, procState, state, persistentState, pendingResults,
|
||||
pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken,
|
||||
activityClientController, fixedRotationAdjustments, shareableActivityToken,
|
||||
launchedFromBubble);
|
||||
launchedFromBubble, taskFragmentToken);
|
||||
|
||||
return instance;
|
||||
}
|
||||
@@ -141,7 +142,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
|
||||
@Override
|
||||
public void recycle() {
|
||||
setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null,
|
||||
null, false, null, null, null, null, null, false);
|
||||
null, false, null, null, null, null, null, false, null);
|
||||
ObjectPool.recycle(this);
|
||||
}
|
||||
|
||||
@@ -172,6 +173,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
|
||||
dest.writeTypedObject(mFixedRotationAdjustments, flags);
|
||||
dest.writeStrongBinder(mShareableActivityToken);
|
||||
dest.writeBoolean(mLaunchedFromBubble);
|
||||
dest.writeStrongBinder(mTaskFragmentToken);
|
||||
}
|
||||
|
||||
/** Read from Parcel. */
|
||||
@@ -190,7 +192,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
|
||||
in.readStrongBinder(),
|
||||
IActivityClientController.Stub.asInterface(in.readStrongBinder()),
|
||||
in.readTypedObject(FixedRotationAdjustments.CREATOR), in.readStrongBinder(),
|
||||
in.readBoolean());
|
||||
in.readBoolean(),
|
||||
in.readStrongBinder());
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<LaunchActivityItem> CREATOR =
|
||||
@@ -229,7 +232,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
|
||||
&& Objects.equals(mProfilerInfo, other.mProfilerInfo)
|
||||
&& Objects.equals(mAssistToken, other.mAssistToken)
|
||||
&& Objects.equals(mFixedRotationAdjustments, other.mFixedRotationAdjustments)
|
||||
&& Objects.equals(mShareableActivityToken, other.mShareableActivityToken);
|
||||
&& Objects.equals(mShareableActivityToken, other.mShareableActivityToken)
|
||||
&& Objects.equals(mTaskFragmentToken, other.mTaskFragmentToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -252,6 +256,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
|
||||
result = 31 * result + Objects.hashCode(mAssistToken);
|
||||
result = 31 * result + Objects.hashCode(mFixedRotationAdjustments);
|
||||
result = 31 * result + Objects.hashCode(mShareableActivityToken);
|
||||
result = 31 * result + Objects.hashCode(mTaskFragmentToken);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -301,7 +306,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
|
||||
ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo,
|
||||
IBinder assistToken, IActivityClientController activityClientController,
|
||||
FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken,
|
||||
boolean launchedFromBubble) {
|
||||
boolean launchedFromBubble, IBinder taskFragmentToken) {
|
||||
instance.mIntent = intent;
|
||||
instance.mIdent = ident;
|
||||
instance.mInfo = info;
|
||||
@@ -323,5 +328,6 @@ public class LaunchActivityItem extends ClientTransactionItem {
|
||||
instance.mFixedRotationAdjustments = fixedRotationAdjustments;
|
||||
instance.mShareableActivityToken = shareableActivityToken;
|
||||
instance.mLaunchedFromBubble = launchedFromBubble;
|
||||
instance.mTaskFragmentToken = taskFragmentToken;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,8 @@ public class ObjectPoolTests {
|
||||
.setProcState(procState).setState(bundle).setPersistentState(persistableBundle)
|
||||
.setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList())
|
||||
.setIsForward(true).setAssistToken(assistToken)
|
||||
.setShareableActivityToken(shareableActivityToken).build();
|
||||
.setShareableActivityToken(shareableActivityToken)
|
||||
.setTaskFragmentToken(new Binder()).build();
|
||||
|
||||
LaunchActivityItem emptyItem = new LaunchActivityItemBuilder().build();
|
||||
LaunchActivityItem item = itemSupplier.get();
|
||||
|
||||
@@ -112,6 +112,7 @@ class TestUtils {
|
||||
private IBinder mShareableActivityToken;
|
||||
private FixedRotationAdjustments mFixedRotationAdjustments;
|
||||
private boolean mLaunchedFromBubble;
|
||||
private IBinder mTaskFragmentToken;
|
||||
|
||||
LaunchActivityItemBuilder setIntent(Intent intent) {
|
||||
mIntent = intent;
|
||||
@@ -213,13 +214,18 @@ class TestUtils {
|
||||
return this;
|
||||
}
|
||||
|
||||
LaunchActivityItemBuilder setTaskFragmentToken(IBinder taskFragmentToken) {
|
||||
mTaskFragmentToken = taskFragmentToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
LaunchActivityItem build() {
|
||||
return LaunchActivityItem.obtain(mIntent, mIdent, mInfo,
|
||||
mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor,
|
||||
mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents,
|
||||
mActivityOptions, mIsForward, mProfilerInfo, mAssistToken,
|
||||
null /* activityClientController */, mFixedRotationAdjustments,
|
||||
mShareableActivityToken, mLaunchedFromBubble);
|
||||
mShareableActivityToken, mLaunchedFromBubble, mTaskFragmentToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,6 +209,7 @@ public class TransactionParcelTests {
|
||||
.setPendingNewIntents(referrerIntentList()).setIsForward(true)
|
||||
.setAssistToken(new Binder()).setFixedRotationAdjustments(fixedRotationAdjustments)
|
||||
.setShareableActivityToken(new Binder())
|
||||
.setTaskFragmentToken(new Binder())
|
||||
.build();
|
||||
|
||||
writeAndPrepareForReading(item);
|
||||
|
||||
@@ -299,7 +299,7 @@ public class ActivityThreadClientTest {
|
||||
null /* activityOptions */, true /* isForward */, null /* profilerInfo */,
|
||||
mThread /* client */, null /* asssitToken */,
|
||||
null /* fixedRotationAdjustments */, null /* shareableActivityToken */,
|
||||
false /* launchedFromBubble */);
|
||||
false /* launchedFromBubble */, null /* taskfragmentToken */);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -155,7 +155,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
|
||||
final List<ExtensionSplitRule> splitRules = getSplitRules();
|
||||
final TaskFragmentContainer currentContainer = getContainerWithActivity(
|
||||
launchedActivity.getActivityToken());
|
||||
launchedActivity.getActivityToken(), launchedActivity);
|
||||
|
||||
// Check if the activity is configured to always be expanded.
|
||||
if (shouldExpand(componentName, splitRules)) {
|
||||
@@ -247,9 +247,29 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
*/
|
||||
@Nullable
|
||||
TaskFragmentContainer getContainerWithActivity(@NonNull IBinder activityToken) {
|
||||
return getContainerWithActivity(activityToken, null /* activityToAdd */);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method can only be called from {@link #onActivityCreated(Activity)}, use
|
||||
* {@link #getContainerWithActivity(IBinder) } otherwise.
|
||||
*
|
||||
* Returns a container that this activity is registered with. The activity could be created
|
||||
* before the container appeared, adding the activity to the container if so.
|
||||
*/
|
||||
@Nullable
|
||||
private TaskFragmentContainer getContainerWithActivity(@NonNull IBinder activityToken,
|
||||
Activity activityToAdd) {
|
||||
final IBinder taskFragmentToken = ActivityThread.currentActivityThread().getActivityClient(
|
||||
activityToken).mTaskFragmentToken;
|
||||
for (TaskFragmentContainer container : mContainers) {
|
||||
if (container.hasActivity(activityToken)) {
|
||||
return container;
|
||||
} else if (container.getTaskFragmentToken().equals(taskFragmentToken)) {
|
||||
if (activityToAdd != null) {
|
||||
container.addPendingAppearedActivity(activityToAdd);
|
||||
}
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,10 +45,10 @@ class TaskFragmentContainer {
|
||||
private TaskFragmentInfo mInfo;
|
||||
|
||||
/**
|
||||
* Activity that is being reparented to this container, but haven't been added to {@link #mInfo}
|
||||
* yet.
|
||||
* Activities that are being reparented or being started to this container, but haven't been
|
||||
* added to {@link #mInfo} yet.
|
||||
*/
|
||||
private Activity mReparentingActivity;
|
||||
private final ArrayList<Activity> mPendingAppearedActivities = new ArrayList<>();
|
||||
|
||||
/** Containers that are dependent on this one and should be completely destroyed on exit. */
|
||||
private final List<TaskFragmentContainer> mContainersToFinishOnExit =
|
||||
@@ -71,7 +71,9 @@ class TaskFragmentContainer {
|
||||
*/
|
||||
TaskFragmentContainer(@Nullable Activity activity) {
|
||||
mToken = new Binder("TaskFragmentContainer");
|
||||
mReparentingActivity = activity;
|
||||
if (activity != null) {
|
||||
addPendingAppearedActivity(activity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,8 +91,8 @@ class TaskFragmentContainer {
|
||||
// fragment info update with it placed in this container. We still want to apply rules
|
||||
// in this intermediate state.
|
||||
List<Activity> allActivities = new ArrayList<>();
|
||||
if (mReparentingActivity != null) {
|
||||
allActivities.add(mReparentingActivity);
|
||||
if (!mPendingAppearedActivities.isEmpty()) {
|
||||
allActivities.addAll(mPendingAppearedActivities);
|
||||
}
|
||||
// Add activities reported from the server.
|
||||
if (mInfo == null) {
|
||||
@@ -106,12 +108,20 @@ class TaskFragmentContainer {
|
||||
return allActivities;
|
||||
}
|
||||
|
||||
void addPendingAppearedActivity(@NonNull Activity pendingAppearedActivity) {
|
||||
mPendingAppearedActivities.add(pendingAppearedActivity);
|
||||
}
|
||||
|
||||
boolean hasActivity(@NonNull IBinder token) {
|
||||
if (mInfo != null && mInfo.getActivities().contains(token)) {
|
||||
return true;
|
||||
}
|
||||
return mReparentingActivity != null
|
||||
&& mReparentingActivity.getActivityToken().equals(token);
|
||||
for (Activity activity : mPendingAppearedActivities) {
|
||||
if (activity.getActivityToken().equals(token)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -121,14 +131,15 @@ class TaskFragmentContainer {
|
||||
|
||||
void setInfo(@Nullable TaskFragmentInfo info) {
|
||||
mInfo = info;
|
||||
if (mInfo == null || mReparentingActivity == null) {
|
||||
if (mInfo == null || mPendingAppearedActivities.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// Cleanup activities that were being re-parented
|
||||
for (IBinder activityToken : mInfo.getActivities()) {
|
||||
if (mReparentingActivity.getActivityToken().equals(activityToken)) {
|
||||
mReparentingActivity = null;
|
||||
break;
|
||||
List<IBinder> infoActivities = mInfo.getActivities();
|
||||
for (int i = mPendingAppearedActivities.size() - 1; i >= 0; --i) {
|
||||
final Activity activity = mPendingAppearedActivities.get(i);
|
||||
if (infoActivities.contains(activity.getActivityToken())) {
|
||||
mPendingAppearedActivities.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,7 +158,7 @@ class TaskFragmentContainer {
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return mReparentingActivity == null && (mInfo == null || mInfo.isEmpty());
|
||||
return mPendingAppearedActivities.isEmpty() && (mInfo == null || mInfo.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,10 +207,10 @@ class TaskFragmentContainer {
|
||||
mActivitiesToFinishOnExit.clear();
|
||||
|
||||
// Finish activities that were being re-parented to this container.
|
||||
if (mReparentingActivity != null) {
|
||||
mReparentingActivity.finish();
|
||||
mReparentingActivity = null;
|
||||
for (Activity activity : mPendingAppearedActivities) {
|
||||
activity.finish();
|
||||
}
|
||||
mPendingAppearedActivities.clear();
|
||||
}
|
||||
|
||||
boolean isFinished() {
|
||||
|
||||
@@ -841,6 +841,10 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
|
||||
proc.getThread(), r.appToken);
|
||||
|
||||
final boolean isTransitionForward = r.isTransitionForward();
|
||||
IBinder fragmentToken = null;
|
||||
if (r.getTaskFragment().getTaskFragmentOrganizerPid() == r.getPid()) {
|
||||
fragmentToken = r.getTaskFragment().getFragmentToken();
|
||||
}
|
||||
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
|
||||
System.identityHashCode(r), r.info,
|
||||
// TODO: Have this take the merged configuration instead of separate global
|
||||
@@ -852,7 +856,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
|
||||
r.takeOptions(), isTransitionForward,
|
||||
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
|
||||
r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken,
|
||||
r.getLaunchedFromBubble()));
|
||||
r.getLaunchedFromBubble(), fragmentToken));
|
||||
|
||||
// Set desired final state.
|
||||
final ActivityLifecycleItem lifecycleItem;
|
||||
|
||||
@@ -1902,6 +1902,10 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
}
|
||||
}
|
||||
|
||||
int getTaskFragmentOrganizerPid() {
|
||||
return mTaskFragmentOrganizerPid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link TaskFragmentInfo} with information from this TaskFragment. Should not be
|
||||
* called from {@link Task}.
|
||||
|
||||
Reference in New Issue
Block a user