Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3963a7f authored by Tony Wickham's avatar Tony Wickham
Browse files

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
parent b9ecff07
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -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);

    }
+5 −8
Original line number Diff line number Diff line
@@ -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 :
+16 −1
Original line number Diff line number Diff line
@@ -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);
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -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")
+115 −19
Original line number Diff line number Diff line
/*
 * 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 @@ 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,15 +126,25 @@ 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()
        }

        if (isSeparateBackgroundEnabled) {
            moveTaskbarBackgroundToAppropriateLayer(skipAnim)
        }
    }

    /**
     * Either:
@@ -107,21 +174,50 @@ class VoiceInteractionWindowController(val context: TaskbarActivityContext) :
        if (skipAnim) {
            onWindowsSynchronized()
        } else {
            separateWindowForTaskbarBackground?.runWhenAttachedToWindow {
                ViewRootSync.synchronizeNextDraw(
                separateWindowForTaskbarBackground,
                    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}"
        )
    }
}