Fix ActivityEmbedding crash when process died

1. When the organizer is removed, also remove any pending event.
2. Only apply transaction when the organizer is registered.

Fix: 240628043
Test: testApplyTransaction_skipTransactionForUnregisterOrganizer
Change-Id: I24c25691fd49fd83100b7ae51ff7fbfeb39a03e9
This commit is contained in:
Chris Li
2022-07-29 17:45:04 +08:00
parent 8be2f81086
commit 2581a7e42c
4 changed files with 44 additions and 0 deletions

View File

@@ -393,6 +393,10 @@ class TaskFragment extends WindowContainer<WindowContainer> {
mTaskFragmentOrganizerProcessName = processName;
}
void onTaskFragmentOrganizerRemoved() {
mTaskFragmentOrganizer = null;
}
/** Whether this TaskFragment is organized by the given {@code organizer}. */
boolean hasTaskFragmentOrganizer(ITaskFragmentOrganizer organizer) {
return organizer != null && mTaskFragmentOrganizer != null

View File

@@ -136,6 +136,9 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
void dispose() {
while (!mOrganizedTaskFragments.isEmpty()) {
final TaskFragment taskFragment = mOrganizedTaskFragments.get(0);
// Cleanup before remove to prevent it from sending any additional event, such as
// #onTaskFragmentVanished, to the removed organizer.
taskFragment.onTaskFragmentOrganizerRemoved();
taskFragment.removeImmediately();
mOrganizedTaskFragments.remove(taskFragment);
}
@@ -512,10 +515,21 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
mPendingTaskFragmentEvents.add(pendingEvent);
}
boolean isOrganizerRegistered(ITaskFragmentOrganizer organizer) {
return mTaskFragmentOrganizerState.containsKey(organizer.asBinder());
}
private void removeOrganizer(ITaskFragmentOrganizer organizer) {
final TaskFragmentOrganizerState state = validateAndGetState(organizer);
// remove all of the children of the organized TaskFragment
state.dispose();
// Remove any pending event of this organizer.
for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
if (event.mTaskFragmentOrg.asBinder().equals(organizer.asBinder())) {
mPendingTaskFragmentEvents.remove(i);
}
}
mTaskFragmentOrganizerState.remove(organizer.asBinder());
}

View File

@@ -386,6 +386,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
private void applyTransaction(@NonNull WindowContainerTransaction t, int syncId,
@Nullable Transition transition, @NonNull CallerInfo caller,
@Nullable Transition finishTransition) {
if (t.getTaskFragmentOrganizer() != null && !mTaskFragmentOrganizerController
.isOrganizerRegistered(t.getTaskFragmentOrganizer())) {
Slog.e(TAG, "Caller organizer=" + t.getTaskFragmentOrganizer()
+ " is no longer registered");
return;
}
int effects = 0;
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d", syncId);
mService.deferWindowLayout();

View File

@@ -420,6 +420,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
@Test
public void testApplyTransaction_enforceHierarchyChange_setAdjacentRoots()
throws RemoteException {
mAtm.mTaskFragmentOrganizerController.registerOrganizer(mIOrganizer);
final TaskFragment taskFragment2 =
new TaskFragment(mAtm, new Binder(), true /* createdByOrganizer */);
final WindowContainerToken token2 = taskFragment2.mRemoteToken.toWindowContainerToken();
@@ -594,6 +595,25 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
assertEquals(activity0, mDisplayContent.mFocusedApp);
}
@Test
public void testApplyTransaction_skipTransactionForUnregisterOrganizer() {
final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent);
final IBinder fragmentToken = new Binder();
// Allow organizer to create TaskFragment and start/reparent activity to TaskFragment.
createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken);
mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
// Nothing should happen as the organizer is not registered.
assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
mController.registerOrganizer(mIOrganizer);
mAtm.mWindowOrganizerController.applyTransaction(mTransaction);
// Successfully created when the organizer is registered.
assertNotNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
}
@Test
public void testTaskFragmentInPip_startActivityInTaskFragment() {
setupTaskFragmentInPip();