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

Commit c3e0b8b0 authored by Michał Brzeziński's avatar Michał Brzeziński Committed by Android (Google) Code Review
Browse files

Merge "Make keyboard backlight indicator more accessible" into main

parents 8d9bba1a 8109c210
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -3266,4 +3266,9 @@
    <string name="privacy_dialog_active_app_usage_2">In use by <xliff:g id="app_name" example="Gmail">%1$s</xliff:g> (<xliff:g id="attribution_label" example="For Wallet">%2$s</xliff:g> \u2022 <xliff:g id="proxy_label" example="Speech services">%3$s</xliff:g>)</string>
    <string name="privacy_dialog_active_app_usage_2">In use by <xliff:g id="app_name" example="Gmail">%1$s</xliff:g> (<xliff:g id="attribution_label" example="For Wallet">%2$s</xliff:g> \u2022 <xliff:g id="proxy_label" example="Speech services">%3$s</xliff:g>)</string>
    <!-- Label for recent app usage of a phone sensor with sub-attribution and proxy label in the privacy dialog [CHAR LIMIT=NONE] -->
    <!-- Label for recent app usage of a phone sensor with sub-attribution and proxy label in the privacy dialog [CHAR LIMIT=NONE] -->
    <string name="privacy_dialog_recent_app_usage_2">Recently used by <xliff:g id="app_name" example="Gmail">%1$s</xliff:g> (<xliff:g id="attribution_label" example="For Wallet">%2$s</xliff:g> \u2022 <xliff:g id="proxy_label" example="Speech services">%3$s</xliff:g>)</string>
    <string name="privacy_dialog_recent_app_usage_2">Recently used by <xliff:g id="app_name" example="Gmail">%1$s</xliff:g> (<xliff:g id="attribution_label" example="For Wallet">%2$s</xliff:g> \u2022 <xliff:g id="proxy_label" example="Speech services">%3$s</xliff:g>)</string>

    <!-- Content description for keyboard backlight brightness dialog [CHAR LIMIT=NONE] -->
    <string name="keyboard_backlight_dialog_title">Keyboard backlight</string>
    <!-- Content description for keyboard backlight brightness value [CHAR LIMIT=NONE] -->
    <string name="keyboard_backlight_value">Level %1$d of %2$d</string>
