Merge changes from topic "embedding-race-condition" into tm-dev

* changes:
  Send Split Info Callback before Activity#onCreate
  Revert "Removing TaskFragment token from LaunchActivityItem"
This commit is contained in:
Shivam Agrawal
2022-04-05 18:36:49 +00:00
committed by Android (Google) Code Review
10 changed files with 74 additions and 16 deletions

View File

@@ -536,6 +536,9 @@ 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 initial TaskFragment that embedded this activity. Do not rely on it
// after creation because the activity could be reparented.
@Nullable public IBinder mInitialTaskFragmentToken;
int ident;
@UnsupportedAppUsage
Intent intent;
@@ -618,7 +621,8 @@ public final class ActivityThread extends ClientTransactionHandler
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client,
IBinder assistToken, IBinder shareableActivityToken, boolean launchedFromBubble) {
IBinder assistToken, IBinder shareableActivityToken, boolean launchedFromBubble,
IBinder initialTaskFragmentToken) {
this.token = token;
this.assistToken = assistToken;
this.shareableActivityToken = shareableActivityToken;
@@ -639,6 +643,7 @@ public final class ActivityThread extends ClientTransactionHandler
compatInfo);
mActivityOptions = activityOptions;
mLaunchedFromBubble = launchedFromBubble;
mInitialTaskFragmentToken = initialTaskFragmentToken;
init();
}

View File

@@ -72,6 +72,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.
@@ -95,7 +96,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble);
client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
mTaskFragmentToken);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -119,7 +121,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
IActivityClientController activityClientController, IBinder shareableActivityToken,
boolean launchedFromBubble) {
boolean launchedFromBubble, IBinder taskFragmentToken) {
LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
if (instance == null) {
instance = new LaunchActivityItem();
@@ -128,7 +130,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
voiceInteractor, procState, state, persistentState, pendingResults,
pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken,
activityClientController, shareableActivityToken,
launchedFromBubble);
launchedFromBubble, taskFragmentToken);
return instance;
}
@@ -136,7 +138,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, false);
null, false, null, null, null, null, false, null);
ObjectPool.recycle(this);
}
@@ -166,6 +168,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
dest.writeStrongInterface(mActivityClientController);
dest.writeStrongBinder(mShareableActivityToken);
dest.writeBoolean(mLaunchedFromBubble);
dest.writeStrongBinder(mTaskFragmentToken);
}
/** Read from Parcel. */
@@ -184,7 +187,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
in.readStrongBinder(),
IActivityClientController.Stub.asInterface(in.readStrongBinder()),
in.readStrongBinder(),
in.readBoolean());
in.readBoolean(),
in.readStrongBinder());
}
public static final @NonNull Creator<LaunchActivityItem> CREATOR =
@@ -222,7 +226,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
&& mIsForward == other.mIsForward
&& Objects.equals(mProfilerInfo, other.mProfilerInfo)
&& Objects.equals(mAssistToken, other.mAssistToken)
&& Objects.equals(mShareableActivityToken, other.mShareableActivityToken);
&& Objects.equals(mShareableActivityToken, other.mShareableActivityToken)
&& Objects.equals(mTaskFragmentToken, other.mTaskFragmentToken);
}
@Override
@@ -244,6 +249,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
result = 31 * result + Objects.hashCode(mProfilerInfo);
result = 31 * result + Objects.hashCode(mAssistToken);
result = 31 * result + Objects.hashCode(mShareableActivityToken);
result = 31 * result + Objects.hashCode(mTaskFragmentToken);
return result;
}
@@ -291,7 +297,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo,
IBinder assistToken, IActivityClientController activityClientController,
IBinder shareableActivityToken, boolean launchedFromBubble) {
IBinder shareableActivityToken, boolean launchedFromBubble, IBinder taskFragmentToken) {
instance.mIntent = intent;
instance.mIdent = ident;
instance.mInfo = info;
@@ -312,5 +318,6 @@ public class LaunchActivityItem extends ClientTransactionItem {
instance.mActivityClientController = activityClientController;
instance.mShareableActivityToken = shareableActivityToken;
instance.mLaunchedFromBubble = launchedFromBubble;
instance.mTaskFragmentToken = taskFragmentToken;
}
}

View File

