From 1c211c2969cbeeb0a38c9abf30195deb05c63a46 Mon Sep 17 00:00:00 2001 From: Yuncheol Heo Date: Mon, 20 Apr 2020 13:08:43 -0700 Subject: [PATCH] Make onTaskDisplayChanged/onTaskRemoved work. - These callbacks are guarded by the condition '!isRootTask' to filter out the unnecessary notifications on the ActivityStack. But, after stack/task merging, the condition blocks the notification on the single task stack. - Adds the test for onTaskDisplayChanged callback. Bug: 152813833 Test: atest TaskStackChangedListenerTest Change-Id: I21312d45de625285c43875a169bffe684e3ba8e3 --- .../core/java/com/android/server/wm/Task.java | 4 +- .../wm/TaskStackChangedListenerTest.java | 83 ++++++++++++++++++- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 2a57fcc9df78e..7a6fb49fc8580 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -641,7 +641,7 @@ class Task extends WindowContainer { return; } removeImmediately(); - if (!isRootTask) { + if (isLeafTask()) { mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId); } } @@ -2777,7 +2777,7 @@ class Task extends WindowContainer { } final DisplayContent prevDc = mDisplayContent; super.onDisplayChanged(dc); - if (!isRootTask) { + if (isLeafTask()) { final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY; mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged( mTaskId, displayId); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java index 6e41118997ac8..9872faaf6582d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java @@ -27,6 +27,7 @@ import static org.junit.Assert.assertTrue; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.TaskDescription; +import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.app.ActivityView; import android.app.IActivityManager; @@ -43,6 +44,7 @@ import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import android.support.test.uiautomator.UiDevice; import android.text.TextUtils; +import android.view.Display; import android.view.ViewGroup; import androidx.test.filters.FlakyTest; @@ -319,15 +321,91 @@ public class TaskStackChangedListenerTest { waitForCallback(singleTaskDisplayEmptyLatch); } + @Test + public void testTaskDisplayChanged() throws Exception { + final CountDownLatch activityViewReadyLatch = new CountDownLatch(1); + final ActivityViewTestActivity activity = + (ActivityViewTestActivity) startTestActivity(ActivityViewTestActivity.class); + final ActivityView activityView = activity.getActivityView(); + activityView.setCallback(new ActivityView.StateCallback() { + @Override + public void onActivityViewReady(ActivityView view) { + activityViewReadyLatch.countDown(); + } + @Override + public void onActivityViewDestroyed(ActivityView view) {} + }); + waitForCallback(activityViewReadyLatch); + + // Launch a Activity inside ActivityView. + final Object[] params1 = new Object[1]; + final CountDownLatch displayChangedLatch1 = new CountDownLatch(1); + final int activityViewDisplayId = activityView.getVirtualDisplayId(); + registerTaskStackChangedListener( + new TaskDisplayChangedListener( + activityViewDisplayId, params1, displayChangedLatch1)); + int taskId1; + ActivityOptions options1 = ActivityOptions.makeBasic() + .setLaunchDisplayId(activityView.getVirtualDisplayId()); + synchronized (sLock) { + taskId1 = startTestActivity(ActivityInActivityView.class, options1).getTaskId(); + } + waitForCallback(displayChangedLatch1); + + assertEquals(taskId1, params1[0]); + + // Launch the Activity in the default display, expects that reparenting happens. + final Object[] params2 = new Object[1]; + final CountDownLatch displayChangedLatch2 = new CountDownLatch(1); + registerTaskStackChangedListener( + new TaskDisplayChangedListener( + Display.DEFAULT_DISPLAY, params2, displayChangedLatch2)); + int taskId2; + ActivityOptions options2 = ActivityOptions.makeBasic() + .setLaunchDisplayId(Display.DEFAULT_DISPLAY); + synchronized (sLock) { + taskId2 = startTestActivity(ActivityInActivityView.class, options2).getTaskId(); + } + waitForCallback(displayChangedLatch2); + + assertEquals(taskId2, params2[0]); + assertEquals(taskId1, taskId2); // TaskId should be same since reparenting happens. + } + + private static class TaskDisplayChangedListener extends TaskStackListener { + private int mDisplayId; + private final Object[] mParams; + private final CountDownLatch mDisplayChangedLatch; + TaskDisplayChangedListener( + int displayId, Object[] params, CountDownLatch displayChangedLatch) { + mDisplayId = displayId; + mParams = params; + mDisplayChangedLatch = displayChangedLatch; + } + @Override + public void onTaskDisplayChanged(int taskId, int displayId) throws RemoteException { + // Filter out the events for the uninterested displays. + // if (displayId != mDisplayId) return; + mParams[0] = taskId; + mDisplayChangedLatch.countDown(); + } + }; + /** * Starts the provided activity and returns the started instance. */ private TestActivity startTestActivity(Class activityClass) throws InterruptedException { + return startTestActivity(activityClass, ActivityOptions.makeBasic()); + } + + private TestActivity startTestActivity(Class activityClass, ActivityOptions options) + throws InterruptedException { final ActivityMonitor monitor = new ActivityMonitor(activityClass.getName(), null, false); getInstrumentation().addMonitor(monitor); final Context context = getInstrumentation().getContext(); context.startActivity( - new Intent(context, activityClass).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + new Intent(context, activityClass).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), + options.toBundle()); final TestActivity activity = (TestActivity) monitor.waitForActivityWithTimeout(1000); if (activity == null) { throw new RuntimeException("Timed out waiting for Activity"); @@ -337,6 +415,9 @@ public class TaskStackChangedListenerTest { } private void registerTaskStackChangedListener(ITaskStackListener listener) throws Exception { + if (mTaskStackListener != null) { + ActivityTaskManager.getService().unregisterTaskStackListener(mTaskStackListener); + } mTaskStackListener = listener; ActivityTaskManager.getService().registerTaskStackListener(listener); }