Merge "Provide a queue to defer TaskFragment events" into sc-v2-dev

This commit is contained in:
Jeff Chang
2021-07-16 02:50:50 +00:00
committed by Android (Google) Code Review
5 changed files with 297 additions and 91 deletions

View File

@@ -732,6 +732,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
WindowOrganizerController mWindowOrganizerController; WindowOrganizerController mWindowOrganizerController;
TaskOrganizerController mTaskOrganizerController; TaskOrganizerController mTaskOrganizerController;
TaskFragmentOrganizerController mTaskFragmentOrganizerController;
@Nullable @Nullable
private BackgroundActivityStartCallback mBackgroundActivityStartCallback; private BackgroundActivityStartCallback mBackgroundActivityStartCallback;
@@ -805,6 +806,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", GL_ES_VERSION_UNDEFINED); GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", GL_ES_VERSION_UNDEFINED);
mWindowOrganizerController = new WindowOrganizerController(this); mWindowOrganizerController = new WindowOrganizerController(this);
mTaskOrganizerController = mWindowOrganizerController.mTaskOrganizerController; mTaskOrganizerController = mWindowOrganizerController.mTaskOrganizerController;
mTaskFragmentOrganizerController =
mWindowOrganizerController.mTaskFragmentOrganizerController;
} }
public void onSystemReady() { public void onSystemReady() {

View File

@@ -858,6 +858,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// Send any pending task-info changes that were queued-up during a layout deferment // Send any pending task-info changes that were queued-up during a layout deferment
mWmService.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); mWmService.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
mWmService.mAtmService.mTaskFragmentOrganizerController.dispatchPendingEvents();
mWmService.mSyncEngine.onSurfacePlacement(); mWmService.mSyncEngine.onSurfacePlacement();
mWmService.mAnimator.executeAfterPrepareSurfacesRunnables(); mWmService.mAnimator.executeAfterPrepareSurfacesRunnables();

View File

@@ -82,6 +82,7 @@ import android.util.DisplayMetrics;
import android.util.Slog; import android.util.Slog;
import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo; import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.window.ITaskFragmentOrganizer; import android.window.ITaskFragmentOrganizer;
import android.window.TaskFragmentInfo; import android.window.TaskFragmentInfo;
@@ -160,6 +161,11 @@ class TaskFragment extends WindowContainer<WindowContainer> {
// The TaskFragment that adjacent to this one. // The TaskFragment that adjacent to this one.
private TaskFragment mAdjacentTaskFragment; private TaskFragment mAdjacentTaskFragment;
/**
* Prevents duplicate calls to onTaskAppeared.
*/
boolean mTaskFragmentAppearedSent;
/** /**
* When we are in the process of pausing an activity, before starting the * When we are in the process of pausing an activity, before starting the
* next one, this variable holds the activity that is currently being paused. * next one, this variable holds the activity that is currently being paused.
@@ -1970,18 +1976,24 @@ class TaskFragment extends WindowContainer<WindowContainer> {
@Override @Override
public void onConfigurationChanged(Configuration newParentConfig) { public void onConfigurationChanged(Configuration newParentConfig) {
super.onConfigurationChanged(newParentConfig); super.onConfigurationChanged(newParentConfig);
sendTaskFragmentInfoChanged();
}
@Override
void setSurfaceControl(SurfaceControl sc) {
super.setSurfaceControl(sc);
// If the TaskFragmentOrganizer was set before we created the SurfaceControl, we need to
// emit the callbacks now.
sendTaskFragmentAppeared();
}
void sendTaskFragmentInfoChanged() {
if (mTaskFragmentOrganizer != null) { if (mTaskFragmentOrganizer != null) {
// Parent config may have changed. The controller will check if there is any important
// config change for the organizer.
mTaskFragmentOrganizerController
.onTaskFragmentParentInfoChanged(mTaskFragmentOrganizer, this);
mTaskFragmentOrganizerController mTaskFragmentOrganizerController
.onTaskFragmentInfoChanged(mTaskFragmentOrganizer, this); .onTaskFragmentInfoChanged(mTaskFragmentOrganizer, this);
} }
} }
// TODO(b/190433129) call when TaskFragment is created from WCT#createTaskFragment
private void sendTaskFragmentAppeared() { private void sendTaskFragmentAppeared() {
if (mTaskFragmentOrganizer != null) { if (mTaskFragmentOrganizer != null) {
mTaskFragmentOrganizerController.onTaskFragmentAppeared(mTaskFragmentOrganizer, this); mTaskFragmentOrganizerController.onTaskFragmentAppeared(mTaskFragmentOrganizer, this);

View File

@@ -19,6 +19,8 @@ package com.android.server.wm;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer; import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Binder; import android.os.Binder;
import android.os.IBinder; import android.os.IBinder;
@@ -33,6 +35,8 @@ import android.window.TaskFragmentInfo;
import com.android.internal.protolog.common.ProtoLog; import com.android.internal.protolog.common.ProtoLog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
@@ -45,16 +49,17 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
private final ActivityTaskManagerService mAtmService; private final ActivityTaskManagerService mAtmService;
private final WindowManagerGlobalLock mGlobalLock; private final WindowManagerGlobalLock mGlobalLock;
private final Map<TaskFragment, TaskFragmentInfo> mLastSentTaskFragmentInfos =
new WeakHashMap<>();
private final Map<TaskFragment, Configuration> mLastSentTaskFragmentParentConfigs =
new WeakHashMap<>();
/** /**
* A Map which manages the relationship between * A Map which manages the relationship between
* {@link ITaskFragmentOrganizer} and {@link TaskFragmentOrganizerState} * {@link ITaskFragmentOrganizer} and {@link TaskFragmentOrganizerState}
*/ */
private final ArrayMap<IBinder, TaskFragmentController> mTaskFragmentOrganizerControllers = private final ArrayMap<IBinder, TaskFragmentOrganizerState> mTaskFragmentOrganizerState =
new ArrayMap<>(); new ArrayMap<>();
/**
* A List which manages the TaskFragment pending event {@link PendingTaskFragmentEvent}
*/
private final ArrayList<PendingTaskFragmentEvent> mPendingTaskFragmentEvents =
new ArrayList<>();
TaskFragmentOrganizerController(ActivityTaskManagerService atm) { TaskFragmentOrganizerController(ActivityTaskManagerService atm) {
mAtmService = atm; mAtmService = atm;
@@ -65,11 +70,15 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
* A class to manage {@link ITaskFragmentOrganizer} and its organized * A class to manage {@link ITaskFragmentOrganizer} and its organized
* {@link TaskFragment TaskFragments}. * {@link TaskFragment TaskFragments}.
*/ */
private class TaskFragmentController implements IBinder.DeathRecipient { private class TaskFragmentOrganizerState implements IBinder.DeathRecipient {
private final ArrayList<TaskFragment> mOrganizedTaskFragments = new ArrayList<>(); private final ArrayList<TaskFragment> mOrganizedTaskFragments = new ArrayList<>();
private final ITaskFragmentOrganizer mOrganizer; private final ITaskFragmentOrganizer mOrganizer;
private final Map<TaskFragment, TaskFragmentInfo> mLastSentTaskFragmentInfos =
new WeakHashMap<>();
private final Map<TaskFragment, Configuration> mLastSentTaskFragmentParentConfigs =
new WeakHashMap<>();
TaskFragmentController(ITaskFragmentOrganizer organizer) { TaskFragmentOrganizerState(ITaskFragmentOrganizer organizer) {
mOrganizer = organizer; mOrganizer = organizer;
try { try {
mOrganizer.asBinder().linkToDeath(this, 0 /*flags*/); mOrganizer.asBinder().linkToDeath(this, 0 /*flags*/);
@@ -85,10 +94,18 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
} }
} }
void addTaskFragment(TaskFragment taskFragment) { /**
if (!mOrganizedTaskFragments.contains(taskFragment)) { * @return {@code true} if taskFragment is organized and not sent the appeared event before.
mOrganizedTaskFragments.add(taskFragment); */
boolean addTaskFragment(TaskFragment taskFragment) {
if (taskFragment.mTaskFragmentAppearedSent) {
return false;
} }
if (mOrganizedTaskFragments.contains(taskFragment)) {
return false;
}
mOrganizedTaskFragments.add(taskFragment);
return true;
} }
void removeTaskFragment(TaskFragment taskFragment) { void removeTaskFragment(TaskFragment taskFragment) {
@@ -100,57 +117,39 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
mOrganizedTaskFragments.clear(); mOrganizedTaskFragments.clear();
mOrganizer.asBinder().unlinkToDeath(this, 0 /*flags*/); mOrganizer.asBinder().unlinkToDeath(this, 0 /*flags*/);
} }
}
@Override
public void registerOrganizer(ITaskFragmentOrganizer organizer) {
final int pid = Binder.getCallingPid();
final long uid = Binder.getCallingUid();
synchronized (mGlobalLock) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
"Register task fragment organizer=%s uid=%d pid=%d",
organizer.asBinder(), uid, pid);
if (mTaskFragmentOrganizerControllers.containsKey(organizer.asBinder())) {
throw new IllegalStateException(
"Replacing existing organizer currently unsupported");
}
mTaskFragmentOrganizerControllers.put(organizer.asBinder(),
new TaskFragmentController(organizer));
}
}
@Override
public void unregisterOrganizer(ITaskFragmentOrganizer organizer) {
validateAndGetController(organizer);
final int pid = Binder.getCallingPid();
final long uid = Binder.getCallingUid();
synchronized (mGlobalLock) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
"Unregister task fragment organizer=%s uid=%d pid=%d",
organizer.asBinder(), uid, pid);
removeOrganizer(organizer);
}
}
void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment tf) { void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment tf) {
final TaskFragmentController controller = validateAndGetController(organizer);
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName()); ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName());
final TaskFragmentInfo info = tf.getTaskFragmentInfo(); final TaskFragmentInfo info = tf.getTaskFragmentInfo();
final SurfaceControl outSurfaceControl = new SurfaceControl(tf.getSurfaceControl(), final SurfaceControl outSurfaceControl = new SurfaceControl(tf.getSurfaceControl(),
"TaskFragmentOrganizerController.onTaskFragmentInfoAppeared"); "TaskFragmentOrganizerController.onTaskFragmentInfoAppeared");
controller.addTaskFragment(tf);
try { try {
organizer.onTaskFragmentAppeared( organizer.onTaskFragmentAppeared(
new TaskFragmentAppearedInfo(info, outSurfaceControl)); new TaskFragmentAppearedInfo(info, outSurfaceControl));
mLastSentTaskFragmentInfos.put(tf, info); mLastSentTaskFragmentInfos.put(tf, info);
tf.mTaskFragmentAppearedSent = true;
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Exception sending onTaskFragmentAppeared callback", e); Slog.e(TAG, "Exception sending onTaskFragmentAppeared callback", e);
} }
onTaskFragmentParentInfoChanged(organizer, tf);
}
void onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment tf) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment vanished name=%s", tf.getName());
try {
organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo());
} catch (RemoteException e) {
Slog.e(TAG, "Exception sending onTaskFragmentVanished callback", e);
}
tf.mTaskFragmentAppearedSent = false;
mLastSentTaskFragmentInfos.remove(tf);
mLastSentTaskFragmentParentConfigs.remove(tf);
} }
void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) { void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
validateAndGetController(organizer); // Parent config may have changed. The controller will check if there is any important
// config change for the organizer.
onTaskFragmentParentInfoChanged(organizer, tf);
// Check if the info is different from the last reported info. // Check if the info is different from the last reported info.
final TaskFragmentInfo info = tf.getTaskFragmentInfo(); final TaskFragmentInfo info = tf.getTaskFragmentInfo();
@@ -159,8 +158,8 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
info.getConfiguration(), lastInfo.getConfiguration())) { info.getConfiguration(), lastInfo.getConfiguration())) {
return; return;
} }
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment info changed name=%s",
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment info changed name=%s", tf.getName()); tf.getName());
try { try {
organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo()); organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo());
mLastSentTaskFragmentInfos.put(tf, info); mLastSentTaskFragmentInfos.put(tf, info);
@@ -169,23 +168,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
} }
} }
void onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment tf) {
final TaskFragmentController controller = validateAndGetController(organizer);
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment vanished name=%s", tf.getName());
try {
organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo());
} catch (RemoteException e) {
Slog.e(TAG, "Exception sending onTaskFragmentVanished callback", e);
}
mLastSentTaskFragmentInfos.remove(tf);
mLastSentTaskFragmentParentConfigs.remove(tf);
controller.removeTaskFragment(tf);
}
void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) { void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
validateAndGetController(organizer);
// Check if the parent info is different from the last reported parent info. // Check if the parent info is different from the last reported parent info.
if (tf.getParent() == null || tf.getParent().asTask() == null) { if (tf.getParent() == null || tf.getParent().asTask() == null) {
mLastSentTaskFragmentParentConfigs.remove(tf); mLastSentTaskFragmentParentConfigs.remove(tf);
@@ -197,7 +180,6 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
if (configurationsAreEqualForOrganizer(parentConfig, lastParentConfig)) { if (configurationsAreEqualForOrganizer(parentConfig, lastParentConfig)) {
return; return;
} }
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
"TaskFragment parent info changed name=%s parentTaskId=%d", "TaskFragment parent info changed name=%s parentTaskId=%d",
tf.getName(), parent.mTaskId); tf.getName(), parent.mTaskId);
@@ -208,12 +190,110 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
Slog.e(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e); Slog.e(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e);
} }
} }
}
@Override
public void registerOrganizer(ITaskFragmentOrganizer organizer) {
final int pid = Binder.getCallingPid();
final long uid = Binder.getCallingUid();
synchronized (mGlobalLock) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
"Register task fragment organizer=%s uid=%d pid=%d",
organizer.asBinder(), uid, pid);
if (mTaskFragmentOrganizerState.containsKey(organizer.asBinder())) {
throw new IllegalStateException(
"Replacing existing organizer currently unsupported");
}
mTaskFragmentOrganizerState.put(organizer.asBinder(),
new TaskFragmentOrganizerState(organizer));
}
}
@Override
public void unregisterOrganizer(ITaskFragmentOrganizer organizer) {
validateAndGetState(organizer);
final int pid = Binder.getCallingPid();
final long uid = Binder.getCallingUid();
synchronized (mGlobalLock) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
"Unregister task fragment organizer=%s uid=%d pid=%d",
organizer.asBinder(), uid, pid);
removeOrganizer(organizer);
}
}
void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment taskFragment) {
final TaskFragmentOrganizerState state = validateAndGetState(organizer);
if (!state.addTaskFragment(taskFragment)) {
return;
}
PendingTaskFragmentEvent pendingEvent = getPendingTaskFragmentEvent(taskFragment,
PendingTaskFragmentEvent.EVENT_APPEARED);
if (pendingEvent == null) {
pendingEvent = new PendingTaskFragmentEvent(taskFragment, organizer,
PendingTaskFragmentEvent.EVENT_APPEARED);
mPendingTaskFragmentEvents.add(pendingEvent);
}
}
void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment taskFragment) {
handleTaskFragmentInfoChanged(organizer, taskFragment,
PendingTaskFragmentEvent.EVENT_INFO_CHANGED);
}
void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer,
TaskFragment taskFragment) {
handleTaskFragmentInfoChanged(organizer, taskFragment,
PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED);
}
private void handleTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer,
TaskFragment taskFragment, int eventType) {
validateAndGetState(organizer);
if (!taskFragment.mTaskFragmentAppearedSent) {
// Skip if TaskFragment still not appeared.
return;
}
PendingTaskFragmentEvent pendingEvent = getLastPendingLifecycleEvent(taskFragment);
if (pendingEvent == null) {
pendingEvent = new PendingTaskFragmentEvent(taskFragment, organizer, eventType);
} else {
if (pendingEvent.mEventType == PendingTaskFragmentEvent.EVENT_VANISHED) {
// Skipped the info changed event if vanished event is pending.
return;
}
// Remove and add for re-ordering.
mPendingTaskFragmentEvents.remove(pendingEvent);
}
mPendingTaskFragmentEvents.add(pendingEvent);
}
void onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment taskFragment) {
final TaskFragmentOrganizerState state = validateAndGetState(organizer);
for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
if (taskFragment == entry.mTaskFragment) {
mPendingTaskFragmentEvents.remove(i);
if (entry.mEventType == PendingTaskFragmentEvent.EVENT_APPEARED) {
// If taskFragment appeared callback is pending, ignore the vanished request.
return;
}
}
}
if (!taskFragment.mTaskFragmentAppearedSent) {
return;
}
PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent(taskFragment,
organizer, PendingTaskFragmentEvent.EVENT_VANISHED);
mPendingTaskFragmentEvents.add(pendingEvent);
state.removeTaskFragment(taskFragment);
}
private void removeOrganizer(ITaskFragmentOrganizer organizer) { private void removeOrganizer(ITaskFragmentOrganizer organizer) {
final TaskFragmentController controller = validateAndGetController(organizer); final TaskFragmentOrganizerState state = validateAndGetState(organizer);
// remove all of the children of the organized TaskFragment // remove all of the children of the organized TaskFragment
controller.dispose(); state.dispose();
mTaskFragmentOrganizerControllers.remove(organizer.asBinder()); mTaskFragmentOrganizerState.remove(organizer.asBinder());
} }
/** /**
@@ -222,13 +302,113 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
* we wouldn't register {@link DeathRecipient} for the organizer, and might not remove the * we wouldn't register {@link DeathRecipient} for the organizer, and might not remove the
* {@link TaskFragment} after the organizer process died. * {@link TaskFragment} after the organizer process died.
*/ */
private TaskFragmentController validateAndGetController(ITaskFragmentOrganizer organizer) { private TaskFragmentOrganizerState validateAndGetState(ITaskFragmentOrganizer organizer) {
final TaskFragmentController controller = final TaskFragmentOrganizerState state =
mTaskFragmentOrganizerControllers.get(organizer.asBinder()); mTaskFragmentOrganizerState.get(organizer.asBinder());
if (controller == null) { if (state == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"TaskFragmentOrganizer has not been registered. Organizer=" + organizer); "TaskFragmentOrganizer has not been registered. Organizer=" + organizer);
} }
return controller; return state;
}
/**
* A class to store {@link ITaskFragmentOrganizer} and its organized
* {@link TaskFragment TaskFragments} with different pending event request.
*/
private static class PendingTaskFragmentEvent {
static final int EVENT_APPEARED = 0;
static final int EVENT_VANISHED = 1;
static final int EVENT_INFO_CHANGED = 2;
static final int EVENT_PARENT_INFO_CHANGED = 3;
@IntDef(prefix = "EVENT_", value = {
EVENT_APPEARED,
EVENT_VANISHED,
EVENT_INFO_CHANGED,
EVENT_PARENT_INFO_CHANGED
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventType {}
@EventType
final int mEventType;
final TaskFragment mTaskFragment;
final ITaskFragmentOrganizer mTaskFragmentOrg;
PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg,
@EventType int eventType) {
mTaskFragment = taskFragment;
mTaskFragmentOrg = taskFragmentOrg;
mEventType = eventType;
}
/**
* @return {@code true} if the pending event is related with taskFragment created, vanished
* and information changed.
*/
boolean isLifecycleEvent() {
switch (mEventType) {
case EVENT_APPEARED:
case EVENT_VANISHED:
case EVENT_INFO_CHANGED:
case EVENT_PARENT_INFO_CHANGED:
return true;
default:
return false;
}
}
}
@Nullable
private PendingTaskFragmentEvent getLastPendingLifecycleEvent(TaskFragment tf) {
for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
if (tf == entry.mTaskFragment && entry.isLifecycleEvent()) {
return entry;
}
}
return null;
}
@Nullable
private PendingTaskFragmentEvent getPendingTaskFragmentEvent(TaskFragment taskFragment,
int type) {
for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
if (taskFragment == entry.mTaskFragment && type == entry.mEventType) {
return entry;
}
}
return null;
}
void dispatchPendingEvents() {
if (mAtmService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()
|| mPendingTaskFragmentEvents.isEmpty()) {
return;
}
for (int i = 0, n = mPendingTaskFragmentEvents.size(); i < n; i++) {
PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
final ITaskFragmentOrganizer taskFragmentOrg = event.mTaskFragmentOrg;
final TaskFragment taskFragment = event.mTaskFragment;
final TaskFragmentOrganizerState state =
mTaskFragmentOrganizerState.get(taskFragmentOrg.asBinder());
if (state == null) continue;
switch (event.mEventType) {
case PendingTaskFragmentEvent.EVENT_APPEARED:
state.onTaskFragmentAppeared(taskFragmentOrg, taskFragment);
break;
case PendingTaskFragmentEvent.EVENT_VANISHED:
state.onTaskFragmentVanished(taskFragmentOrg, taskFragment);
break;
case PendingTaskFragmentEvent.EVENT_INFO_CHANGED:
state.onTaskFragmentInfoChanged(taskFragmentOrg, taskFragment);
break;
case PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED:
state.onTaskFragmentParentInfoChanged(taskFragmentOrg, taskFragment);
}
}
mPendingTaskFragmentEvents.clear();
} }
} }