@@ -157,7 +157,7 @@ public class ObjectPoolTests {
.setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList())
.setIsForward(true).setAssistToken(assistToken)
.setShareableActivityToken(shareableActivityToken)
.build();
.setTaskFragmentToken(new Binder()).build();
LaunchActivityItem emptyItem = new LaunchActivityItemBuilder().build();
LaunchActivityItem item = itemSupplier.get();

View File

@@ -110,6 +110,7 @@ class TestUtils {
private IBinder mAssistToken;
private IBinder mShareableActivityToken;
private boolean mLaunchedFromBubble;
private IBinder mTaskFragmentToken;
LaunchActivityItemBuilder setIntent(Intent intent) {
mIntent = intent;
@@ -206,13 +207,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 */, mShareableActivityToken,
mLaunchedFromBubble);
mLaunchedFromBubble, mTaskFragmentToken);
}
}
}

View File

@@ -203,6 +203,7 @@ public class TransactionParcelTests {
.setPendingResults(resultInfoList()).setActivityOptions(ActivityOptions.makeBasic())
.setPendingNewIntents(referrerIntentList()).setIsForward(true)
.setAssistToken(new Binder()).setShareableActivityToken(new Binder())
.setTaskFragmentToken(new Binder())
.build();
writeAndPrepareForReading(item);

View File

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

View File

@@ -615,14 +615,22 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return null;
}
private void updateCallbackIfNecessary() {
updateCallbackIfNecessary(true /* deferCallbackUntilAllActivitiesCreated */);
}
/**
* Notifies listeners about changes to split states if necessary.
*
* @param deferCallbackUntilAllActivitiesCreated boolean to indicate whether the split info
* callback should be deferred until all the
* organized activities have been created.
*/
private void updateCallbackIfNecessary() {
private void updateCallbackIfNecessary(boolean deferCallbackUntilAllActivitiesCreated) {
if (mEmbeddingCallback == null) {
return;
}
if (!allActivitiesCreated()) {
if (deferCallbackUntilAllActivitiesCreated && !allActivitiesCreated()) {
return;
}
List<SplitInfo> currentSplitStates = getActiveSplitStates();
@@ -837,6 +845,36 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter {
@Override
public void onActivityPreCreated(Activity activity, Bundle savedInstanceState) {
final IBinder activityToken = activity.getActivityToken();
final IBinder initialTaskFragmentToken = ActivityThread.currentActivityThread()
.getActivityClient(activityToken).mInitialTaskFragmentToken;
// If the activity is not embedded, then it will not have an initial task fragment token
// so no further action is needed.
if (initialTaskFragmentToken == null) {
return;
}
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
.mContainers;
for (int j = containers.size() - 1; j >= 0; j--) {
final TaskFragmentContainer container = containers.get(j);
if (!container.hasActivity(activityToken)
&& container.getTaskFragmentToken().equals(initialTaskFragmentToken)) {
// The onTaskFragmentInfoChanged callback containing this activity has not
// reached the client yet, so add the activity to the pending appeared
// activities and send a split info callback to the client before
// {@link Activity#onCreate} is called.
container.addPendingAppearedActivity(activity);
updateCallbackIfNecessary(
false /* deferCallbackUntilAllActivitiesCreated */);
return;
}
}
}
}
@Override
public void onActivityPostCreated(Activity activity, Bundle savedInstanceState) {
// Calling after Activity#onCreate is complete to allow the app launch something

View File

@@ -120,7 +120,7 @@ class TaskFragmentContainer {
}
ActivityStack toActivityStack() {
return new ActivityStack(collectActivities(), mInfo.getRunningActivityCount() == 0);
return new ActivityStack(collectActivities(), isEmpty());
}
void addPendingAppearedActivity(@NonNull Activity pendingAppearedActivity) {

View File

@@ -897,6 +897,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
proc.getThread(), r.token);
final boolean isTransitionForward = r.isTransitionForward();
final IBinder 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
@@ -907,7 +908,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
results, newIntents, r.takeOptions(), isTransitionForward,
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
r.shareableActivityToken, r.getLaunchedFromBubble()));
r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;

View File

@@ -2262,7 +2262,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
mFragmentToken,
mRemoteToken.toWindowContainerToken(),
getConfiguration(),
getChildCount() == 0,
runningActivityCount[0] == 0,
runningActivityCount[0],
isVisible(),
childActivities,