Loading packages/SystemUI/res/layout/controls_management_favorites.xml +21 −3 Original line number Diff line number Diff line Loading @@ -21,15 +21,32 @@ android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/error_message" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/controls_management_list_margin" android:text="@string/controls_favorite_load_error" android:textAppearance="?android:attr/textAppearanceSmall" android:visibility="gone" android:gravity="center_horizontal" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="parent" app:layout_constraintBottom_toTopOf="@id/text_favorites" /> <TextView android:id="@+id/text_favorites" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="FAVORITES" android:layout_marginTop="@dimen/controls_management_list_margin" android:text="@string/controls_favorite_header_favorites" android:textAppearance="?android:attr/textAppearanceSmall" android:textAllCaps="true" app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toTopOf="@id/divider1" app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toBottomOf="@id/error_message" /> <View Loading Loading @@ -60,8 +77,9 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/controls_management_list_margin" android:text="ALL" android:text="@string/controls_favorite_header_all" android:textAppearance="?android:attr/textAppearanceSmall" android:textAllCaps="true" app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toTopOf="@id/divider2" app:layout_constraintTop_toBottomOf="@id/listFavorites" Loading packages/SystemUI/res/values/strings.xml +6 −0 Original line number Diff line number Diff line Loading @@ -2595,4 +2595,10 @@ <string name="controls_favorite_default_title">Controls</string> <!-- Controls management controls screen subtitle [CHAR LIMIT=NONE] --> <string name="controls_favorite_subtitle">Choose controls for quick access</string> <!-- Controls management controls screen favorites header [CHAR LIMIT=50] --> <string name="controls_favorite_header_favorites">Favorites</string> <!-- Controls management controls screen all header [CHAR LIMIT=50] --> <string name="controls_favorite_header_all">All</string> <!-- Controls management controls screen error on load message [CHAR LIMIT=50] --> <string name="controls_favorite_load_error">The list of all controls could not be loaded.</string> </resources> packages/SystemUI/src/com/android/systemui/controls/UserAwareController.kt +4 −1 Original line number Diff line number Diff line Loading @@ -18,8 +18,11 @@ package com.android.systemui.controls import android.os.UserHandle /** * An interface for controllers that keep track of the current user and can be notified of user * changes. */ interface UserAwareController { fun changeUser(newUser: UserHandle) {} val currentUserId: Int } No newline at end of file packages/SystemUI/src/com/android/systemui/controls/controller/ControlInfo.kt +23 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,15 @@ import android.util.Log /** * Stores basic information about a [Control] to persist and keep track of favorites. * * The identifier of this [Control] is the combination of [component] and [controlId]. The other * two fields are there for persistence. In this way, basic information can be shown to the user * before the service has to report on the status. * * @property component the name of the component that provides the [Control]. * @property controlId unique (for the given [component]) identifier for this [Control]. * @property controlTitle last title reported for this [Control]. * @property deviceType last reported type for this [Control]. */ data class ControlInfo( val component: ComponentName, Loading @@ -33,6 +42,14 @@ data class ControlInfo( companion object { private const val TAG = "ControlInfo" private const val SEPARATOR = ":" /** * Creates a [ControlInfo] from a [SEPARATOR] separated list of fields. * * @param separator fields of a [ControlInfo] separated by [SEPARATOR] * @return a [ControlInfo] or `null` if there was an error. * @see [ControlInfo.toString] */ fun createFromString(string: String): ControlInfo? { val parts = string.split(SEPARATOR) val component = ComponentName.unflattenFromString(parts[0]) Loading @@ -53,6 +70,12 @@ data class ControlInfo( if (DeviceTypes.validDeviceType(type)) type else DeviceTypes.TYPE_UNKNOWN) } } /** * Returns a [String] representation of the fields separated using [SEPARATOR]. * * @return a [String] representation of `this` */ override fun toString(): String { return component.flattenToString() + "$SEPARATOR$controlId$SEPARATOR$controlTitle$SEPARATOR$deviceType" Loading packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt +60 −1 Original line number Diff line number Diff line Loading @@ -18,13 +18,72 @@ package com.android.systemui.controls.controller import android.content.ComponentName import android.service.controls.Control import android.service.controls.ControlsProviderService import android.service.controls.actions.ControlAction import com.android.systemui.controls.UserAwareController import java.util.function.Consumer /** * Controller for keeping track of any [ControlsProviderService] that needs to be bound. * * This controller serves as an interface between [ControlsController] and the services. * * This controller being a [UserAwareController] means that all binding and requests will be * performed on services bound as the current user. */ interface ControlsBindingController : UserAwareController { fun bindAndLoad(component: ComponentName, callback: (List<Control>) -> Unit) /** * Request bind to a service and load all controls. * * @param component The [ComponentName] of the service to bind * @param callback a callback to return the loaded controls to (or an error). */ fun bindAndLoad(component: ComponentName, callback: LoadCallback) /** * Request to bind to the given services. * * @param components a list of [ComponentName] of the services to bind */ fun bindServices(components: List<ComponentName>) /** * Send a subscribe message to retrieve status of a set of controls. * * The controls passed do not have to belong to a single [ControlsProviderService]. The * corresponding service [ComponentName] is associated with each control. * * @param controls a list of controls with corresponding [ComponentName] to request status * update */ fun subscribe(controls: List<ControlInfo>) /** * Send an action performed on a [Control]. * * @param controlInfo information about the actioned control, including the [ComponentName] * @param action the action performed on the control */ fun action(controlInfo: ControlInfo, action: ControlAction) /** * Unsubscribe from all services to stop status updates. */ fun unsubscribe() /** * Consumer for load calls. * * Supports also sending error messages. */ interface LoadCallback : Consumer<List<Control>> { /** * Indicates an error loading. * * @message an error message. */ fun error(message: String) } } No newline at end of file Loading
packages/SystemUI/res/layout/controls_management_favorites.xml +21 −3 Original line number Diff line number Diff line Loading @@ -21,15 +21,32 @@ android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/error_message" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/controls_management_list_margin" android:text="@string/controls_favorite_load_error" android:textAppearance="?android:attr/textAppearanceSmall" android:visibility="gone" android:gravity="center_horizontal" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="parent" app:layout_constraintBottom_toTopOf="@id/text_favorites" /> <TextView android:id="@+id/text_favorites" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="FAVORITES" android:layout_marginTop="@dimen/controls_management_list_margin" android:text="@string/controls_favorite_header_favorites" android:textAppearance="?android:attr/textAppearanceSmall" android:textAllCaps="true" app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toTopOf="@id/divider1" app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toBottomOf="@id/error_message" /> <View Loading Loading @@ -60,8 +77,9 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/controls_management_list_margin" android:text="ALL" android:text="@string/controls_favorite_header_all" android:textAppearance="?android:attr/textAppearanceSmall" android:textAllCaps="true" app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toTopOf="@id/divider2" app:layout_constraintTop_toBottomOf="@id/listFavorites" Loading
packages/SystemUI/res/values/strings.xml +6 −0 Original line number Diff line number Diff line Loading @@ -2595,4 +2595,10 @@ <string name="controls_favorite_default_title">Controls</string> <!-- Controls management controls screen subtitle [CHAR LIMIT=NONE] --> <string name="controls_favorite_subtitle">Choose controls for quick access</string> <!-- Controls management controls screen favorites header [CHAR LIMIT=50] --> <string name="controls_favorite_header_favorites">Favorites</string> <!-- Controls management controls screen all header [CHAR LIMIT=50] --> <string name="controls_favorite_header_all">All</string> <!-- Controls management controls screen error on load message [CHAR LIMIT=50] --> <string name="controls_favorite_load_error">The list of all controls could not be loaded.</string> </resources>
packages/SystemUI/src/com/android/systemui/controls/UserAwareController.kt +4 −1 Original line number Diff line number Diff line Loading @@ -18,8 +18,11 @@ package com.android.systemui.controls import android.os.UserHandle /** * An interface for controllers that keep track of the current user and can be notified of user * changes. */ interface UserAwareController { fun changeUser(newUser: UserHandle) {} val currentUserId: Int } No newline at end of file
packages/SystemUI/src/com/android/systemui/controls/controller/ControlInfo.kt +23 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,15 @@ import android.util.Log /** * Stores basic information about a [Control] to persist and keep track of favorites. * * The identifier of this [Control] is the combination of [component] and [controlId]. The other * two fields are there for persistence. In this way, basic information can be shown to the user * before the service has to report on the status. * * @property component the name of the component that provides the [Control]. * @property controlId unique (for the given [component]) identifier for this [Control]. * @property controlTitle last title reported for this [Control]. * @property deviceType last reported type for this [Control]. */ data class ControlInfo( val component: ComponentName, Loading @@ -33,6 +42,14 @@ data class ControlInfo( companion object { private const val TAG = "ControlInfo" private const val SEPARATOR = ":" /** * Creates a [ControlInfo] from a [SEPARATOR] separated list of fields. * * @param separator fields of a [ControlInfo] separated by [SEPARATOR] * @return a [ControlInfo] or `null` if there was an error. * @see [ControlInfo.toString] */ fun createFromString(string: String): ControlInfo? { val parts = string.split(SEPARATOR) val component = ComponentName.unflattenFromString(parts[0]) Loading @@ -53,6 +70,12 @@ data class ControlInfo( if (DeviceTypes.validDeviceType(type)) type else DeviceTypes.TYPE_UNKNOWN) } } /** * Returns a [String] representation of the fields separated using [SEPARATOR]. * * @return a [String] representation of `this` */ override fun toString(): String { return component.flattenToString() + "$SEPARATOR$controlId$SEPARATOR$controlTitle$SEPARATOR$deviceType" Loading
packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt +60 −1 Original line number Diff line number Diff line Loading @@ -18,13 +18,72 @@ package com.android.systemui.controls.controller import android.content.ComponentName import android.service.controls.Control import android.service.controls.ControlsProviderService import android.service.controls.actions.ControlAction import com.android.systemui.controls.UserAwareController import java.util.function.Consumer /** * Controller for keeping track of any [ControlsProviderService] that needs to be bound. * * This controller serves as an interface between [ControlsController] and the services. * * This controller being a [UserAwareController] means that all binding and requests will be * performed on services bound as the current user. */ interface ControlsBindingController : UserAwareController { fun bindAndLoad(component: ComponentName, callback: (List<Control>) -> Unit) /** * Request bind to a service and load all controls. * * @param component The [ComponentName] of the service to bind * @param callback a callback to return the loaded controls to (or an error). */ fun bindAndLoad(component: ComponentName, callback: LoadCallback) /** * Request to bind to the given services. * * @param components a list of [ComponentName] of the services to bind */ fun bindServices(components: List<ComponentName>) /** * Send a subscribe message to retrieve status of a set of controls. * * The controls passed do not have to belong to a single [ControlsProviderService]. The * corresponding service [ComponentName] is associated with each control. * * @param controls a list of controls with corresponding [ComponentName] to request status * update */ fun subscribe(controls: List<ControlInfo>) /** * Send an action performed on a [Control]. * * @param controlInfo information about the actioned control, including the [ComponentName] * @param action the action performed on the control */ fun action(controlInfo: ControlInfo, action: ControlAction) /** * Unsubscribe from all services to stop status updates. */ fun unsubscribe() /** * Consumer for load calls. * * Supports also sending error messages. */ interface LoadCallback : Consumer<List<Control>> { /** * Indicates an error loading. * * @message an error message. */ fun error(message: String) } } No newline at end of file