View File

@@ -102,6 +102,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
mController.registerOrganizer(mIOrganizer); mController.registerOrganizer(mIOrganizer);
mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment); mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
verify(mOrganizer).onTaskFragmentAppeared(any()); verify(mOrganizer).onTaskFragmentAppeared(any());
} }
@@ -110,6 +111,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
public void testOnTaskFragmentInfoChanged() { public void testOnTaskFragmentInfoChanged() {
mController.registerOrganizer(mIOrganizer); mController.registerOrganizer(mIOrganizer);
mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment); mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
// No callback if the info is not changed. // No callback if the info is not changed.
doReturn(true).when(mTaskFragmentInfo).equalsForTaskFragmentOrganizer(any()); doReturn(true).when(mTaskFragmentInfo).equalsForTaskFragmentOrganizer(any());
@@ -117,6 +119,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
mController.onTaskFragmentInfoChanged(mTaskFragment.getTaskFragmentOrganizer(), mController.onTaskFragmentInfoChanged(mTaskFragment.getTaskFragmentOrganizer(),
mTaskFragment); mTaskFragment);
mController.dispatchPendingEvents();
verify(mOrganizer, never()).onTaskFragmentInfoChanged(any()); verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
@@ -125,6 +128,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
mController.onTaskFragmentInfoChanged(mTaskFragment.getTaskFragmentOrganizer(), mController.onTaskFragmentInfoChanged(mTaskFragment.getTaskFragmentOrganizer(),
mTaskFragment); mTaskFragment);
mController.dispatchPendingEvents();
verify(mOrganizer).onTaskFragmentInfoChanged(mTaskFragmentInfo); verify(mOrganizer).onTaskFragmentInfoChanged(mTaskFragmentInfo);
} }
@@ -133,7 +137,9 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
public void testOnTaskFragmentVanished() { public void testOnTaskFragmentVanished() {
mController.registerOrganizer(mIOrganizer); mController.registerOrganizer(mIOrganizer);
mTaskFragment.mTaskFragmentAppearedSent = true;
mController.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment); mController.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
verify(mOrganizer).onTaskFragmentVanished(any()); verify(mOrganizer).onTaskFragmentVanished(any());
} }
@@ -148,8 +154,10 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
doReturn(parentConfig).when(parent).getConfiguration(); doReturn(parentConfig).when(parent).getConfiguration();
doReturn(parent).when(parent).asTask(); doReturn(parent).when(parent).asTask();
mTaskFragment.mTaskFragmentAppearedSent = true;
mController.onTaskFragmentParentInfoChanged( mController.onTaskFragmentParentInfoChanged(
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment); mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mFragmentToken), any()); verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mFragmentToken), any());
@@ -158,6 +166,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
mController.onTaskFragmentParentInfoChanged( mController.onTaskFragmentParentInfoChanged(
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment); mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(any(), any()); verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(any(), any());
@@ -166,6 +175,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
mController.onTaskFragmentParentInfoChanged( mController.onTaskFragmentParentInfoChanged(
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment); mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mFragmentToken), any()); verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mFragmentToken), any());
} }