Loading packages/SystemUI/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -685,6 +685,7 @@ </activity> <activity android:name=".controls.management.ControlsEditingActivity" android:label="@string/controls_menu_edit" android:theme="@style/Theme.ControlsManagement" android:excludeFromRecents="true" android:noHistory="true" Loading packages/SystemUI/res/values/ids.xml +3 −0 Original line number Diff line number Diff line Loading @@ -169,5 +169,8 @@ <item type="id" name="screen_recording_options" /> <item type="id" name="screen_recording_dialog_source_text" /> <item type="id" name="screen_recording_dialog_source_description" /> <item type="id" name="accessibility_action_controls_move_before" /> <item type="id" name="accessibility_action_controls_move_after" /> </resources> packages/SystemUI/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -2711,6 +2711,8 @@ <string name="accessibility_control_change_favorite">favorite</string> <!-- a11y action to unfavorite a control. It will read as "Double-tap to unfavorite" in screen readers [CHAR LIMIT=NONE] --> <string name="accessibility_control_change_unfavorite">unfavorite</string> <!-- a11y action to move a control to the position specified by the parameter [CHAR LIMIT=NONE] --> <string name="accessibility_control_move">Move to position <xliff:g id="number" example="1">%d</xliff:g></string> <!-- Controls management controls screen default title [CHAR LIMIT=30] --> <string name="controls_favorite_default_title">Controls</string> Loading packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt +2 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ class AllModel( private var modified = false override val moveHelper = null override val favorites: List<ControlInfo> get() = favoriteIds.mapNotNull { id -> val control = controls.firstOrNull { it.control.controlId == id }?.control Loading packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt +86 −10 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.controls.management import android.content.ComponentName import android.graphics.Rect import android.os.Bundle import android.service.controls.Control import android.service.controls.DeviceTypes import android.view.LayoutInflater Loading Loading @@ -78,7 +79,7 @@ class ControlAdapter( background = parent.context.getDrawable( R.drawable.control_background_ripple) }, model is FavoritesModel // Indicates that position information is needed model?.moveHelper // Indicates that position information is needed ) { id, favorite -> model?.changeFavoriteStatus(id, favorite) } Loading Loading @@ -176,12 +177,14 @@ private class ZoneHolder(view: View) : Holder(view) { /** * Holder for using with [ControlStatusWrapper] to display names of zones. * @param moveHelper a helper interface to facilitate a11y rearranging. Null indicates no * rearranging * @param favoriteCallback this callback will be called whenever the favorite state of the * [Control] this view represents changes. */ internal class ControlHolder( view: View, val withPosition: Boolean, val moveHelper: ControlsModel.MoveHelper?, val favoriteCallback: ModelFavoriteChanger ) : Holder(view) { private val favoriteStateDescription = Loading @@ -197,7 +200,11 @@ internal class ControlHolder( visibility = View.VISIBLE } private val accessibilityDelegate = ControlHolderAccessibilityDelegate(this::stateDescription) private val accessibilityDelegate = ControlHolderAccessibilityDelegate( this::stateDescription, this::getLayoutPosition, moveHelper ) init { ViewCompat.setAccessibilityDelegate(itemView, accessibilityDelegate) Loading @@ -207,7 +214,7 @@ internal class ControlHolder( private fun stateDescription(favorite: Boolean): CharSequence? { if (!favorite) { return notFavoriteStateDescription } else if (!withPosition) { } else if (moveHelper == null) { return favoriteStateDescription } else { val position = layoutPosition + 1 Loading Loading @@ -256,15 +263,67 @@ internal class ControlHolder( } } /** * Accessibility delegate for [ControlHolder]. * * Provides the following functionality: * * Sets the state description indicating whether the controls is Favorited or Unfavorited * * Adds the position to the state description if necessary. * * Adds context action for moving (rearranging) a control. * * @param stateRetriever function to determine the state description based on the favorite state * @param positionRetriever function to obtain the position of this control. It only has to be * correct in controls that are currently favorites (and therefore can * be moved). * @param moveHelper helper interface to determine if a control can be moved and actually move it. */ private class ControlHolderAccessibilityDelegate( val stateRetriever: (Boolean) -> CharSequence? val stateRetriever: (Boolean) -> CharSequence?, val positionRetriever: () -> Int, val moveHelper: ControlsModel.MoveHelper? ) : AccessibilityDelegateCompat() { var isFavorite = false companion object { private val MOVE_BEFORE_ID = R.id.accessibility_action_controls_move_before private val MOVE_AFTER_ID = R.id.accessibility_action_controls_move_after } override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) { super.onInitializeAccessibilityNodeInfo(host, info) info.isContextClickable = false addClickAction(host, info) maybeAddMoveBeforeAction(host, info) maybeAddMoveAfterAction(host, info) // Determine the stateDescription based on the holder information info.stateDescription = stateRetriever(isFavorite) // Remove the information at the end indicating row and column. info.setCollectionItemInfo(null) info.className = Switch::class.java.name } override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?): Boolean { if (super.performAccessibilityAction(host, action, args)) { return true } return when (action) { MOVE_BEFORE_ID -> { moveHelper?.moveBefore(positionRetriever()) true } MOVE_AFTER_ID -> { moveHelper?.moveAfter(positionRetriever()) true } else -> false } } private fun addClickAction(host: View, info: AccessibilityNodeInfoCompat) { // Change the text for the double-tap action val clickActionString = if (isFavorite) { host.context.getString(R.string.accessibility_control_change_unfavorite) Loading @@ -276,13 +335,30 @@ private class ControlHolderAccessibilityDelegate( // “favorite/unfavorite” clickActionString) info.addAction(click) } // Determine the stateDescription based on the holder information info.stateDescription = stateRetriever(isFavorite) // Remove the information at the end indicating row and column. info.setCollectionItemInfo(null) private fun maybeAddMoveBeforeAction(host: View, info: AccessibilityNodeInfoCompat) { if (moveHelper?.canMoveBefore(positionRetriever()) ?: false) { val newPosition = positionRetriever() + 1 - 1 val moveBefore = AccessibilityNodeInfoCompat.AccessibilityActionCompat( MOVE_BEFORE_ID, host.context.getString(R.string.accessibility_control_move, newPosition) ) info.addAction(moveBefore) info.isContextClickable = true } } info.className = Switch::class.java.name private fun maybeAddMoveAfterAction(host: View, info: AccessibilityNodeInfoCompat) { if (moveHelper?.canMoveAfter(positionRetriever()) ?: false) { val newPosition = positionRetriever() + 1 + 1 val moveAfter = AccessibilityNodeInfoCompat.AccessibilityActionCompat( MOVE_AFTER_ID, host.context.getString(R.string.accessibility_control_move, newPosition) ) info.addAction(moveAfter) info.isContextClickable = true } } } Loading Loading
packages/SystemUI/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -685,6 +685,7 @@ </activity> <activity android:name=".controls.management.ControlsEditingActivity" android:label="@string/controls_menu_edit" android:theme="@style/Theme.ControlsManagement" android:excludeFromRecents="true" android:noHistory="true" Loading
packages/SystemUI/res/values/ids.xml +3 −0 Original line number Diff line number Diff line Loading @@ -169,5 +169,8 @@ <item type="id" name="screen_recording_options" /> <item type="id" name="screen_recording_dialog_source_text" /> <item type="id" name="screen_recording_dialog_source_description" /> <item type="id" name="accessibility_action_controls_move_before" /> <item type="id" name="accessibility_action_controls_move_after" /> </resources>
packages/SystemUI/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -2711,6 +2711,8 @@ <string name="accessibility_control_change_favorite">favorite</string> <!-- a11y action to unfavorite a control. It will read as "Double-tap to unfavorite" in screen readers [CHAR LIMIT=NONE] --> <string name="accessibility_control_change_unfavorite">unfavorite</string> <!-- a11y action to move a control to the position specified by the parameter [CHAR LIMIT=NONE] --> <string name="accessibility_control_move">Move to position <xliff:g id="number" example="1">%d</xliff:g></string> <!-- Controls management controls screen default title [CHAR LIMIT=30] --> <string name="controls_favorite_default_title">Controls</string> Loading
packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt +2 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ class AllModel( private var modified = false override val moveHelper = null override val favorites: List<ControlInfo> get() = favoriteIds.mapNotNull { id -> val control = controls.firstOrNull { it.control.controlId == id }?.control Loading
packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt +86 −10 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.controls.management import android.content.ComponentName import android.graphics.Rect import android.os.Bundle import android.service.controls.Control import android.service.controls.DeviceTypes import android.view.LayoutInflater Loading Loading @@ -78,7 +79,7 @@ class ControlAdapter( background = parent.context.getDrawable( R.drawable.control_background_ripple) }, model is FavoritesModel // Indicates that position information is needed model?.moveHelper // Indicates that position information is needed ) { id, favorite -> model?.changeFavoriteStatus(id, favorite) } Loading Loading @@ -176,12 +177,14 @@ private class ZoneHolder(view: View) : Holder(view) { /** * Holder for using with [ControlStatusWrapper] to display names of zones. * @param moveHelper a helper interface to facilitate a11y rearranging. Null indicates no * rearranging * @param favoriteCallback this callback will be called whenever the favorite state of the * [Control] this view represents changes. */ internal class ControlHolder( view: View, val withPosition: Boolean, val moveHelper: ControlsModel.MoveHelper?, val favoriteCallback: ModelFavoriteChanger ) : Holder(view) { private val favoriteStateDescription = Loading @@ -197,7 +200,11 @@ internal class ControlHolder( visibility = View.VISIBLE } private val accessibilityDelegate = ControlHolderAccessibilityDelegate(this::stateDescription) private val accessibilityDelegate = ControlHolderAccessibilityDelegate( this::stateDescription, this::getLayoutPosition, moveHelper ) init { ViewCompat.setAccessibilityDelegate(itemView, accessibilityDelegate) Loading @@ -207,7 +214,7 @@ internal class ControlHolder( private fun stateDescription(favorite: Boolean): CharSequence? { if (!favorite) { return notFavoriteStateDescription } else if (!withPosition) { } else if (moveHelper == null) { return favoriteStateDescription } else { val position = layoutPosition + 1 Loading Loading @@ -256,15 +263,67 @@ internal class ControlHolder( } } /** * Accessibility delegate for [ControlHolder]. * * Provides the following functionality: * * Sets the state description indicating whether the controls is Favorited or Unfavorited * * Adds the position to the state description if necessary. * * Adds context action for moving (rearranging) a control. * * @param stateRetriever function to determine the state description based on the favorite state * @param positionRetriever function to obtain the position of this control. It only has to be * correct in controls that are currently favorites (and therefore can * be moved). * @param moveHelper helper interface to determine if a control can be moved and actually move it. */ private class ControlHolderAccessibilityDelegate( val stateRetriever: (Boolean) -> CharSequence? val stateRetriever: (Boolean) -> CharSequence?, val positionRetriever: () -> Int, val moveHelper: ControlsModel.MoveHelper? ) : AccessibilityDelegateCompat() { var isFavorite = false companion object { private val MOVE_BEFORE_ID = R.id.accessibility_action_controls_move_before private val MOVE_AFTER_ID = R.id.accessibility_action_controls_move_after } override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) { super.onInitializeAccessibilityNodeInfo(host, info) info.isContextClickable = false addClickAction(host, info) maybeAddMoveBeforeAction(host, info) maybeAddMoveAfterAction(host, info) // Determine the stateDescription based on the holder information info.stateDescription = stateRetriever(isFavorite) // Remove the information at the end indicating row and column. info.setCollectionItemInfo(null) info.className = Switch::class.java.name } override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?): Boolean { if (super.performAccessibilityAction(host, action, args)) { return true } return when (action) { MOVE_BEFORE_ID -> { moveHelper?.moveBefore(positionRetriever()) true } MOVE_AFTER_ID -> { moveHelper?.moveAfter(positionRetriever()) true } else -> false } } private fun addClickAction(host: View, info: AccessibilityNodeInfoCompat) { // Change the text for the double-tap action val clickActionString = if (isFavorite) { host.context.getString(R.string.accessibility_control_change_unfavorite) Loading @@ -276,13 +335,30 @@ private class ControlHolderAccessibilityDelegate( // “favorite/unfavorite” clickActionString) info.addAction(click) } // Determine the stateDescription based on the holder information info.stateDescription = stateRetriever(isFavorite) // Remove the information at the end indicating row and column. info.setCollectionItemInfo(null) private fun maybeAddMoveBeforeAction(host: View, info: AccessibilityNodeInfoCompat) { if (moveHelper?.canMoveBefore(positionRetriever()) ?: false) { val newPosition = positionRetriever() + 1 - 1 val moveBefore = AccessibilityNodeInfoCompat.AccessibilityActionCompat( MOVE_BEFORE_ID, host.context.getString(R.string.accessibility_control_move, newPosition) ) info.addAction(moveBefore) info.isContextClickable = true } } info.className = Switch::class.java.name private fun maybeAddMoveAfterAction(host: View, info: AccessibilityNodeInfoCompat) { if (moveHelper?.canMoveAfter(positionRetriever()) ?: false) { val newPosition = positionRetriever() + 1 + 1 val moveAfter = AccessibilityNodeInfoCompat.AccessibilityActionCompat( MOVE_AFTER_ID, host.context.getString(R.string.accessibility_control_move, newPosition) ) info.addAction(moveAfter) info.isContextClickable = true } } } Loading