Merge "Make sure empty TaskFragment notify organizer" into tm-dev
This commit is contained in:
@@ -181,7 +181,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment info changed name=%s",
|
||||
tf.getName());
|
||||
try {
|
||||
mOrganizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo());
|
||||
mOrganizer.onTaskFragmentInfoChanged(info);
|
||||
mLastSentTaskFragmentInfos.put(tf, info);
|
||||
} catch (RemoteException e) {
|
||||
Slog.d(TAG, "Exception sending onTaskFragmentInfoChanged callback", e);
|
||||
@@ -424,6 +424,10 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
}
|
||||
// Remove and add for re-ordering.
|
||||
mPendingTaskFragmentEvents.remove(pendingEvent);
|
||||
// Reset the defer time when TaskFragment is changed, so that it can check again if
|
||||
// the event should be sent to the organizer, for example the TaskFragment may become
|
||||
// empty.
|
||||
pendingEvent.mDeferTime = 0;
|
||||
}
|
||||
mPendingTaskFragmentEvents.add(pendingEvent);
|
||||
}
|
||||
@@ -654,26 +658,15 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean shouldSendEventWhenTaskInvisible(@NonNull Task task,
|
||||
@NonNull PendingTaskFragmentEvent event) {
|
||||
private boolean shouldSendEventWhenTaskInvisible(@NonNull PendingTaskFragmentEvent event) {
|
||||
final TaskFragmentOrganizerState state =
|
||||
mTaskFragmentOrganizerState.get(event.mTaskFragmentOrg.asBinder());
|
||||
final TaskFragmentInfo lastInfo = state.mLastSentTaskFragmentInfos.get(event.mTaskFragment);
|
||||
final TaskFragmentInfo info = event.mTaskFragment.getTaskFragmentInfo();
|
||||
// Send an info changed callback if this event is for the last activities to finish in a
|
||||
// Task so that the {@link TaskFragmentOrganizer} can delete this TaskFragment. Otherwise,
|
||||
// the Task may be removed before it becomes visible again to send this event because it no
|
||||
// longer has activities. As a result, the organizer will never get this info changed event
|
||||
// and will not delete the TaskFragment because the organizer thinks the TaskFragment still
|
||||
// has running activities.
|
||||
// Another case is when an organized TaskFragment became empty because the last running
|
||||
// activity is reparented to a new Task due to enter PiP. We also want to notify the
|
||||
// organizer, so it can remove the empty TaskFragment and update the paired TaskFragment
|
||||
// without causing the extra delay.
|
||||
// TaskFragment so that the {@link TaskFragmentOrganizer} can delete this TaskFragment.
|
||||
return event.mEventType == PendingTaskFragmentEvent.EVENT_INFO_CHANGED
|
||||
&& (task.topRunningActivity() == null || info.isTaskFragmentClearedForPip())
|
||||
&& lastInfo != null
|
||||
&& lastInfo.getRunningActivityCount() > 0 && info.getRunningActivityCount() == 0;
|
||||
&& lastInfo != null && lastInfo.hasRunningActivity() && info.isEmpty();
|
||||
}
|
||||
|
||||
void dispatchPendingEvents() {
|
||||
@@ -690,7 +683,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null;
|
||||
if (task != null && (task.lastActiveTime <= event.mDeferTime
|
||||
|| !(isTaskVisible(task, visibleTasks, invisibleTasks)
|
||||
|| shouldSendEventWhenTaskInvisible(task, event)))) {
|
||||
|| shouldSendEventWhenTaskInvisible(event)))) {
|
||||
// Defer sending events to the TaskFragment until the host task is active again.
|
||||
event.mDeferTime = task.lastActiveTime;
|
||||
continue;
|
||||
|
||||
@@ -778,6 +778,47 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
||||
verify(mOrganizer).onTaskFragmentInfoChanged(any());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a task fragment info changed event is sent if the TaskFragment becomes empty
|
||||
* even if the Task is invisible.
|
||||
*/
|
||||
@Test
|
||||
public void testPendingTaskFragmentInfoChangedEvent_emptyTaskFragment() {
|
||||
// Create a TaskFragment with an activity, all within a parent task
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
||||
.setParentTask(task)
|
||||
.setOrganizer(mOrganizer)
|
||||
.setFragmentToken(mFragmentToken)
|
||||
.createActivityCount(1)
|
||||
.build();
|
||||
final ActivityRecord embeddedActivity = taskFragment.getTopNonFinishingActivity();
|
||||
// Add another activity in the Task so that it always contains a non-finishing activitiy.
|
||||
final ActivityRecord nonEmbeddedActivity = createActivityRecord(task);
|
||||
assertTrue(task.shouldBeVisible(null));
|
||||
|
||||
// Dispatch pending info changed event from creating the activity
|
||||
mController.registerOrganizer(mIOrganizer);
|
||||
taskFragment.mTaskFragmentAppearedSent = true;
|
||||
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
|
||||
mController.dispatchPendingEvents();
|
||||
verify(mOrganizer).onTaskFragmentInfoChanged(any());
|
||||
|
||||
// Verify the info changed callback is not called when the task is invisible
|
||||
reset(mOrganizer);
|
||||
doReturn(false).when(task).shouldBeVisible(any());
|
||||
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
|
||||
mController.dispatchPendingEvents();
|
||||
verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
|
||||
|
||||
// Finish the embedded activity, and verify the info changed callback is called because the
|
||||
// TaskFragment is becoming empty.
|
||||
embeddedActivity.finishing = true;
|
||||
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
|
||||
mController.dispatchPendingEvents();
|
||||
verify(mOrganizer).onTaskFragmentInfoChanged(any());
|
||||
}
|
||||
|
||||
/**
|
||||
* When an embedded {@link TaskFragment} is removed, we should clean up the reference in the
|
||||
* {@link WindowOrganizerController}.
|
||||
|
||||
Reference in New Issue
Block a user