Merge "Send Task Fragment Info Update When Task Invisible..." into sc-v2-dev am: 785ee1a55c
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16639421 Change-Id: Ia509c7c72338abd5028c2c8db6d572f642a637e4
This commit is contained in:
@@ -22,6 +22,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANI
|
|||||||
import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
|
import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
|
||||||
|
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@@ -497,6 +498,23 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean shouldSendEventWhenTaskInvisible(@NonNull Task task,
|
||||||
|
@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.
|
||||||
|
return event.mEventType == PendingTaskFragmentEvent.EVENT_INFO_CHANGED
|
||||||
|
&& task.topRunningActivity() == null && lastInfo != null
|
||||||
|
&& lastInfo.getRunningActivityCount() > 0 && info.getRunningActivityCount() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
void dispatchPendingEvents() {
|
void dispatchPendingEvents() {
|
||||||
if (mAtmService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()
|
if (mAtmService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()
|
||||||
|| mPendingTaskFragmentEvents.isEmpty()) {
|
|| mPendingTaskFragmentEvents.isEmpty()) {
|
||||||
@@ -510,7 +528,8 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
|||||||
final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
|
final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
|
||||||
final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null;
|
final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null;
|
||||||
if (task != null && (task.lastActiveTime <= event.mDeferTime
|
if (task != null && (task.lastActiveTime <= event.mDeferTime
|
||||||
|| !isTaskVisible(task, visibleTasks, invisibleTasks))) {
|
|| !(isTaskVisible(task, visibleTasks, invisibleTasks)
|
||||||
|
|| shouldSendEventWhenTaskInvisible(task, event)))) {
|
||||||
// Defer sending events to the TaskFragment until the host task is active again.
|
// Defer sending events to the TaskFragment until the host task is active again.
|
||||||
event.mDeferTime = task.lastActiveTime;
|
event.mDeferTime = task.lastActiveTime;
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -21,14 +21,17 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
|||||||
import static com.android.server.wm.testing.Assert.assertThrows;
|
import static com.android.server.wm.testing.Assert.assertThrows;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.clearInvocations;
|
import static org.mockito.Mockito.clearInvocations;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.reset;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -471,6 +474,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
|||||||
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
||||||
.setParentTask(task)
|
.setParentTask(task)
|
||||||
.setOrganizer(mOrganizer)
|
.setOrganizer(mOrganizer)
|
||||||
|
.setFragmentToken(mFragmentToken)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Mock the task to invisible
|
// Mock the task to invisible
|
||||||
@@ -485,4 +489,38 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
|||||||
// Verifies that event was not sent
|
// Verifies that event was not sent
|
||||||
verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
|
verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that a task fragment info changed event is still sent if the task is invisible only
|
||||||
|
* when the info changed event is because of the last activity in a task finishing.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testLastPendingTaskFragmentInfoChangedEventOfInvisibleTaskSent() {
|
||||||
|
// Create a TaskFragment with an activity, all within a parent task
|
||||||
|
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
||||||
|
.setOrganizer(mOrganizer)
|
||||||
|
.setFragmentToken(mFragmentToken)
|
||||||
|
.setCreateParentTask()
|
||||||
|
.createActivityCount(1)
|
||||||
|
.build();
|
||||||
|
final Task parentTask = taskFragment.getTask();
|
||||||
|
final ActivityRecord activity = taskFragment.getTopNonFinishingActivity();
|
||||||
|
assertTrue(parentTask.shouldBeVisible(null));
|
||||||
|
|
||||||
|
// Dispatch pending info changed event from creating the activity
|
||||||
|
mController.registerOrganizer(mIOrganizer);
|
||||||
|
taskFragment.mTaskFragmentAppearedSent = true;
|
||||||
|
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
|
||||||
|
mController.dispatchPendingEvents();
|
||||||
|
|
||||||
|
// Finish the activity and verify that the task is invisible
|
||||||
|
activity.finishing = true;
|
||||||
|
assertFalse(parentTask.shouldBeVisible(null));
|
||||||
|
|
||||||
|
// Verify the info changed callback still occurred despite the task being invisible
|
||||||
|
reset(mOrganizer);
|
||||||
|
mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
|
||||||
|
mController.dispatchPendingEvents();
|
||||||
|
verify(mOrganizer).onTaskFragmentInfoChanged(any());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user