diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java index f9fc9832c8..491938d2b5 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java @@ -169,6 +169,7 @@ public class TaskbarDragLayer extends BaseDragLayer { mBackgroundRenderer.setBackgroundProgress(mTaskbarBackgroundProgress); mBackgroundRenderer.draw(canvas); super.dispatchDraw(canvas); + mControllerCallbacks.drawDebugUi(canvas); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java index 3823c5a098..3f5402fc16 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java @@ -19,8 +19,10 @@ import static com.android.launcher3.taskbar.TaskbarPinningController.PINNING_PER import static com.android.launcher3.taskbar.TaskbarPinningController.PINNING_TRANSIENT; import android.content.res.Resources; +import android.graphics.Canvas; import android.graphics.Point; import android.graphics.Rect; +import android.os.SystemProperties; import android.view.ViewTreeObserver; import com.android.launcher3.DeviceProfile; @@ -39,6 +41,9 @@ import java.io.PrintWriter; public class TaskbarDragLayerController implements TaskbarControllers.LoggableTaskbarController, TaskbarControllers.BackgroundRendererController { + private static final boolean DEBUG = SystemProperties.getBoolean( + "persist.debug.draw_taskbar_debug_ui", false); + private final TaskbarActivityContext mActivity; private final TaskbarDragLayer mTaskbarDragLayer; private final int mFolderMargin; @@ -299,5 +304,15 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa mTaskbarStashViaTouchController, }; } + + /** + * Draws debug UI on top of everything in TaskbarDragLayer. + */ + public void drawDebugUi(Canvas canvas) { + if (!DEBUG) { + return; + } + mControllers.taskbarInsetsController.drawDebugTouchableRegionBounds(canvas); + } } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index 7ebc18d6e0..a12ee81036 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -15,7 +15,11 @@ */ package com.android.launcher3.taskbar +import android.graphics.Canvas +import android.graphics.Color import android.graphics.Insets +import android.graphics.Paint +import android.graphics.Rect import android.graphics.Region import android.inputmethodservice.InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR import android.os.Binder @@ -47,6 +51,7 @@ import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarControlle import com.android.launcher3.util.DisplayController import java.io.PrintWriter import kotlin.jvm.optionals.getOrNull +import kotlin.math.max /** Handles the insets that Taskbar provides to underlying apps and the IME. */ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTaskbarController { @@ -58,7 +63,8 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas /** The bottom insets taskbar provides to the IME when IME is visible. */ val taskbarHeightForIme: Int = context.resources.getDimensionPixelSize(R.dimen.taskbar_ime_size) - private val touchableRegion: Region = Region() + // The touchableRegion we will set unless some other state takes precedence. + private val defaultTouchableRegion: Region = Region() private val insetsOwner: IBinder = Binder() private val deviceProfileChangeListener = { _: DeviceProfile -> onTaskbarOrBubblebarWindowHeightOrInsetsChanged() @@ -69,6 +75,7 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas context, this::onTaskbarOrBubblebarWindowHeightOrInsetsChanged ) + private val debugTouchableRegion = DebugTouchableRegion() // Initialized in init. private lateinit var controllers: TaskbarControllers @@ -124,7 +131,7 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas } else { 0 } - val touchableHeight = Math.max(taskbarTouchableHeight, bubblesTouchableHeight) + val touchableHeight = max(taskbarTouchableHeight, bubblesTouchableHeight) if ( controllers.bubbleControllers.isPresent && @@ -132,14 +139,14 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas ) { val iconBounds = controllers.bubbleControllers.get().bubbleBarViewController.bubbleBarBounds - touchableRegion.set( + defaultTouchableRegion.set( iconBounds.left, iconBounds.top, iconBounds.right, iconBounds.bottom ) } else { - touchableRegion.set( + defaultTouchableRegion.set( 0, windowLayoutParams.height - touchableHeight, context.deviceProfile.widthPx, @@ -296,6 +303,8 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas context.dragLayer, insetsInfo.touchableRegion ) + debugTouchableRegion.lastSetTouchableBounds.set(insetsInfo.touchableRegion.bounds) + val bubbleBarVisible = controllers.bubbleControllers.isPresent && controllers.bubbleControllers.get().bubbleBarViewController.isBubbleBarVisible() @@ -303,21 +312,28 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas if (context.dragLayer.alpha < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) { // Let touches pass through us. insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION) + debugTouchableRegion.lastSetTouchableReason = "Taskbar is invisible" } else if ( controllers.navbarButtonsViewController.isImeVisible && controllers.taskbarStashController.isStashed ) { + // Let touches pass through us. insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION) + debugTouchableRegion.lastSetTouchableReason = "Stashed over IME" } else if (!controllers.uiController.isTaskbarTouchable) { // Let touches pass through us. insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION) + debugTouchableRegion.lastSetTouchableReason = "Taskbar is not touchable" } else if (controllers.taskbarDragController.isSystemDragInProgress) { // Let touches pass through us. insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION) + debugTouchableRegion.lastSetTouchableReason = "System drag is in progress" } else if (context.isTaskbarWindowFullscreen) { // Intercept entire fullscreen window. insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME) insetsIsTouchableRegion = false + debugTouchableRegion.lastSetTouchableReason = "Taskbar is fullscreen" + context.dragLayer.getBoundsInWindow(debugTouchableRegion.lastSetTouchableBounds, false) } else if ( controllers.taskbarViewController.areIconsVisible() || context.isNavBarKidsModeActive || @@ -346,19 +362,33 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas region.op(bubbleBarBounds, Region.Op.UNION) } insetsInfo.touchableRegion.set(region) + debugTouchableRegion.lastSetTouchableReason = "Transient Taskbar is in Overview" + debugTouchableRegion.lastSetTouchableBounds.set(region.bounds) } else { - insetsInfo.touchableRegion.set(touchableRegion) + insetsInfo.touchableRegion.set(defaultTouchableRegion) + debugTouchableRegion.lastSetTouchableReason = "Using default touchable region" + debugTouchableRegion.lastSetTouchableBounds.set(defaultTouchableRegion.bounds) } insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION) insetsIsTouchableRegion = false } else { insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION) + debugTouchableRegion.lastSetTouchableReason = + "Icons are not visible, but other components such as 3 buttons might be" } context.excludeFromMagnificationRegion(insetsIsTouchableRegion) } + /** Draws the last set touchableRegion as a red rectangle onto the given Canvas. */ + fun drawDebugTouchableRegionBounds(canvas: Canvas) { + val paint = Paint() + paint.color = Color.RED + paint.style = Paint.Style.STROKE + canvas.drawRect(debugTouchableRegion.lastSetTouchableBounds, paint) + } + override fun dumpLogs(prefix: String, pw: PrintWriter) { - pw.println(prefix + "TaskbarInsetsController:") + pw.println("${prefix}TaskbarInsetsController:") pw.println("$prefix\twindowHeight=${windowLayoutParams.height}") for (provider in windowLayoutParams.providedInsets) { pw.print( @@ -377,5 +407,12 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas } pw.println() } + pw.println("$prefix\tlastSetTouchableBounds=${debugTouchableRegion.lastSetTouchableBounds}") + pw.println("$prefix\tlastSetTouchableReason=${debugTouchableRegion.lastSetTouchableReason}") + } + + class DebugTouchableRegion { + val lastSetTouchableBounds = Rect() + var lastSetTouchableReason = "" } } diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java index c9e536a737..b165876895 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java @@ -17,16 +17,23 @@ package com.android.quickstep; import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT; +import android.graphics.Rect; + import androidx.test.filters.LargeTest; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape; import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch; import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch; +import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; +import java.io.Closeable; +import java.io.IOException; + @LargeTest @RunWith(AndroidJUnit4.class) public class TaplTestsPersistentTaskbar extends AbstractTaplTestsTaskbar { @@ -39,4 +46,28 @@ public class TaplTestsPersistentTaskbar extends AbstractTaplTestsTaskbar { // Width check is performed inside TAPL whenever getTaskbar() is called. getTaskbar(); } + + @Test + @NavigationModeSwitch(mode = NavigationModeSwitchRule.Mode.THREE_BUTTON) + public void testThreeButtonsTaskbarBoundsAfterConfigChangeDuringIme() { + // Start off in light mode. + try (Closeable c = InstrumentationRegistry.getInstrumentation().getUiAutomation() + .executeShellCommand("cmd uimode night no")) { + Rect taskbarBoundsBefore = getTaskbar().getVisibleBounds(); + startImeTestActivity(); + // IME should stash the taskbar, which hides icons even in 3 button mode. + mLauncher.getLaunchedAppState().assertTaskbarHidden(); + // Switch to dark mode (any configuration change here would do). + InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand( + "cmd uimode night yes").close(); + // Close IME to check new taskbar bounds. + mLauncher.pressBack(); + Rect taskbarBoundsAfter = getTaskbar().getVisibleBounds(); + Assert.assertEquals( + "Taskbar bounds are not the same after a configuration change while stashed.", + taskbarBoundsBefore, taskbarBoundsAfter); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/tests/tapl/com/android/launcher3/tapl/Taskbar.java b/tests/tapl/com/android/launcher3/tapl/Taskbar.java index a202c53375..e6315f3d3b 100644 --- a/tests/tapl/com/android/launcher3/tapl/Taskbar.java +++ b/tests/tapl/com/android/launcher3/tapl/Taskbar.java @@ -153,7 +153,7 @@ public final class Taskbar { return By.clazz(TextView.class).text(""); } - private Rect getVisibleBounds() { + public Rect getVisibleBounds() { return mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID).getVisibleBounds(); }