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

Commit 5671aa9f authored by Shivangi Dubey's avatar Shivangi Dubey Committed by Android (Google) Code Review
Browse files

Merge "Set tooltip color scheme to match app scheme" into main

parents 6f797c8a 7d94df70
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -22,6 +22,6 @@
    android:viewportHeight="960"
    android:viewportHeight="960"
    android:viewportWidth="960">
    android:viewportWidth="960">
    <path
    <path
        android:fillColor="@android:color/system_on_tertiary_fixed"
        android:fillColor="@android:color/system_on_tertiary_container_light"
        android:pathData="M419,880Q391,880 366.5,868Q342,856 325,834L107,557L126,537Q146,516 174,512Q202,508 226,523L300,568L300,240Q300,223 311.5,211.5Q323,200 340,200Q357,200 369,211.5Q381,223 381,240L381,712L284,652L388,785Q394,792 402,796Q410,800 419,800L640,800Q673,800 696.5,776.5Q720,753 720,720L720,560Q720,543 708.5,531.5Q697,520 680,520L461,520L461,440L680,440Q730,440 765,475Q800,510 800,560L800,720Q800,786 753,833Q706,880 640,880L419,880ZM167,340Q154,318 147,292.5Q140,267 140,240Q140,157 198.5,98.5Q257,40 340,40Q423,40 481.5,98.5Q540,157 540,240Q540,267 533,292.5Q526,318 513,340L444,300Q452,286 456,271.5Q460,257 460,240Q460,190 425,155Q390,120 340,120Q290,120 255,155Q220,190 220,240Q220,257 224,271.5Q228,286 236,300L167,340ZM502,620L502,620L502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620L502,620Z" />
        android:pathData="M419,880Q391,880 366.5,868Q342,856 325,834L107,557L126,537Q146,516 174,512Q202,508 226,523L300,568L300,240Q300,223 311.5,211.5Q323,200 340,200Q357,200 369,211.5Q381,223 381,240L381,712L284,652L388,785Q394,792 402,796Q410,800 419,800L640,800Q673,800 696.5,776.5Q720,753 720,720L720,560Q720,543 708.5,531.5Q697,520 680,520L461,520L461,440L680,440Q730,440 765,475Q800,510 800,560L800,720Q800,786 753,833Q706,880 640,880L419,880ZM167,340Q154,318 147,292.5Q140,267 140,240Q140,157 198.5,98.5Q257,40 340,40Q423,40 481.5,98.5Q540,157 540,240Q540,267 533,292.5Q526,318 513,340L444,300Q452,286 456,271.5Q460,257 460,240Q460,190 425,155Q390,120 340,120Q290,120 255,155Q220,190 220,240Q220,257 224,271.5Q228,286 236,300L167,340ZM502,620L502,620L502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620L502,620Z" />
</vector>
</vector>
+1 −1
Original line number Original line Diff line number Diff line
@@ -37,7 +37,7 @@
        android:layout_marginStart="2dp"
        android:layout_marginStart="2dp"
        android:lineHeight="20dp"
        android:lineHeight="20dp"
        android:maxWidth="150dp"
        android:maxWidth="150dp"
        android:textColor="@android:color/system_on_tertiary_fixed"
        android:textColor="@android:color/system_on_tertiary_container_light"
        android:textFontWeight="500"
        android:textFontWeight="500"
        android:textSize="14sp" />
        android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
 No newline at end of file
