From 53a8bbdd72685f486fa23f2ecfde3bfdf3fb7fdf Mon Sep 17 00:00:00 2001 From: Matt Pietal Date: Thu, 5 Mar 2020 16:10:34 -0500 Subject: [PATCH] Controls UI - Stateless controls Add support for touchable controls without any state. Refactor to support using app icons as well as device type specific icons. Cache icons since they will most likely be used many times. Bug: 150849751 Test: visual Change-Id: I2d729ced2361e623d3f575149b5c0b4492072ff3 --- .../systemui/controls/ControlStatus.kt | 4 +- .../controller/ControlsControllerImpl.kt | 8 +- .../controls/management/ControlAdapter.kt | 11 ++- .../management/ControlsRequestDialog.kt | 8 +- .../controls/ui/ControlActionCoordinator.kt | 5 + .../systemui/controls/ui/ControlViewHolder.kt | 14 ++- .../controls/ui/ControlsUiControllerImpl.kt | 94 ++++++++++--------- .../systemui/controls/ui/DefaultBehavior.kt | 3 +- .../systemui/controls/ui/RenderInfo.kt | 60 ++++++++++-- .../controls/ui/TemperatureControlBehavior.kt | 5 +- .../systemui/controls/ui/ToggleBehavior.kt | 7 +- .../controls/ui/ToggleRangeBehavior.kt | 7 +- .../systemui/controls/ui/TouchBehavior.kt | 58 ++++++++++++ .../systemui/controls/ui/UnknownBehavior.kt | 3 +- .../controller/ControlsControllerImplTest.kt | 6 +- .../controls/management/AllModelTest.kt | 4 +- .../controls/management/FavoriteModelTest.kt | 4 +- 17 files changed, 212 insertions(+), 89 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt diff --git a/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt b/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt index 49a16d892ef40..dec60073a55e7 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt @@ -16,10 +16,12 @@ package com.android.systemui.controls +import android.content.ComponentName import android.service.controls.Control data class ControlStatus( val control: Control, + val component: ComponentName, var favorite: Boolean, val removed: Boolean = false -) \ No newline at end of file +) diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt index 5e1ed5892e2ee..cf4b8a55ce97f 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt @@ -238,7 +238,11 @@ class ControlsControllerImpl @Inject constructor ( } val removed = findRemoved(favoritesForComponentKeys.toSet(), controls) val controlsWithFavorite = controls.map { - ControlStatus(it, it.controlId in favoritesForComponentKeys) + ControlStatus( + it, + componentName, + it.controlId in favoritesForComponentKeys + ) } val loadData = createLoadDataObject( Favorites.getControlsForComponent(componentName) @@ -290,7 +294,7 @@ class ControlsControllerImpl @Inject constructor ( .setTitle(controlInfo.controlTitle) .setDeviceType(controlInfo.deviceType) .build() - return ControlStatus(control, true, setRemoved) + return ControlStatus(control, componentName, true, setRemoved) } private fun findRemoved(favoriteKeys: Set, list: List): Set { diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt index 179e9fb027974..563c2f677801b 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt @@ -16,8 +16,8 @@ package com.android.systemui.controls.management +import android.content.ComponentName import android.graphics.Rect -import android.graphics.drawable.Icon import android.service.controls.DeviceTypes import android.view.LayoutInflater import android.view.View @@ -147,7 +147,7 @@ private class ControlHolder(view: View, val favoriteCallback: ModelFavoriteChang override fun bindData(wrapper: ElementWrapper) { wrapper as ControlWrapper val data = wrapper.controlStatus - val renderInfo = getRenderInfo(data.control.deviceType) + val renderInfo = getRenderInfo(data.component, data.control.deviceType) title.text = data.control.title subtitle.text = data.control.subtitle favorite.isChecked = data.favorite @@ -160,16 +160,17 @@ private class ControlHolder(view: View, val favoriteCallback: ModelFavoriteChang } private fun getRenderInfo( + component: ComponentName, @DeviceTypes.DeviceType deviceType: Int ): RenderInfo { - return RenderInfo.lookup(deviceType, true) + return RenderInfo.lookup(itemView.context, component, deviceType, true) } private fun applyRenderInfo(ri: RenderInfo) { val context = itemView.context val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme()) - icon.setImageIcon(Icon.createWithResource(context, ri.iconResourceId)) + icon.setImageDrawable(ri.icon) icon.setImageTintList(fg) } } @@ -191,4 +192,4 @@ class MarginItemDecorator( right = sideMargins } } -} \ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt index 463632b319bb9..a7fc2ac800702 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt @@ -21,7 +21,6 @@ import android.app.Dialog import android.content.ComponentName import android.content.DialogInterface import android.content.Intent -import android.graphics.drawable.Icon import android.os.Bundle import android.os.UserHandle import android.service.controls.Control @@ -137,11 +136,10 @@ class ControlsRequestDialog @Inject constructor( } fun createDialog(label: CharSequence): Dialog { - - val renderInfo = RenderInfo.lookup(control.deviceType, true) + val renderInfo = RenderInfo.lookup(this, component, control.deviceType, true) val frame = LayoutInflater.from(this).inflate(R.layout.controls_dialog, null).apply { requireViewById(R.id.icon).apply { - setImageIcon(Icon.createWithResource(context, renderInfo.iconResourceId)) + setImageDrawable(renderInfo.icon) setImageTintList( context.resources.getColorStateList(renderInfo.foreground, context.theme)) } @@ -176,4 +174,4 @@ class ControlsRequestDialog @Inject constructor( } finish() } -} \ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt index eb84a8bcbfbdf..680d0066fc56f 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt @@ -20,6 +20,7 @@ import android.app.PendingIntent import android.content.Intent import android.provider.Settings import android.service.controls.actions.BooleanAction +import android.service.controls.actions.CommandAction import android.util.Log import android.view.HapticFeedbackConstants @@ -36,6 +37,10 @@ object ControlActionCoordinator { cvh.clipLayer.setLevel(nextLevel) } + fun touch(cvh: ControlViewHolder, templateId: String) { + cvh.action(CommandAction(templateId)) + } + fun longPress(cvh: ControlViewHolder) { // Long press snould only be called when there is valid control state, otherwise ignore cvh.cws.control?.let { diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt index b1b98bc7d044e..fc5663fe8c97a 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt @@ -19,11 +19,11 @@ package com.android.systemui.controls.ui import android.content.Context import android.graphics.BlendMode import android.graphics.drawable.ClipDrawable -import android.graphics.drawable.Icon import android.graphics.drawable.LayerDrawable import android.service.controls.Control import android.service.controls.actions.ControlAction import android.service.controls.templates.ControlTemplate +import android.service.controls.templates.StatelessTemplate import android.service.controls.templates.TemperatureControlTemplate import android.service.controls.templates.ToggleRangeTemplate import android.service.controls.templates.ToggleTemplate @@ -122,19 +122,25 @@ class ControlViewHolder( return when { status == Control.STATUS_UNKNOWN -> UnknownBehavior::class template is ToggleTemplate -> ToggleBehavior::class + template is StatelessTemplate -> TouchBehavior::class template is ToggleRangeTemplate -> ToggleRangeBehavior::class template is TemperatureControlTemplate -> TemperatureControlBehavior::class else -> DefaultBehavior::class } } - internal fun applyRenderInfo(ri: RenderInfo) { + internal fun applyRenderInfo(enabled: Boolean, offset: Int = 0) { + setEnabled(enabled) + + val deviceType = cws.control?.let { it.getDeviceType() } ?: cws.ci.deviceType + val ri = RenderInfo.lookup(context, cws.componentName, deviceType, enabled, offset) + val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme()) val bg = context.getResources().getColorStateList(ri.background, context.getTheme()) status.setTextColor(fg) statusExtra.setTextColor(fg) - icon.setImageIcon(Icon.createWithResource(context, ri.iconResourceId)) + icon.setImageDrawable(ri.icon) icon.setImageTintList(fg) clipLayer.getDrawable().apply { @@ -143,7 +149,7 @@ class ControlViewHolder( } } - fun setEnabled(enabled: Boolean) { + private fun setEnabled(enabled: Boolean) { status.setEnabled(enabled) icon.setEnabled(enabled) } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt index 826618a51d8f5..bde966ca067e5 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -188,36 +188,23 @@ class ControlsUiControllerImpl @Inject constructor ( parent.removeAllViews() controlViewsById.clear() - val inflater = LayoutInflater.from(context) - inflater.inflate(R.layout.controls_with_favorites, parent, true) + createListView() + createDropDown(items) + } - val listView = parent.requireViewById(R.id.global_actions_controls_list) as ViewGroup - var lastRow: ViewGroup = createRow(inflater, listView) - selectedStructure.controls.forEach { - if (lastRow.getChildCount() == 2) { - lastRow = createRow(inflater, listView) - } - val item = inflater.inflate( - R.layout.controls_base_item, lastRow, false) as ViewGroup - lastRow.addView(item) - val cvh = ControlViewHolder(item, controlsController.get(), uiExecutor, bgExecutor) - val key = ControlKey(selectedStructure.componentName, it.controlId) - cvh.bindData(controlsById.getValue(key)) - controlViewsById.put(key, cvh) - } - - // add spacer if necessary to keep control size consistent - if ((selectedStructure.controls.size % 2) == 1) { - lastRow.addView(Space(context), LinearLayout.LayoutParams(0, 0, 1f)) + private fun createDropDown(items: List) { + items.forEach { + RenderInfo.registerComponentIcon(it.componentName, it.icon) } val itemsByComponent = items.associateBy { it.componentName } - var adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply { - val listItems = allStructures.mapNotNull { - itemsByComponent.get(it.componentName)?.copy(structure = it.structure) - } + val itemsWithStructure = allStructures.mapNotNull { + itemsByComponent.get(it.componentName)?.copy(structure = it.structure) + } + val selectionItem = findSelectionItem(selectedStructure, itemsWithStructure) ?: items[0] - addAll(listItems + addControlsItem) + var adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply { + addAll(itemsWithStructure + addControlsItem) } /* @@ -225,16 +212,15 @@ class ControlsUiControllerImpl @Inject constructor ( * for this dialog. Use a textView with the ListPopupWindow to achieve * a similar effect */ - val item = adapter.findSelectionItem(selectedStructure) ?: adapter.getItem(0) parent.requireViewById(R.id.app_or_structure_spinner).apply { - setText(item.getTitle()) + setText(selectionItem.getTitle()) // override the default color on the dropdown drawable (getBackground() as LayerDrawable).getDrawable(1) .setTint(context.resources.getColor(R.color.control_spinner_dropdown, null)) } parent.requireViewById(R.id.app_icon).apply { - setContentDescription(item.getTitle()) - setImageDrawable(item.icon) + setContentDescription(selectionItem.getTitle()) + setImageDrawable(selectionItem.icon) } val anchor = parent.requireViewById(R.id.controls_header) anchor.setOnClickListener(object : View.OnClickListener { @@ -272,6 +258,36 @@ class ControlsUiControllerImpl @Inject constructor ( }) } + private fun createListView() { + val inflater = LayoutInflater.from(context) + inflater.inflate(R.layout.controls_with_favorites, parent, true) + + val listView = parent.requireViewById(R.id.global_actions_controls_list) as ViewGroup + var lastRow: ViewGroup = createRow(inflater, listView) + selectedStructure.controls.forEach { + if (lastRow.getChildCount() == 2) { + lastRow = createRow(inflater, listView) + } + val baseLayout = inflater.inflate( + R.layout.controls_base_item, lastRow, false) as ViewGroup + lastRow.addView(baseLayout) + val cvh = ControlViewHolder( + baseLayout, + controlsController.get(), + uiExecutor, + bgExecutor + ) + val key = ControlKey(selectedStructure.componentName, it.controlId) + cvh.bindData(controlsById.getValue(key)) + controlViewsById.put(key, cvh) + } + + // add spacer if necessary to keep control size consistent + if ((selectedStructure.controls.size % 2) == 1) { + lastRow.addView(Space(context), LinearLayout.LayoutParams(0, 0, 1f)) + } + } + private fun loadPreference(structures: List): StructureInfo { if (structures.isEmpty()) return EMPTY_STRUCTURE @@ -320,6 +336,8 @@ class ControlsUiControllerImpl @Inject constructor ( controlsById.clear() controlViewsById.clear() controlsListingController.get().removeCallback(listingCallback) + + RenderInfo.clearCache() } override fun onRefreshState(componentName: ComponentName, controls: List) { @@ -358,6 +376,11 @@ class ControlsUiControllerImpl @Inject constructor ( listView.addView(row) return row } + + private fun findSelectionItem(si: StructureInfo, items: List): SelectionItem? = + items.firstOrNull { + it.componentName == si.componentName && it.structure == si.structure + } } private data class SelectionItem( @@ -388,17 +411,4 @@ private class ItemAdapter( } return view } - - fun findSelectionItem(si: StructureInfo): SelectionItem? { - var i = 0 - while (i < getCount()) { - val item = getItem(i) - if (item.componentName == si.componentName && - item.structure == si.structure) { - return item - } - i++ - } - return null - } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DefaultBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DefaultBehavior.kt index 17479293f7dcb..e850a6a559d68 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/DefaultBehavior.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DefaultBehavior.kt @@ -25,7 +25,6 @@ class DefaultBehavior : Behavior { override fun bind(cws: ControlWithState) { cvh.status.setText(cws.control?.getStatusText() ?: "") - cvh.setEnabled(false) - cvh.applyRenderInfo(RenderInfo.lookup(cws.ci.deviceType, false)) + cvh.applyRenderInfo(false) } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt index da52c6f8ee21d..56267beb1b71f 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt @@ -16,8 +16,14 @@ package com.android.systemui.controls.ui +import android.annotation.MainThread +import android.content.ComponentName +import android.content.Context +import android.graphics.drawable.Drawable import android.service.controls.DeviceTypes import android.service.controls.templates.TemperatureControlTemplate +import android.util.ArrayMap +import android.util.SparseArray import com.android.systemui.R @@ -31,18 +37,54 @@ data class IconState(val disabledResourceId: Int, val enabledResourceId: Int) { } } -data class RenderInfo(val iconResourceId: Int, val foreground: Int, val background: Int) { +data class RenderInfo(val icon: Drawable, val foreground: Int, val background: Int) { companion object { - fun lookup(deviceType: Int, enabled: Boolean): RenderInfo { - val iconState = deviceIconMap.getValue(deviceType) + const val APP_ICON_ID = -1 + private val iconMap = SparseArray() + private val appIconMap = ArrayMap() + + @MainThread + fun lookup( + context: Context, + componentName: ComponentName, + deviceType: Int, + enabled: Boolean, + offset: Int = 0 + ): RenderInfo { val (fg, bg) = deviceColorMap.getValue(deviceType) - return RenderInfo(iconState[enabled], fg, bg) + + val iconKey = if (offset > 0) { + deviceType * BUCKET_SIZE + offset + } else deviceType + + val iconState = deviceIconMap.getValue(iconKey) + val resourceId = iconState[enabled] + var icon: Drawable? = null + if (resourceId == APP_ICON_ID) { + icon = appIconMap.get(componentName) + if (icon == null) { + icon = context.resources + .getDrawable(R.drawable.ic_device_unknown_gm2_24px, null) + appIconMap.put(componentName, icon) + } + } else { + icon = iconMap.get(resourceId) + if (icon == null) { + icon = context.resources.getDrawable(resourceId, null) + iconMap.put(resourceId, icon) + } + } + return RenderInfo(icon!!, fg, bg) } - fun lookup(deviceType: Int, offset: Int, enabled: Boolean): RenderInfo { - val key = deviceType * BUCKET_SIZE + offset - return lookup(key, enabled) + fun registerComponentIcon(componentName: ComponentName, icon: Drawable) { + appIconMap.put(componentName, icon) + } + + fun clearCache() { + iconMap.clear() + appIconMap.clear() } } } @@ -116,6 +158,10 @@ private val deviceIconMap = mapOf( DeviceTypes.TYPE_MOP to IconState( R.drawable.ic_vacuum_gm2_24px, R.drawable.ic_vacuum_gm2_24px + ), + DeviceTypes.TYPE_ROUTINE to IconState( + RenderInfo.APP_ICON_ID, + RenderInfo.APP_ICON_ID ) ).withDefault { IconState( diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt index 239d2e5477bf8..15c1dabf71bd7 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt @@ -47,10 +47,7 @@ class TemperatureControlBehavior : Behavior { val activeMode = template.getCurrentActiveMode() val enabled = activeMode != 0 && activeMode != TemperatureControlTemplate.MODE_OFF - val deviceType = control.getDeviceType() - clipLayer.setLevel(if (enabled) MAX_LEVEL else MIN_LEVEL) - cvh.setEnabled(enabled) - cvh.applyRenderInfo(RenderInfo.lookup(deviceType, activeMode, enabled)) + cvh.applyRenderInfo(enabled, activeMode) } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt index d306d7c84e7f6..a3368ef77a56a 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt @@ -34,7 +34,7 @@ class ToggleBehavior : Behavior { override fun initialize(cvh: ControlViewHolder) { this.cvh = cvh - cvh.setEnabled(false) + cvh.applyRenderInfo(false) cvh.layout.setOnClickListener(View.OnClickListener() { ControlActionCoordinator.toggle(cvh, template.getTemplateId(), template.isChecked()) @@ -51,10 +51,7 @@ class ToggleBehavior : Behavior { clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) val checked = template.isChecked() - val deviceType = control.getDeviceType() - clipLayer.setLevel(if (checked) MAX_LEVEL else MIN_LEVEL) - cvh.setEnabled(checked) - cvh.applyRenderInfo(RenderInfo.lookup(deviceType, checked)) + cvh.applyRenderInfo(checked) } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt index cca56c2199726..6595b55a691d4 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt @@ -56,7 +56,7 @@ class ToggleRangeBehavior : Behavior { status = cvh.status context = status.getContext() - cvh.setEnabled(false) + cvh.applyRenderInfo(false) val gestureListener = ToggleRangeGestureListener(cvh.layout) val gestureDetector = GestureDetector(context, gestureListener) @@ -89,14 +89,11 @@ class ToggleRangeBehavior : Behavior { rangeTemplate = template.getRange() val checked = template.isChecked() - val deviceType = control.getDeviceType() - val currentRatio = rangeTemplate.getCurrentValue() / (rangeTemplate.getMaxValue() - rangeTemplate.getMinValue()) updateRange(currentRatio, checked) - cvh.setEnabled(checked) - cvh.applyRenderInfo(RenderInfo.lookup(deviceType, checked)) + cvh.applyRenderInfo(checked) } fun beginUpdateRange() { diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt new file mode 100644 index 0000000000000..d64a5f0604873 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 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.controls.ui + +import android.graphics.drawable.Drawable +import android.graphics.drawable.LayerDrawable +import android.view.View +import android.service.controls.Control +import android.service.controls.templates.StatelessTemplate + +import com.android.systemui.R +import com.android.systemui.controls.ui.ControlActionCoordinator.MIN_LEVEL + +/** + * Supports touch events, but has no notion of state as the {@link ToggleBehavior} does. Must be + * used with {@link StatelessTemplate}. + */ +class TouchBehavior : Behavior { + lateinit var clipLayer: Drawable + lateinit var template: StatelessTemplate + lateinit var control: Control + lateinit var cvh: ControlViewHolder + + override fun initialize(cvh: ControlViewHolder) { + this.cvh = cvh + cvh.applyRenderInfo(false) + + cvh.layout.setOnClickListener(View.OnClickListener() { + ControlActionCoordinator.touch(cvh, template.getTemplateId()) + }) + } + + override fun bind(cws: ControlWithState) { + this.control = cws.control!! + cvh.status.setText(control.getStatusText()) + template = control.getControlTemplate() as StatelessTemplate + + val ld = cvh.layout.getBackground() as LayerDrawable + clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) + clipLayer.setLevel(MIN_LEVEL) + + cvh.applyRenderInfo(false) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/UnknownBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/UnknownBehavior.kt index 1f33b8515dc70..c3572491f9f1d 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/UnknownBehavior.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/UnknownBehavior.kt @@ -25,7 +25,6 @@ class UnknownBehavior : Behavior { override fun bind(cws: ControlWithState) { cvh.status.setText(cvh.context.getString(com.android.internal.R.string.loading)) - cvh.setEnabled(false) - cvh.applyRenderInfo(RenderInfo.lookup(cws.ci.deviceType, false)) + cvh.applyRenderInfo(false) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt index a8c4851585db6..91583c2fd7abe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt @@ -234,7 +234,7 @@ class ControlsControllerImplTest : SysuiTestCase() { loaded = true assertEquals(1, controls.size) val controlStatus = controls[0] - assertEquals(ControlStatus(control, false), controlStatus) + assertEquals(ControlStatus(control, TEST_COMPONENT, false), controlStatus) assertTrue(favorites.isEmpty()) assertFalse(data.errorOnLoad) @@ -265,10 +265,10 @@ class ControlsControllerImplTest : SysuiTestCase() { loaded = true assertEquals(2, controls.size) val controlStatus = controls.first { it.control.controlId == TEST_CONTROL_ID } - assertEquals(ControlStatus(control, true), controlStatus) + assertEquals(ControlStatus(control, TEST_COMPONENT, true), controlStatus) val controlStatus2 = controls.first { it.control.controlId == TEST_CONTROL_ID_2 } - assertEquals(ControlStatus(control2, false), controlStatus2) + assertEquals(ControlStatus(control2, TEST_COMPONENT, false), controlStatus2) assertEquals(1, favorites.size) assertEquals(TEST_CONTROL_ID, favorites[0]) diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/AllModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/AllModelTest.kt index 68e1ec1d9f1d5..133df2aa203f1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/AllModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/AllModelTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.controls.management import android.app.PendingIntent +import android.content.ComponentName import android.service.controls.Control import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest @@ -78,6 +79,7 @@ class AllModelTest : SysuiTestCase() { Control.StatelessBuilder("$idPrefix$it", pendingIntent) .setZone(zoneMap(it)) .build(), + ComponentName("", ""), it in favoritesIndices ) } @@ -189,4 +191,4 @@ class AllModelTest : SysuiTestCase() { assertTrue(sameControl(it.first, it.second)) } } -} \ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoriteModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoriteModelTest.kt index 9ffc29e0eb7ef..c330b38fed422 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoriteModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoriteModelTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.controls.management import android.app.PendingIntent +import android.content.ComponentName import android.service.controls.Control import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest @@ -70,6 +71,7 @@ open class FavoriteModelTest : SysuiTestCase() { Control.StatelessBuilder("$idPrefix$it", pendingIntent) .setZone((it % 3).toString()) .build(), + ComponentName("", ""), it in favoritesIndices ) } @@ -195,4 +197,4 @@ class FavoriteModelParameterizedTest(val from: Int, val to: Int) : FavoriteModel verifyNoMoreInteractions(allAdapter, favoritesAdapter) } -} \ No newline at end of file +}