From ef31d0a35e09969c3163f8a314261aadf90df157 Mon Sep 17 00:00:00 2001 From: helencheuk Date: Sat, 27 Apr 2024 22:04:34 +0100 Subject: [PATCH] Fix performance issue caused by triggering hover focus animation accidentally HoverAnimator and FocusAnimator are triggered unexpectedly on state transition. When it is already disabled, it is disabled again when user swipes to All Apps and triggers animators. Add checking to not trigger animator when the new enable status is the same as the current one. Bug: 333688227 Test: Ran v2/android-crystalball-eng/health/microbench/systemui/main/systemui-misc-1-jank-suite in ab/ Flag: N/A Change-Id: I090490f1c78a3427225c24bc536e1767700ec6c3 --- .../quickstep/views/ClearAllButton.java | 5 +- .../com/android/quickstep/views/TaskView.java | 4 ++ .../com/android/quickstep/TaskViewTest.java | 47 ++++++++++++++++--- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java index b8afd9ddd9..c3efc3cbcf 100644 --- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java +++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java @@ -34,7 +34,6 @@ import androidx.annotation.Nullable; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Flags; import com.android.launcher3.R; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.quickstep.orientation.RecentsPagedOrientationHandler; import com.android.quickstep.util.BorderAnimator; @@ -136,6 +135,10 @@ public class ClearAllButton extends Button { * Enable or disable showing border on focus change */ public void setBorderEnabled(boolean enabled) { + if (mBorderEnabled == enabled) { + return; + } + mBorderEnabled = enabled; if (mFocusBorderAnimator != null) { mFocusBorderAnimator.setBorderVisibility(/* visible= */ diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index c90e789b3b..158c15dfc3 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -583,6 +583,10 @@ public class TaskView extends FrameLayout implements Reusable { * Enable or disable showing border on hover and focus change */ public void setBorderEnabled(boolean enabled) { + if (mBorderEnabled == enabled) { + return; + } + mBorderEnabled = enabled; // Set the animation correctly in case it misses the hover/focus event during state // transition diff --git a/quickstep/tests/src/com/android/quickstep/TaskViewTest.java b/quickstep/tests/src/com/android/quickstep/TaskViewTest.java index 8eec9034ca..512557bf3a 100644 --- a/quickstep/tests/src/com/android/quickstep/TaskViewTest.java +++ b/quickstep/tests/src/com/android/quickstep/TaskViewTest.java @@ -17,9 +17,11 @@ package com.android.quickstep; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -34,7 +36,6 @@ import android.view.MotionEvent; import androidx.test.filters.SmallTest; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.quickstep.util.BorderAnimator; import com.android.quickstep.views.TaskView; @@ -74,6 +75,7 @@ public class TaskViewTest { @Test public void notShowBorderOnBorderDisabled() { + presetBorderStatus(/* enabled= */ true); mTaskView.setBorderEnabled(/* enabled= */ false); MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0); mTaskView.onHoverEvent(MotionEvent.obtain(event)); @@ -86,7 +88,7 @@ public class TaskViewTest { } @Test - public void showBorderOnBorderEnabled() { + public void showBorderOnHoverEvent() { mTaskView.setBorderEnabled(/* enabled= */ true); MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0); mTaskView.onHoverEvent(MotionEvent.obtain(event)); @@ -97,8 +99,19 @@ public class TaskViewTest { true); } + @Test + public void showBorderOnBorderEnabled() { + presetBorderStatus(/* enabled= */ false); + mTaskView.setBorderEnabled(/* enabled= */ true); + verify(mHoverAnimator, times(1)).setBorderVisibility(/* visible= */ true, /* animated= */ + true); + verify(mFocusAnimator, times(1)).setBorderVisibility(/* visible= */ true, /* animated= */ + true); + } + @Test public void hideBorderOnBorderDisabled() { + presetBorderStatus(/* enabled= */ true); mTaskView.setBorderEnabled(/* enabled= */ false); verify(mHoverAnimator, times(1)).setBorderVisibility(/* visible= */ false, /* animated= */ true); @@ -106,14 +119,36 @@ public class TaskViewTest { true); } + @Test + public void notTriggerAnimatorWhenEnableStatusUnchanged() { + presetBorderStatus(/* enabled= */ false); + // Border is disabled by default, no animator is triggered after it is disabled again + mTaskView.setBorderEnabled(/* enabled= */ false); + verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ + anyBoolean(), /* animated= */ anyBoolean()); + verify(mFocusAnimator, never()).setBorderVisibility(/* visible= */ + anyBoolean(), /* animated= */ anyBoolean()); + } + + private void presetBorderStatus(boolean enabled) { + // Make the task view focused and hovered + MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0); + mTaskView.onHoverEvent(MotionEvent.obtain(event)); + mTaskView.requestFocus(); + mTaskView.setBorderEnabled(/* enabled= */ enabled); + // Reset invocation count after presetting status + reset(mHoverAnimator); + reset(mFocusAnimator); + } + @Test public void notShowBorderByDefault() { MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0); mTaskView.onHoverEvent(MotionEvent.obtain(event)); - verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ false, /* animated= */ - true); + verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ + anyBoolean(), /* animated= */ anyBoolean()); mTaskView.onFocusChanged(true, 0, new Rect()); - verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ false, /* animated= */ - true); + verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ + anyBoolean(), /* animated= */ anyBoolean()); } }