+48 −8
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.res.Resources
import android.graphics.Point
import android.graphics.Point
import android.os.SystemProperties
import android.os.SystemProperties
import android.util.Slog
import android.util.Slog
import androidx.core.content.withStyledAttributes
import com.android.window.flags.Flags
import com.android.window.flags.Flags
import com.android.wm.shell.R
import com.android.wm.shell.R
import com.android.wm.shell.desktopmode.CaptionState
import com.android.wm.shell.desktopmode.CaptionState
@@ -32,8 +33,11 @@ import com.android.wm.shell.shared.annotations.ShellBackgroundThread
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.canEnterDesktopMode
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.canEnterDesktopMode
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource
import com.android.wm.shell.windowdecor.common.DecorThemeUtil
import com.android.wm.shell.windowdecor.common.Theme
import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController
import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController
import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController.EducationViewConfig
import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController.EducationViewConfig
import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController.TooltipColorScheme
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainCoroutineDispatcher
import kotlinx.coroutines.MainCoroutineDispatcher
@@ -70,6 +74,7 @@ class AppHandleEducationController(
    @ShellMainThread private val applicationCoroutineScope: CoroutineScope,
    @ShellMainThread private val applicationCoroutineScope: CoroutineScope,
    @ShellBackgroundThread private val backgroundDispatcher: MainCoroutineDispatcher,
    @ShellBackgroundThread private val backgroundDispatcher: MainCoroutineDispatcher,
) {
) {
  private val decorThemeUtil = DecorThemeUtil(context)
  private lateinit var openHandleMenuCallback: (Int) -> Unit
  private lateinit var openHandleMenuCallback: (Int) -> Unit
  private lateinit var toDesktopModeCallback: (Int, DesktopModeTransitionSource) -> Unit
  private lateinit var toDesktopModeCallback: (Int, DesktopModeTransitionSource) -> Unit


@@ -97,7 +102,9 @@ class AppHandleEducationController(
            }
            }
            .flowOn(backgroundDispatcher)
            .flowOn(backgroundDispatcher)
            .collectLatest { captionState ->
            .collectLatest { captionState ->
              showEducation(captionState)
              val tooltipColorScheme = tooltipColorScheme(captionState)

              showEducation(captionState, tooltipColorScheme)
              // After showing first tooltip, mark education as viewed
              // After showing first tooltip, mark education as viewed
              appHandleEducationDatastoreRepository.updateEducationViewedTimestampMillis(true)
              appHandleEducationDatastoreRepository.updateEducationViewedTimestampMillis(true)
            }
            }
