summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Winson Chung <winsonc@google.com> 2020-04-10 03:03:21 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-04-10 03:03:21 +0000
commitcb437ade00bd23dba1a8ea729bc4ecefd1bc5fbe (patch)
tree4912153b9a9a5191b31522c8b40594a3806f41b2
parent9454e04c8c33070e161c0a364257616b078c5e21 (diff)
parent8b5d23ab108e80a4c6af5253733c3c6cf504e13f (diff)
Merge changes I7d2ca2a2,I9f1fc593 into rvc-dev
* changes: Fix a couple issues with previous CL (keeping tasks hidden) Keep task hidden until task appeared
-rw-r--r--core/java/android/window/TaskOrganizerTaskEmbedder.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java6
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java13
-rw-r--r--services/core/java/com/android/server/wm/Task.java12
-rw-r--r--services/core/java/com/android/server/wm/TaskOrganizerController.java154
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java9
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java9
10 files changed, 177 insertions, 42 deletions
diff --git a/core/java/android/window/TaskOrganizerTaskEmbedder.java b/core/java/android/window/TaskOrganizerTaskEmbedder.java
index 2091c9398e95..39a0101bbf59 100644
--- a/core/java/android/window/TaskOrganizerTaskEmbedder.java
+++ b/core/java/android/window/TaskOrganizerTaskEmbedder.java
@@ -254,7 +254,9 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
mTaskToken = taskInfo.token;
mTaskLeash = mTaskToken.getLeash();
mTransaction.reparent(mTaskLeash, mSurfaceControl)
- .show(mSurfaceControl).apply();
+ .show(mTaskLeash)
+ .show(mSurfaceControl)
+ .apply();
if (mPendingNotifyBoundsChanged) {
// TODO: Either defer show or hide and synchronize show with the resize
notifyBoundsChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
index d219a9e65a3c..dba43430b490 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
@@ -319,6 +319,7 @@ public class PipAnimationController {
getSurfaceTransactionHelper()
.crop(tx, leash, getDestinationBounds())
.round(tx, leash, shouldApplyCornerRadius());
+ tx.show(leash);
tx.apply();
}
};
@@ -359,6 +360,7 @@ public class PipAnimationController {
getSurfaceTransactionHelper()
.alpha(tx, leash, 1f)
.round(tx, leash, shouldApplyCornerRadius());
+ tx.show(leash);
tx.apply();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
index 0d66340a3917..56a748497d4e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
@@ -51,7 +51,6 @@ public class PipAnimationControllerTest extends SysuiTestCase {
private PipAnimationController mPipAnimationController;
- @Mock
private SurfaceControl mLeash;
@Mock
@@ -61,6 +60,10 @@ public class PipAnimationControllerTest extends SysuiTestCase {
public void setUp() throws Exception {
mPipAnimationController = new PipAnimationController(
mContext, new PipSurfaceTransactionHelper(mContext));
+ mLeash = new SurfaceControl.Builder()
+ .setContainerLayer()
+ .setName("FakeLeash")
+ .build();
MockitoAnnotations.initMocks(this);
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index c4d034207449..856fbc70438e 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5212,6 +5212,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
updateReportedVisibilityLocked();
}
+ void onStartingWindowDrawn() {
+ if (task != null) {
+ task.setHasBeenVisible(true);
+ }
+ }
+
/** Called when the windows associated app window container are drawn. */
void onWindowsDrawn(boolean drawn, long timestampNs) {
mDrawn = drawn;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 15a09e55bb48..11fda369ec5f 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -37,6 +37,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
@@ -2116,16 +2117,19 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
try {
final Task task = r.getTask();
-
final ActivityStack pinnedStack = taskDisplayArea.getRootPinnedTask();
+
// This will change the pinned stack's windowing mode to its original mode, ensuring
// we only have one stack that is in pinned mode.
if (pinnedStack != null) {
pinnedStack.dismissPip();
}
- final boolean singleActivity = task.getChildCount() == 1;
+ // Set a transition to ensure that we don't immediately try and update the visibility
+ // of the activity entering PIP
+ r.getDisplayContent().prepareAppTransition(TRANSIT_NONE, false);
+ final boolean singleActivity = task.getChildCount() == 1;
final ActivityStack stack;
if (singleActivity) {
stack = r.getRootTask();
@@ -2148,11 +2152,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mService.continueWindowLayout();
}
- // TODO: revisit the following statement after the animation is moved from WM to SysUI.
- // Update the visibility of all activities after the they have been reparented to the new
- // stack. This MUST run after the animation above is scheduled to ensure that the windows
- // drawn signal is scheduled after the bounds animation start call on the bounds animator
- // thread.
ensureActivitiesVisible(null, 0, false /* preserveWindows */);
resumeFocusedStacksTopActivities();
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 106f0709e1ef..1e70573a2ada 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4098,8 +4098,18 @@ class Task extends WindowContainer<WindowContainer> {
}
void setHasBeenVisible(boolean hasBeenVisible) {
+ final boolean prevHasBeenVisible = mHasBeenVisible;
mHasBeenVisible = hasBeenVisible;
if (hasBeenVisible) {
+ // If the task is not yet visible when it is added to the task organizer, then we should
+ // hide it to allow the task organizer to show it when it is properly reparented. We
+ // skip this for tasks created by the organizer because they can synchronously update
+ // the leash before new children are added to the task.
+ if (!mCreatedByOrganizer && mTaskOrganizer != null && !prevHasBeenVisible) {
+ getPendingTransaction().hide(getSurfaceControl());
+ commitPendingTransaction();
+ }
+
sendTaskAppeared();
if (!isRootTask()) {
getRootTask().setHasBeenVisible(true);
@@ -4143,6 +4153,8 @@ class Task extends WindowContainer<WindowContainer> {
// Let the old organizer know it has lost control.
sendTaskVanished();
mTaskOrganizer = organizer;
+
+
sendTaskAppeared();
onTaskOrganizerChanged();
return true;
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 22702dd6b566..9873031e0138 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -25,6 +25,7 @@ import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFI
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.WindowConfiguration;
import android.content.Intent;
@@ -38,6 +39,7 @@ import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
import android.window.WindowContainerToken;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import java.io.PrintWriter;
@@ -46,6 +48,7 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.WeakHashMap;
+import java.util.function.Consumer;
/**
* Stores the TaskOrganizers associated with a given windowing mode and
@@ -81,17 +84,105 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
}
}
- };
+ }
+
+ /**
+ * A wrapper class around ITaskOrganizer to ensure that the calls are made in the right
+ * lifecycle order since we may be updating the visibility of task surface controls in a pending
+ * transaction before they are presented to the task org.
+ */
+ private class TaskOrganizerCallbacks {
+ final WindowManagerService mService;
+ final ITaskOrganizer mTaskOrganizer;
+ final Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
+
+ TaskOrganizerCallbacks(WindowManagerService wm, ITaskOrganizer taskOrg,
+ Consumer<Runnable> deferTaskOrgCallbacksConsumer) {
+ mService = wm;
+ mDeferTaskOrgCallbacksConsumer = deferTaskOrgCallbacksConsumer;
+ mTaskOrganizer = taskOrg;
+ }
+
+ IBinder getBinder() {
+ return mTaskOrganizer.asBinder();
+ }
+
+ void onTaskAppeared(Task task) {
+ final RunningTaskInfo taskInfo = task.getTaskInfo();
+ mDeferTaskOrgCallbacksConsumer.accept(() -> {
+ try {
+ mTaskOrganizer.onTaskAppeared(taskInfo);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception sending onTaskAppeared callback", e);
+ }
+ });
+ }
+
+
+ void onTaskVanished(Task task) {
+ final RunningTaskInfo taskInfo = task.getTaskInfo();
+ mDeferTaskOrgCallbacksConsumer.accept(() -> {
+ try {
+ mTaskOrganizer.onTaskVanished(taskInfo);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception sending onTaskVanished callback", e);
+ }
+ });
+ }
+
+ void onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo) {
+ if (!task.mCreatedByOrganizer && !task.mTaskAppearedSent) {
+ // Skip if the task has not yet received taskAppeared(), except for tasks created
+ // by the organizer that don't receive that signal
+ return;
+ }
+ mDeferTaskOrgCallbacksConsumer.accept(() -> {
+ if (!task.isOrganized()) {
+ // This is safe to ignore if the task is no longer organized
+ return;
+ }
+ try {
+ mTaskOrganizer.onTaskInfoChanged(taskInfo);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
+ }
+ });
+ }
+
+ void onBackPressedOnTaskRoot(Task task) {
+ if (!task.mCreatedByOrganizer && !task.mTaskAppearedSent) {
+ // Skip if the task has not yet received taskAppeared(), except for tasks created
+ // by the organizer that don't receive that signal
+ return;
+ }
+ mDeferTaskOrgCallbacksConsumer.accept(() -> {
+ if (!task.isOrganized()) {
+ // This is safe to ignore if the task is no longer organized
+ return;
+ }
+ try {
+ mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
+ }
+ });
+ }
+ }
private class TaskOrganizerState {
- private final ITaskOrganizer mOrganizer;
+ private final TaskOrganizerCallbacks mOrganizer;
private final DeathRecipient mDeathRecipient;
private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
private final int mUid;
private boolean mInterceptBackPressedOnTaskRoot;
TaskOrganizerState(ITaskOrganizer organizer, int uid) {
- mOrganizer = organizer;
+ final Consumer<Runnable> deferTaskOrgCallbacksConsumer =
+ mDeferTaskOrgCallbacksConsumer != null
+ ? mDeferTaskOrgCallbacksConsumer
+ : mService.mWindowManager.mAnimator::addAfterPrepareSurfacesRunnable;
+ mOrganizer = new TaskOrganizerCallbacks(mService.mWindowManager, organizer,
+ deferTaskOrgCallbacksConsumer);
mDeathRecipient = new DeathRecipient(organizer);
try {
organizer.asBinder().linkToDeath(mDeathRecipient, 0);
@@ -112,23 +203,15 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
mOrganizedTasks.add(t);
}
if (t.taskAppearedReady()) {
- try {
- t.mTaskAppearedSent = true;
- mOrganizer.onTaskAppeared(t.getTaskInfo());
- } catch (Exception e) {
- Slog.e(TAG, "Exception sending taskAppeared callback" + e);
- }
+ t.mTaskAppearedSent = true;
+ mOrganizer.onTaskAppeared(t);
}
}
void removeTask(Task t) {
if (t.mTaskAppearedSent) {
- try {
- t.mTaskAppearedSent = false;
- mOrganizer.onTaskVanished(t.getTaskInfo());
- } catch (Exception e) {
- Slog.e(TAG, "Exception sending taskVanished callback" + e);
- }
+ t.mTaskAppearedSent = false;
+ mOrganizer.onTaskVanished(t);
}
mOrganizedTasks.remove(t);
}
@@ -136,7 +219,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
void dispose() {
releaseTasks();
for (int i = mTaskOrganizersForWindowingMode.size() - 1; i >= 0; --i) {
- mTaskOrganizersForWindowingMode.valueAt(i).remove(mOrganizer.asBinder());
+ mTaskOrganizersForWindowingMode.valueAt(i).remove(mOrganizer.getBinder());
}
}
@@ -149,7 +232,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
void unlinkDeath() {
- mOrganizer.asBinder().unlinkToDeath(mDeathRecipient, 0);
+ mOrganizer.getBinder().unlinkToDeath(mDeathRecipient, 0);
}
}
@@ -159,9 +242,10 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>();
- final ActivityTaskManagerService mService;
+ private final ActivityTaskManagerService mService;
- RunningTaskInfo mTmpTaskInfo;
+ private RunningTaskInfo mTmpTaskInfo;
+ private Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
TaskOrganizerController(ActivityTaskManagerService atm) {
mService = atm;
@@ -173,6 +257,15 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
/**
+ * Specifies the consumer to run to defer the task org callbacks. Can be overridden while
+ * testing to allow the callbacks to be sent synchronously.
+ */
+ @VisibleForTesting
+ public void setDeferTaskOrgCallbacksConsumer(Consumer<Runnable> consumer) {
+ mDeferTaskOrgCallbacksConsumer = consumer;
+ }
+
+ /**
* Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
* If there was already a TaskOrganizer for this windowing mode it will be evicted
* but will continue to organize it's existing tasks.
@@ -263,7 +356,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
if (state == null) {
return null;
}
- return state.mOrganizer;
+ return state.mOrganizer.mTaskOrganizer;
}
void onTaskAppeared(ITaskOrganizer organizer, Task task) {
@@ -368,10 +461,15 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
// change.
mTmpTaskInfo = null;
- if (task.mTaskOrganizer != null) {
- try {
- task.mTaskOrganizer.onTaskInfoChanged(newInfo);
- } catch (RemoteException e) {
+ if (task.isOrganized()) {
+ // Because we defer sending taskAppeared() until the app has drawn, we may receive a
+ // configuration change before the state actually has the task registered. As such we
+ // should ignore these change events to the organizer until taskAppeared(). If the task
+ // was created by the organizer, then we always send the info change.
+ final TaskOrganizerState state = mTaskOrganizerStates.get(
+ task.mTaskOrganizer.asBinder());
+ if (state != null) {
+ state.mOrganizer.onTaskInfoChanged(task, newInfo);
}
}
}
@@ -531,11 +629,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
return false;
}
- try {
- state.mOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
- } catch (Exception e) {
- Slog.e(TAG, "Exception sending interceptBackPressedOnTaskRoot callback" + e);
- }
+ state.mOrganizer.onBackPressedOnTaskRoot(task);
return true;
}
@@ -552,7 +646,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
final TaskOrganizerState state = mTaskOrganizerStates.get(taskOrgs.get(j));
final ArrayList<Task> tasks = state.mOrganizedTasks;
pw.print(innerPrefix + " ");
- pw.println(state.mOrganizer + " uid=" + state.mUid + ":");
+ pw.println(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid + ":");
for (int k = 0; k < tasks.size(); k++) {
pw.println(innerPrefix + " " + tasks.get(k));
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 3c0eb88d90fc..ecc07bd4de01 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -2207,6 +2207,11 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
boolean isVoiceInteraction) {
+ if (isOrganized()) {
+ // Defer to the task organizer to run animations
+ return null;
+ }
+
final DisplayContent displayContent = getDisplayContent();
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
final int width = displayInfo.appWidth;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5a76bac67d64..627fdc342a9a 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4274,9 +4274,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
logPerformShow("performShow on ");
final int drawState = mWinAnimator.mDrawState;
- if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW)
- && mAttrs.type != TYPE_APPLICATION_STARTING && mActivityRecord != null) {
- mActivityRecord.onFirstWindowDrawn(this, mWinAnimator);
+ if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW) && mActivityRecord != null) {
+ if (mAttrs.type != TYPE_APPLICATION_STARTING) {
+ mActivityRecord.onFirstWindowDrawn(this, mWinAnimator);
+ } else {
+ mActivityRecord.onStartingWindowDrawn();
+ }
}
if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index 06ca6c110613..f275e378ed26 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -69,6 +69,8 @@ import android.window.WindowContainerTransaction;
import androidx.test.filters.SmallTest;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -117,6 +119,13 @@ public class TaskOrganizerTests extends WindowTestsBase {
return createTaskStackOnDisplay(mDisplayContent);
}
+ @Before
+ public void setUp() {
+ // We defer callbacks since we need to adjust task surface visibility, but for these tests,
+ // just run the callbacks synchronously
+ mWm.mAtmService.mTaskOrganizerController.setDeferTaskOrgCallbacksConsumer((r) -> r.run());
+ }
+
@Test
public void testAppearVanish() throws RemoteException {
final ActivityStack stack = createStack();