diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java index 2b976df802..439d632fb7 100644 --- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java @@ -18,6 +18,7 @@ package com.android.launcher3.taskbar; 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 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT 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 8a5b2c5e17..5e64a57d5c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -239,7 +239,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext { 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 @@ public class TaskbarActivityContext extends BaseTaskbarContext { 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 @@ public class TaskbarActivityContext extends BaseTaskbarContext { 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 1f3eac09df..267bee1670 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java @@ -49,6 +49,8 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa 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 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa mKeyguardBgTaskbar.value = 1; mNotificationShadeBgTaskbar.value = 1; mImeBgTaskbar.value = 1; + mAssistantBgTaskbar.value = 1; mBgOverride.value = 1; updateBackgroundAlpha(); } @@ -120,6 +123,10 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa return mImeBgTaskbar; } + public AnimatedFloat getAssistantBgTaskbar() { + return mAssistantBgTaskbar; + } + public AnimatedFloat getOverrideBackgroundAlpha() { return mBgOverride; } @@ -144,7 +151,8 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa 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 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa 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 c4d1ab2c30..faf7451999 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt @@ -151,7 +151,7 @@ class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) : } 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 7b5773afe4..7a5deb74f1 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 - private lateinit var separateWindowLayoutParams: WindowManager.LayoutParams + // Only initialized if isSeparateBackgroundEnabled + private var separateWindowForTaskbarBackground: BaseDragLayer? = 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(context, null, 0) { override fun recreateControllers() { @@ -38,17 +77,35 @@ class VoiceInteractionWindowController(val context: TaskbarActivityContext) : 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 @@ class VoiceInteractionWindowController(val context: TaskbarActivityContext) : .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 @@ class VoiceInteractionWindowController(val context: TaskbarActivityContext) : 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}" + ) } }