Fixes to VoiceInteractionWindowController
- Make temporary taskbar background behind assistant non-touchable
(fail-safe in case the window isn't removed for some reason)
- Give temporary taskbar background a different window title and
add a couple more dump statements to help debugging
- Only show the taskbar background for persistent taskbar; transient
taskbar can skip most of the special casing and just hide it
- Fix bug where we weren't drawing the separate taskbar background in 3
button mode
- Fix bug where we weren't actually synchronizing
separateWindowForTaskbarBackground with TaskbarDragLayer, since the
former wasn't attached to the window yet; now we wait until it is
attached before calling synchronizeNextDraw()
- Also added dump logs for TaskbarDragLayerController alpha channels
Test: manual in 3 button and gesture nav (with and without
FORCE_PERSISTENT_TASKBAR enabled)
Fixes: 243652789
Bug: 262664266
Change-Id: I865871e57dd4cb255a916317a7e5d35cfde97df5
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 2b976df..439d632 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -18,6 +18,7 @@
import static android.view.View.AccessibilityDelegate;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
@@ -870,8 +871,8 @@
mAreNavButtonsInSeparateWindow = true;
mContext.getDragLayer().removeView(mNavButtonsView);
mSeparateWindowParent.addView(mNavButtonsView);
- WindowManager.LayoutParams windowLayoutParams = mContext.createDefaultWindowLayoutParams();
- windowLayoutParams.setTitle(NAV_BUTTONS_SEPARATE_WINDOW_TITLE);
+ WindowManager.LayoutParams windowLayoutParams = mContext.createDefaultWindowLayoutParams(
+ TYPE_NAVIGATION_BAR_PANEL, NAV_BUTTONS_SEPARATE_WINDOW_TITLE);
mContext.addWindowView(mSeparateWindowParent, windowLayoutParams);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 8a5b2c5..5e64a57 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -239,7 +239,8 @@
public void init(@NonNull TaskbarSharedState sharedState) {
mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight();
- mWindowLayoutParams = createDefaultWindowLayoutParams();
+ mWindowLayoutParams =
+ createDefaultWindowLayoutParams(TYPE_NAVIGATION_BAR_PANEL, WINDOW_TITLE);
// Initialize controllers after all are constructed.
mControllers.init(sharedState);
@@ -315,16 +316,12 @@
return super.getStatsLogManager();
}
- /** @see #createDefaultWindowLayoutParams(int) */
- public WindowManager.LayoutParams createDefaultWindowLayoutParams() {
- return createDefaultWindowLayoutParams(TYPE_NAVIGATION_BAR_PANEL);
- }
-
/**
* Creates LayoutParams for adding a view directly to WindowManager as a new window.
* @param type The window type to pass to the created WindowManager.LayoutParams.
+ * @param title The window title to pass to the created WindowManager.LayoutParams.
*/
- public WindowManager.LayoutParams createDefaultWindowLayoutParams(int type) {
+ public WindowManager.LayoutParams createDefaultWindowLayoutParams(int type, String title) {
DeviceProfile deviceProfile = getDeviceProfile();
// Taskbar is on the logical bottom of the screen
boolean isVerticalBarLayout = TaskbarManager.isPhoneMode(deviceProfile) &&
@@ -344,7 +341,7 @@
type,
windowFlags,
PixelFormat.TRANSLUCENT);
- windowLayoutParams.setTitle(WINDOW_TITLE);
+ windowLayoutParams.setTitle(title);
windowLayoutParams.packageName = getPackageName();
windowLayoutParams.gravity = !isVerticalBarLayout ?
Gravity.BOTTOM :
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 1f3eac0..267bee1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -49,6 +49,8 @@
private final AnimatedFloat mNotificationShadeBgTaskbar = new AnimatedFloat(
this::updateBackgroundAlpha);
private final AnimatedFloat mImeBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha);
+ private final AnimatedFloat mAssistantBgTaskbar = new AnimatedFloat(
+ this::updateBackgroundAlpha);
// Used to hide our background color when someone else (e.g. ScrimView) is handling it.
private final AnimatedFloat mBgOverride = new AnimatedFloat(this::updateBackgroundAlpha);
@@ -82,6 +84,7 @@
mKeyguardBgTaskbar.value = 1;
mNotificationShadeBgTaskbar.value = 1;
mImeBgTaskbar.value = 1;
+ mAssistantBgTaskbar.value = 1;
mBgOverride.value = 1;
updateBackgroundAlpha();
}
@@ -120,6 +123,10 @@
return mImeBgTaskbar;
}
+ public AnimatedFloat getAssistantBgTaskbar() {
+ return mAssistantBgTaskbar;
+ }
+
public AnimatedFloat getOverrideBackgroundAlpha() {
return mBgOverride;
}
@@ -144,7 +151,8 @@
private void updateBackgroundAlpha() {
final float bgNavbar = mBgNavbar.value;
final float bgTaskbar = mBgTaskbar.value * mKeyguardBgTaskbar.value
- * mNotificationShadeBgTaskbar.value * mImeBgTaskbar.value;
+ * mNotificationShadeBgTaskbar.value * mImeBgTaskbar.value
+ * mAssistantBgTaskbar.value;
mLastSetBackgroundAlpha = mBgOverride.value * Math.max(bgNavbar, bgTaskbar);
mTaskbarDragLayer.setTaskbarBackgroundAlpha(mLastSetBackgroundAlpha);
@@ -196,6 +204,13 @@
pw.println(prefix + "\tmBgOffset=" + mBgOffset.value);
pw.println(prefix + "\tmFolderMargin=" + mFolderMargin);
pw.println(prefix + "\tmLastSetBackgroundAlpha=" + mLastSetBackgroundAlpha);
+ pw.println(prefix + "\t\tmBgOverride=" + mBgOverride.value);
+ pw.println(prefix + "\t\tmBgNavbar=" + mBgNavbar.value);
+ pw.println(prefix + "\t\tmBgTaskbar=" + mBgTaskbar.value);
+ pw.println(prefix + "\t\tmKeyguardBgTaskbar=" + mKeyguardBgTaskbar.value);
+ pw.println(prefix + "\t\tmNotificationShadeBgTaskbar=" + mNotificationShadeBgTaskbar.value);
+ pw.println(prefix + "\t\tmImeBgTaskbar=" + mImeBgTaskbar.value);
+ pw.println(prefix + "\t\tmAssistantBgTaskbar=" + mAssistantBgTaskbar.value);
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index c4d1ab2..faf7451 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -151,7 +151,7 @@
}
override fun dumpLogs(prefix: String?, pw: PrintWriter?) {
- pw?.println("$(prefix)TaskbarEduController:")
+ pw?.println(prefix + "TaskbarEduTooltipController:")
pw?.println("$prefix\tisTooltipEnabled=$isTooltipEnabled")
pw?.println("$prefix\tisOpen=$isOpen")
pw?.println("$prefix\ttooltipStep=$tooltipStep")
diff --git a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
index 7b5773a..7a5deb7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
@@ -1,31 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.launcher3.taskbar
+import android.animation.AnimatorSet
import android.graphics.Canvas
+import android.view.View
+import android.view.ViewTreeObserver
+import android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION
import android.view.WindowManager
import android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
+import com.android.launcher3.util.DisplayController
import com.android.launcher3.views.BaseDragLayer
import com.android.systemui.animation.ViewRootSync
import java.io.PrintWriter
private const val TASKBAR_ICONS_FADE_DURATION = 300L
private const val STASHED_HANDLE_FADE_DURATION = 180L
+private const val TEMP_BACKGROUND_WINDOW_TITLE = "VoiceInteractionTaskbarBackground"
-/** Controls Taskbar behavior while Voice Interaction Window (assistant) is showing. */
+/**
+ * Controls Taskbar behavior while Voice Interaction Window (assistant) is showing. Specifically:
+ * - We always hide the taskbar icons or stashed handle, whichever is currently showing.
+ * - For persistent taskbar, we also move the taskbar background to a new window/layer
+ * (TYPE_APPLICATION_OVERLAY) which is behind the assistant.
+ * - For transient taskbar, we hide the real taskbar background (if it's showing).
+ */
class VoiceInteractionWindowController(val context: TaskbarActivityContext) :
TaskbarControllers.LoggableTaskbarController, TaskbarControllers.BackgroundRendererController {
+ private val isSeparateBackgroundEnabled = !DisplayController.isTransientTaskbar(context)
private val taskbarBackgroundRenderer = TaskbarBackgroundRenderer(context)
+ private val nonTouchableInsetsComputer =
+ ViewTreeObserver.OnComputeInternalInsetsListener {
+ it.touchableRegion.setEmpty()
+ it.setTouchableInsets(TOUCHABLE_INSETS_REGION)
+ }
// Initialized in init.
private lateinit var controllers: TaskbarControllers
- private lateinit var separateWindowForTaskbarBackground: BaseDragLayer<TaskbarActivityContext>
- private lateinit var separateWindowLayoutParams: WindowManager.LayoutParams
+ // Only initialized if isSeparateBackgroundEnabled
+ private var separateWindowForTaskbarBackground: BaseDragLayer<TaskbarActivityContext>? = null
+ private var separateWindowLayoutParams: WindowManager.LayoutParams? = null
private var isVoiceInteractionWindowVisible: Boolean = false
+ private var pendingAttachedToWindowListener: View.OnAttachStateChangeListener? = null
fun init(controllers: TaskbarControllers) {
this.controllers = controllers
+ if (!isSeparateBackgroundEnabled) {
+ return
+ }
+
separateWindowForTaskbarBackground =
object : BaseDragLayer<TaskbarActivityContext>(context, null, 0) {
override fun recreateControllers() {
@@ -38,17 +77,35 @@
taskbarBackgroundRenderer.draw(canvas)
}
}
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ viewTreeObserver.addOnComputeInternalInsetsListener(nonTouchableInsetsComputer)
+ }
+
+ override fun onDetachedFromWindow() {
+ super.onDetachedFromWindow()
+ viewTreeObserver.removeOnComputeInternalInsetsListener(
+ nonTouchableInsetsComputer
+ )
+ }
}
- separateWindowForTaskbarBackground.recreateControllers()
- separateWindowForTaskbarBackground.setWillNotDraw(false)
+ separateWindowForTaskbarBackground?.recreateControllers()
+ separateWindowForTaskbarBackground?.setWillNotDraw(false)
separateWindowLayoutParams =
- context.createDefaultWindowLayoutParams(TYPE_APPLICATION_OVERLAY)
- separateWindowLayoutParams.isSystemApplicationOverlay = true
+ context.createDefaultWindowLayoutParams(
+ TYPE_APPLICATION_OVERLAY,
+ TEMP_BACKGROUND_WINDOW_TITLE
+ )
+ separateWindowLayoutParams?.isSystemApplicationOverlay = true
}
fun onDestroy() {
setIsVoiceInteractionWindowVisible(visible = false, skipAnim = true)
+ separateWindowForTaskbarBackground?.removeOnAttachStateChangeListener(
+ pendingAttachedToWindowListener
+ )
}
fun setIsVoiceInteractionWindowVisible(visible: Boolean, skipAnim: Boolean) {
@@ -69,14 +126,24 @@
.get(StashedHandleViewController.ALPHA_INDEX_ASSISTANT_INVOKED)
.animateToValue(taskbarIconAlpha)
.setDuration(STASHED_HANDLE_FADE_DURATION)
- fadeTaskbarIcons.start()
- fadeStashedHandle.start()
+ val animSet = AnimatorSet()
+ animSet.play(fadeTaskbarIcons)
+ animSet.play(fadeStashedHandle)
+ if (!isSeparateBackgroundEnabled) {
+ val fadeTaskbarBackground =
+ controllers.taskbarDragLayerController.assistantBgTaskbar
+ .animateToValue(taskbarIconAlpha)
+ .setDuration(TASKBAR_ICONS_FADE_DURATION)
+ animSet.play(fadeTaskbarBackground)
+ }
+ animSet.start()
if (skipAnim) {
- fadeTaskbarIcons.end()
- fadeStashedHandle.end()
+ animSet.end()
}
- moveTaskbarBackgroundToAppropriateLayer(skipAnim)
+ if (isSeparateBackgroundEnabled) {
+ moveTaskbarBackgroundToAppropriateLayer(skipAnim)
+ }
}
/**
@@ -107,21 +174,50 @@
if (skipAnim) {
onWindowsSynchronized()
} else {
- ViewRootSync.synchronizeNextDraw(
- separateWindowForTaskbarBackground,
- context.dragLayer,
- onWindowsSynchronized
- )
+ separateWindowForTaskbarBackground?.runWhenAttachedToWindow {
+ ViewRootSync.synchronizeNextDraw(
+ separateWindowForTaskbarBackground!!,
+ context.dragLayer,
+ onWindowsSynchronized
+ )
+ }
}
}
+ private fun View.runWhenAttachedToWindow(onAttachedToWindow: () -> Unit) {
+ if (isAttachedToWindow) {
+ onAttachedToWindow()
+ return
+ }
+ removeOnAttachStateChangeListener(pendingAttachedToWindowListener)
+ pendingAttachedToWindowListener =
+ object : View.OnAttachStateChangeListener {
+ override fun onViewAttachedToWindow(v: View?) {
+ onAttachedToWindow()
+ removeOnAttachStateChangeListener(this)
+ pendingAttachedToWindowListener = null
+ }
+
+ override fun onViewDetachedFromWindow(v: View?) {}
+ }
+ addOnAttachStateChangeListener(pendingAttachedToWindowListener)
+ }
+
override fun setCornerRoundness(cornerRoundness: Float) {
+ if (!isSeparateBackgroundEnabled) {
+ return
+ }
taskbarBackgroundRenderer.setCornerRoundness(cornerRoundness)
- separateWindowForTaskbarBackground.invalidate()
+ separateWindowForTaskbarBackground?.invalidate()
}
override fun dumpLogs(prefix: String, pw: PrintWriter) {
pw.println(prefix + "VoiceInteractionWindowController:")
+ pw.println("$prefix\tisSeparateBackgroundEnabled=$isSeparateBackgroundEnabled")
pw.println("$prefix\tisVoiceInteractionWindowVisible=$isVoiceInteractionWindowVisible")
+ pw.println(
+ "$prefix\tisSeparateTaskbarBackgroundAttachedToWindow=" +
+ "${separateWindowForTaskbarBackground?.isAttachedToWindow}"
+ )
}
}