Merge "Provide a queue to defer TaskFragment events" into sc-v2-dev
This commit is contained in:
@@ -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() {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user