@@ -123,7 +130,7 @@ class AppHandleEducationController(
    if (canEnterDesktopMode(context) && Flags.enableDesktopWindowingAppHandleEducation()) block()
    if (canEnterDesktopMode(context) && Flags.enableDesktopWindowingAppHandleEducation()) block()
  }
  }


  private fun showEducation(captionState: CaptionState) {
  private fun showEducation(captionState: CaptionState, tooltipColorScheme: TooltipColorScheme) {
    val appHandleBounds = (captionState as CaptionState.AppHandle).globalAppHandleBounds
    val appHandleBounds = (captionState as CaptionState.AppHandle).globalAppHandleBounds
    val tooltipGlobalCoordinates =
    val tooltipGlobalCoordinates =
        Point(appHandleBounds.left + appHandleBounds.width() / 2, appHandleBounds.bottom)
        Point(appHandleBounds.left + appHandleBounds.width() / 2, appHandleBounds.bottom)
@@ -132,14 +139,17 @@ class AppHandleEducationController(
    val appHandleTooltipConfig =
    val appHandleTooltipConfig =
        EducationViewConfig(
        EducationViewConfig(
            tooltipViewLayout = R.layout.desktop_windowing_education_top_arrow_tooltip,
            tooltipViewLayout = R.layout.desktop_windowing_education_top_arrow_tooltip,
            tooltipColorScheme = tooltipColorScheme,
            tooltipViewGlobalCoordinates = tooltipGlobalCoordinates,
            tooltipViewGlobalCoordinates = tooltipGlobalCoordinates,
            tooltipText = getString(R.string.windowing_app_handle_education_tooltip),
            tooltipText = getString(R.string.windowing_app_handle_education_tooltip),
            arrowDirection = DesktopWindowingEducationTooltipController.TooltipArrowDirection.UP,
            arrowDirection = DesktopWindowingEducationTooltipController.TooltipArrowDirection.UP,
            onEducationClickAction = {
            onEducationClickAction = {
              launchWithExceptionHandling { showWindowingImageButtonTooltip() }
              launchWithExceptionHandling { showWindowingImageButtonTooltip(tooltipColorScheme) }
              openHandleMenuCallback(captionState.runningTaskInfo.taskId)
              openHandleMenuCallback(captionState.runningTaskInfo.taskId)
            },
            },
            onDismissAction = { launchWithExceptionHandling { showWindowingImageButtonTooltip() } },
            onDismissAction = {
              launchWithExceptionHandling { showWindowingImageButtonTooltip(tooltipColorScheme) }
            },
        )
        )


    windowingEducationViewController.showEducationTooltip(
    windowingEducationViewController.showEducationTooltip(
@@ -147,7 +157,7 @@ class AppHandleEducationController(
  }
  }


  /** Show tooltip that points to windowing image button in app handle menu */
  /** Show tooltip that points to windowing image button in app handle menu */
  private suspend fun showWindowingImageButtonTooltip() {
  private suspend fun showWindowingImageButtonTooltip(tooltipColorScheme: TooltipColorScheme) {
    val appInfoPillHeight = getSize(R.dimen.desktop_mode_handle_menu_app_info_pill_height)
    val appInfoPillHeight = getSize(R.dimen.desktop_mode_handle_menu_app_info_pill_height)
    val windowingOptionPillHeight = getSize(R.dimen.desktop_mode_handle_menu_windowing_pill_height)
    val windowingOptionPillHeight = getSize(R.dimen.desktop_mode_handle_menu_windowing_pill_height)
    val appHandleMenuWidth =
    val appHandleMenuWidth =
@@ -188,18 +198,21 @@ class AppHandleEducationController(
          val windowingImageButtonTooltipConfig =
          val windowingImageButtonTooltipConfig =
              EducationViewConfig(
              EducationViewConfig(
                  tooltipViewLayout = R.layout.desktop_windowing_education_left_arrow_tooltip,
                  tooltipViewLayout = R.layout.desktop_windowing_education_left_arrow_tooltip,
                  tooltipColorScheme = tooltipColorScheme,
                  tooltipViewGlobalCoordinates = tooltipGlobalCoordinates,
                  tooltipViewGlobalCoordinates = tooltipGlobalCoordinates,
                  tooltipText =
                  tooltipText =
                      getString(R.string.windowing_desktop_mode_image_button_education_tooltip),
                      getString(R.string.windowing_desktop_mode_image_button_education_tooltip),
                  arrowDirection =
                  arrowDirection =
                      DesktopWindowingEducationTooltipController.TooltipArrowDirection.LEFT,
                      DesktopWindowingEducationTooltipController.TooltipArrowDirection.LEFT,
                  onEducationClickAction = {
                  onEducationClickAction = {
                    launchWithExceptionHandling { showExitWindowingTooltip() }
                    launchWithExceptionHandling { showExitWindowingTooltip(tooltipColorScheme) }
                    toDesktopModeCallback(
                    toDesktopModeCallback(
                        captionState.runningTaskInfo.taskId,
                        captionState.runningTaskInfo.taskId,
                        DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON)
                        DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON)
                  },
                  },
                  onDismissAction = { launchWithExceptionHandling { showExitWindowingTooltip() } },
                  onDismissAction = {
                    launchWithExceptionHandling { showExitWindowingTooltip(tooltipColorScheme) }
                  },
              )
              )


          windowingEducationViewController.showEducationTooltip(
          windowingEducationViewController.showEducationTooltip(
@@ -209,7 +222,7 @@ class AppHandleEducationController(
  }
  }


  /** Show tooltip that points to app chip button and educates user on how to exit desktop mode */
  /** Show tooltip that points to app chip button and educates user on how to exit desktop mode */
  private suspend fun showExitWindowingTooltip() {
  private suspend fun showExitWindowingTooltip(tooltipColorScheme: TooltipColorScheme) {
    windowDecorCaptionHandleRepository.captionStateFlow
    windowDecorCaptionHandleRepository.captionStateFlow
        // After the previous tooltip was dismissed, wait for 400 ms and see if the user entered
        // After the previous tooltip was dismissed, wait for 400 ms and see if the user entered
        // desktop mode.
        // desktop mode.
@@ -238,6 +251,7 @@ class AppHandleEducationController(
          val exitWindowingTooltipConfig =
          val exitWindowingTooltipConfig =
              EducationViewConfig(
              EducationViewConfig(
                  tooltipViewLayout = R.layout.desktop_windowing_education_left_arrow_tooltip,
                  tooltipViewLayout = R.layout.desktop_windowing_education_left_arrow_tooltip,
                  tooltipColorScheme = tooltipColorScheme,
                  tooltipViewGlobalCoordinates = tooltipGlobalCoordinates,
                  tooltipViewGlobalCoordinates = tooltipGlobalCoordinates,
                  tooltipText = getString(R.string.windowing_desktop_mode_exit_education_tooltip),
                  tooltipText = getString(R.string.windowing_desktop_mode_exit_education_tooltip),
                  arrowDirection =
                  arrowDirection =
@@ -254,6 +268,32 @@ class AppHandleEducationController(
        }
        }
  }
  }


  private fun tooltipColorScheme(captionState: CaptionState): TooltipColorScheme {
    context.withStyledAttributes(
        set = null,
        attrs =
            intArrayOf(
                com.android.internal.R.attr.materialColorOnTertiaryFixed,
                com.android.internal.R.attr.materialColorTertiaryFixed,
                com.android.internal.R.attr.materialColorTertiaryFixedDim),
        defStyleAttr = 0,
        defStyleRes = 0) {
          val onTertiaryFixed = getColor(/* index= */ 0, /* defValue= */ 0)
          val tertiaryFixed = getColor(/* index= */ 1, /* defValue= */ 0)
          val tertiaryFixedDim = getColor(/* index= */ 2, /* defValue= */ 0)
          val taskInfo = (captionState as CaptionState.AppHandle).runningTaskInfo

          val tooltipContainerColor =
              if (decorThemeUtil.getAppTheme(taskInfo) == Theme.LIGHT) {
                tertiaryFixed
              } else {
                tertiaryFixedDim
              }
          return TooltipColorScheme(tooltipContainerColor, onTertiaryFixed, onTertiaryFixed)
        }
    return TooltipColorScheme(0, 0, 0)
  }

  /**
  /**
   * Setup callbacks for app handle education tooltips.
   * Setup callbacks for app handle education tooltips.
   *
   *
+32 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.wm.shell.windowdecor.education
package com.android.wm.shell.windowdecor.education


import android.annotation.ColorInt
import android.annotation.DimenRes
import android.annotation.DimenRes
import android.annotation.LayoutRes
import android.annotation.LayoutRes
import android.content.Context
import android.content.Context
@@ -32,6 +33,7 @@ import android.widget.LinearLayout
import android.widget.TextView
import android.widget.TextView
import android.window.DisplayAreaInfo
import android.window.DisplayAreaInfo
import android.window.WindowContainerTransaction
import android.window.WindowContainerTransaction
import androidx.core.graphics.drawable.DrawableCompat
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.SpringForce
import androidx.dynamicanimation.animation.SpringForce
import com.android.wm.shell.R
import com.android.wm.shell.R
@@ -120,6 +122,7 @@ class DesktopWindowingEducationTooltipController(
                hideEducationTooltip()
                hideEducationTooltip()
                tooltipViewConfig.onEducationClickAction()
                tooltipViewConfig.onEducationClickAction()
              }
              }
              setTooltipColorScheme(tooltipViewConfig.tooltipColorScheme)
            }
            }


    val tooltipDimens = tooltipDimens(tooltipView = tooltipView, tooltipViewConfig.arrowDirection)
    val tooltipDimens = tooltipDimens(tooltipView = tooltipView, tooltipViewConfig.arrowDirection)
@@ -189,6 +192,21 @@ class DesktopWindowingEducationTooltipController(
            view = tooltipView)
            view = tooltipView)
  }
  }


  private fun View.setTooltipColorScheme(tooltipColorScheme: TooltipColorScheme) {
    requireViewById<LinearLayout>(R.id.tooltip_container).apply {
      background.setTint(tooltipColorScheme.container)
    }
    requireViewById<ImageView>(R.id.arrow_icon).apply {
      val wrappedDrawable = DrawableCompat.wrap(this.drawable)
      DrawableCompat.setTint(wrappedDrawable, tooltipColorScheme.container)
    }
    requireViewById<TextView>(R.id.tooltip_text).apply { setTextColor(tooltipColorScheme.text) }
    requireViewById<ImageView>(R.id.tooltip_icon).apply {
      val wrappedDrawable = DrawableCompat.wrap(this.drawable)
      DrawableCompat.setTint(wrappedDrawable, tooltipColorScheme.icon)
    }
  }

  private fun tooltipViewGlobalCoordinates(
  private fun tooltipViewGlobalCoordinates(
      tooltipViewGlobalCoordinates: Point,
      tooltipViewGlobalCoordinates: Point,
      arrowDirection: TooltipArrowDirection,
      arrowDirection: TooltipArrowDirection,
@@ -255,6 +273,7 @@ class DesktopWindowingEducationTooltipController(
   */
   */
  data class EducationViewConfig(
  data class EducationViewConfig(
      @LayoutRes val tooltipViewLayout: Int,
      @LayoutRes val tooltipViewLayout: Int,
      val tooltipColorScheme: TooltipColorScheme,
      val tooltipViewGlobalCoordinates: Point,
      val tooltipViewGlobalCoordinates: Point,
      val tooltipText: String,
      val tooltipText: String,
      val arrowDirection: TooltipArrowDirection,
      val arrowDirection: TooltipArrowDirection,
@@ -262,6 +281,19 @@ class DesktopWindowingEducationTooltipController(
      val onDismissAction: () -> Unit,
      val onDismissAction: () -> Unit,
  )
  )


  /**
   * Color scheme of education view:
   *
   * @property container Color of the container of the tooltip.
   * @property text Text color of the [TextView] of education tooltip.
   * @property icon Color to be filled in tooltip's icon.
   */
  data class TooltipColorScheme(
      @ColorInt val container: Int,
      @ColorInt val text: Int,
      @ColorInt val icon: Int,
  )

  /** Direction of arrow of the tooltip */
  /** Direction of arrow of the tooltip */
  enum class TooltipArrowDirection {
  enum class TooltipArrowDirection {
    UP,
    UP,
+33 −1
Original line number Original line Diff line number Diff line
@@ -30,12 +30,15 @@ import android.view.View
import android.view.WindowManager
import android.view.WindowManager
import android.widget.TextView
import android.widget.TextView
import android.window.WindowContainerTransaction
import android.window.WindowContainerTransaction
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.wm.shell.R
import com.android.wm.shell.R
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController.TooltipArrowDirection
import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController.TooltipArrowDirection
import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController.TooltipColorScheme
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Before
import org.junit.Test
import org.junit.Test
@@ -240,14 +243,42 @@ class DesktopWindowingEducationTooltipControllerTest : ShellTestCase() {
        /* fromRotation= */ ROTATION_90,
        /* fromRotation= */ ROTATION_90,
        /* toRotation= */ ROTATION_180,
        /* toRotation= */ ROTATION_180,
        /* newDisplayAreaInfo= */ null,
        /* newDisplayAreaInfo= */ null,
        WindowContainerTransaction())
        WindowContainerTransaction(),
    )


    verify(mockPopupWindow, times(1)).releaseView()
    verify(mockPopupWindow, times(1)).releaseView()
    verify(mockDisplayController, atLeastOnce()).removeDisplayChangingController(any())
    verify(mockDisplayController, atLeastOnce()).removeDisplayChangingController(any())
  }
  }


  @Test
  fun showEducationTooltip_setTooltipColorScheme_correctColorsAreSet() {
    val tooltipColorScheme =
        TooltipColorScheme(
            container = Color.Red.toArgb(), text = Color.Blue.toArgb(), icon = Color.Green.toArgb())
    val tooltipViewConfig = createTooltipConfig(tooltipColorScheme = tooltipColorScheme)

    tooltipController.showEducationTooltip(tooltipViewConfig = tooltipViewConfig, taskId = 123)

    verify(mockViewContainerFactory, times(1))
        .create(
            windowManagerWrapper = any(),
            taskId = anyInt(),
            x = anyInt(),
            y = anyInt(),
            width = anyInt(),
            height = anyInt(),
            flags = anyInt(),
            view = tooltipViewArgumentCaptor.capture())
    val tooltipTextView =
        tooltipViewArgumentCaptor.lastValue.findViewById<TextView>(R.id.tooltip_text)
    assertThat(tooltipTextView.textColors.defaultColor).isEqualTo(Color.Blue.toArgb())
  }

  private fun createTooltipConfig(
  private fun createTooltipConfig(
      @LayoutRes tooltipViewLayout: Int = R.layout.desktop_windowing_education_top_arrow_tooltip,
      @LayoutRes tooltipViewLayout: Int = R.layout.desktop_windowing_education_top_arrow_tooltip,
      tooltipColorScheme: TooltipColorScheme =
          TooltipColorScheme(
              container = Color.Red.toArgb(), text = Color.Red.toArgb(), icon = Color.Red.toArgb()),
      tooltipViewGlobalCoordinates: Point = Point(0, 0),
      tooltipViewGlobalCoordinates: Point = Point(0, 0),
      tooltipText: String = "This is a tooltip",
      tooltipText: String = "This is a tooltip",
      arrowDirection: TooltipArrowDirection = TooltipArrowDirection.UP,
      arrowDirection: TooltipArrowDirection = TooltipArrowDirection.UP,
@@ -256,6 +287,7 @@ class DesktopWindowingEducationTooltipControllerTest : ShellTestCase() {
  ) =
  ) =
      DesktopWindowingEducationTooltipController.EducationViewConfig(
      DesktopWindowingEducationTooltipController.EducationViewConfig(
          tooltipViewLayout = tooltipViewLayout,
          tooltipViewLayout = tooltipViewLayout,
          tooltipColorScheme = tooltipColorScheme,
          tooltipViewGlobalCoordinates = tooltipViewGlobalCoordinates,
          tooltipViewGlobalCoordinates = tooltipViewGlobalCoordinates,
          tooltipText = tooltipText,
          tooltipText = tooltipText,
          arrowDirection = arrowDirection,
          arrowDirection = arrowDirection,