</resources>
</resources>
+22 −7
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@ import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import android.view.ViewGroup.MarginLayoutParams
import android.view.Window
import android.view.Window
import android.view.WindowManager
import android.view.WindowManager
import android.view.accessibility.AccessibilityEvent
import android.widget.FrameLayout
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.LinearLayout
@@ -78,23 +79,29 @@ class KeyboardBacklightDialog(
    private lateinit var stepProperties: StepViewProperties
    private lateinit var stepProperties: StepViewProperties


    @ColorInt
    @ColorInt
    var filledRectangleColor = getColorFromStyle(com.android.internal.R.attr.materialColorPrimary)
    private val filledRectangleColor =
        getColorFromStyle(com.android.internal.R.attr.materialColorPrimary)
    @ColorInt
    @ColorInt
    var emptyRectangleColor =
    private val emptyRectangleColor =
        getColorFromStyle(com.android.internal.R.attr.materialColorOutlineVariant)
        getColorFromStyle(com.android.internal.R.attr.materialColorOutlineVariant)
    @ColorInt
    @ColorInt
    var backgroundColor = getColorFromStyle(com.android.internal.R.attr.materialColorSurfaceBright)
    private val backgroundColor =
        getColorFromStyle(com.android.internal.R.attr.materialColorSurfaceBright)
    @ColorInt
    @ColorInt
    var defaultIconColor = getColorFromStyle(com.android.internal.R.attr.materialColorOnPrimary)
    private val defaultIconColor =
        getColorFromStyle(com.android.internal.R.attr.materialColorOnPrimary)
    @ColorInt
    @ColorInt
    var defaultIconBackgroundColor =
    private val defaultIconBackgroundColor =
        getColorFromStyle(com.android.internal.R.attr.materialColorPrimary)
        getColorFromStyle(com.android.internal.R.attr.materialColorPrimary)
    @ColorInt
    @ColorInt
    var dimmedIconColor = getColorFromStyle(com.android.internal.R.attr.materialColorOnSurface)
    private val dimmedIconColor =
        getColorFromStyle(com.android.internal.R.attr.materialColorOnSurface)
    @ColorInt
    @ColorInt
    var dimmedIconBackgroundColor =
    private val dimmedIconBackgroundColor =
        getColorFromStyle(com.android.internal.R.attr.materialColorSurfaceDim)
        getColorFromStyle(com.android.internal.R.attr.materialColorSurfaceDim)


    private val levelContentDescription = context.getString(R.string.keyboard_backlight_value)

    init {
    init {
        currentLevel = initialCurrentLevel
        currentLevel = initialCurrentLevel
        maxLevel = initialMaxLevel
        maxLevel = initialMaxLevel
@@ -103,6 +110,8 @@ class KeyboardBacklightDialog(
    override fun onCreate(savedInstanceState: Bundle?) {
    override fun onCreate(savedInstanceState: Bundle?) {
        setUpWindowProperties(this)
        setUpWindowProperties(this)
        setWindowPosition()
        setWindowPosition()
        // title is used for a11y announcement
        window?.setTitle(context.getString(R.string.keyboard_backlight_dialog_title))
        updateResources()
        updateResources()
        rootView = buildRootView()
        rootView = buildRootView()
        setContentView(rootView)
        setContentView(rootView)
@@ -159,6 +168,12 @@ class KeyboardBacklightDialog(
        currentLevel = current
        currentLevel = current
        updateIconTile()
        updateIconTile()
        updateStepColors()
        updateStepColors()
        updateAccessibilityInfo()
    }

    private fun updateAccessibilityInfo() {
        rootView.contentDescription = String.format(levelContentDescription, currentLevel, maxLevel)
        rootView.sendAccessibilityEvent(AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION)
    }
    }


    private fun updateIconTile() {
    private fun updateIconTile() {
+84 −0
Original line number Original line 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.systemui.keyboard.backlight.ui.view

import android.testing.TestableLooper.RunWithLooper
import android.view.View
import android.view.accessibility.AccessibilityEvent
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.res.R
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

@RunWithLooper
@SmallTest
@RunWith(JUnit4::class)
class KeyboardBacklightDialogTest : SysuiTestCase() {

    private lateinit var dialog: KeyboardBacklightDialog
    private lateinit var rootView: View
    private val descriptionString = context.getString(R.string.keyboard_backlight_value)

    @Before
    fun setUp() {
        dialog =
            KeyboardBacklightDialog(context, initialCurrentLevel = 0, initialMaxLevel = MAX_LEVEL)
        dialog.show()
        rootView = dialog.requireViewById(R.id.keyboard_backlight_dialog_container)
    }

    @Test
    fun rootViewContentDescription_containsInitialLevel() {
        assertThat(rootView.contentDescription).isEqualTo(contentDescriptionForLevel(INITIAL_LEVEL))
    }

    @Test
    fun contentDescriptionUpdated_afterEveryLevelUpdate() {
        val events = startCollectingAccessibilityEvents(rootView)

        dialog.updateState(current = 1, max = MAX_LEVEL)

        assertThat(rootView.contentDescription).isEqualTo(contentDescriptionForLevel(1))
        assertThat(events).contains(AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION)
    }

    private fun contentDescriptionForLevel(level: Int): String {
        return String.format(descriptionString, level, MAX_LEVEL)
    }

    private fun startCollectingAccessibilityEvents(rootView: View): MutableList<Int> {
        val events = mutableListOf<Int>()
        rootView.accessibilityDelegate =
            object : View.AccessibilityDelegate() {
                override fun sendAccessibilityEvent(host: View, eventType: Int) {
                    super.sendAccessibilityEvent(host, eventType)
                    events.add(eventType)
                }
            }
        return events
    }

    companion object {
        private const val MAX_LEVEL = 5
        private const val INITIAL_LEVEL = 0
    }
}