diff options
6 files changed, 12 insertions, 382 deletions
diff --git a/packages/SystemUI/res/layout/bindable_status_bar_icon.xml b/packages/SystemUI/res/layout/bindable_status_bar_icon.xml deleted file mode 100644 index ee4d05c3bda5..000000000000 --- a/packages/SystemUI/res/layout/bindable_status_bar_icon.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?><!-- - ~ 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. - --> - -<!-- Base layout that provides a single bindable icon_view id image view --> -<com.android.systemui.statusbar.pipeline.shared.ui.view.SingleBindableStatusBarIconView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="center_vertical" - > - - <ImageView - android:id="@+id/icon_view" - android:layout_height="@dimen/status_bar_bindable_icon_size" - android:layout_width="wrap_content" - android:layout_gravity="center_vertical" - android:padding="@dimen/status_bar_bindable_icon_padding" - android:scaleType="fitCenter" - /> - -</com.android.systemui.statusbar.pipeline.shared.ui.view.SingleBindableStatusBarIconView> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 59bc9772bf9f..90d8cdb724e4 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -151,8 +151,6 @@ <dimen name="status_bar_icon_size_sp">@*android:dimen/status_bar_icon_size_sp</dimen> <!-- Original dp height of notification icons in the status bar --> <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen> - <dimen name="status_bar_bindable_icon_size">20sp</dimen> - <dimen name="status_bar_bindable_icon_padding">2sp</dimen> <!-- Default horizontal drawable padding for status bar icons. --> <dimen name="status_bar_horizontal_padding">2.5sp</dimen> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt index 0051161eff35..1d514b40ec9b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt @@ -23,6 +23,7 @@ import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconM import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine @@ -52,17 +53,16 @@ constructor( } .stateIn(scope, SharingStarted.WhileSubscribed(), false) - val icon: StateFlow<Icon?> = + val icon: Flow<Icon?> = combine( - shouldShowIcon, - interactor.connectionState, - interactor.signalStrength, - ) { shouldShow, state, signalStrength -> - if (shouldShow) { - SatelliteIconModel.fromConnectionState(state, signalStrength) - } else { - null - } + shouldShowIcon, + interactor.connectionState, + interactor.signalStrength, + ) { shouldShow, state, signalStrength -> + if (shouldShow) { + SatelliteIconModel.fromConnectionState(state, signalStrength) + } else { + null } - .stateIn(scope, SharingStarted.WhileSubscribed(), null) + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt index 25a2c9dd3caf..3b87bed2e0ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt @@ -103,7 +103,7 @@ open class ModernStatusBarView(context: Context, attrs: AttributeSet?) : * * Creates a dot view, and uses [bindingCreator] to get and set the binding. */ - open fun initView(slot: String, bindingCreator: () -> ModernStatusBarViewBinding) { + fun initView(slot: String, bindingCreator: () -> ModernStatusBarViewBinding) { // The dot view requires [slot] to be set, and the [binding] may require an instantiated dot // view. So, this is the required order. this.slot = slot diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconView.kt deleted file mode 100644 index c663c37fec98..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconView.kt +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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.statusbar.pipeline.shared.ui.view - -import android.content.Context -import android.content.res.ColorStateList -import android.graphics.Color -import android.util.AttributeSet -import android.view.LayoutInflater -import android.view.View -import android.widget.ImageView -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle -import com.android.internal.annotations.VisibleForTesting -import com.android.systemui.lifecycle.repeatWhenAttached -import com.android.systemui.res.R -import com.android.systemui.statusbar.StatusBarIconView -import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN -import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewBinding -import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewVisibilityHelper -import kotlinx.coroutines.awaitCancellation -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.launch - -/** Simple single-icon view that is bound to bindable_status_bar_icon.xml */ -class SingleBindableStatusBarIconView( - context: Context, - attrs: AttributeSet?, -) : ModernStatusBarView(context, attrs) { - - internal lateinit var iconView: ImageView - internal lateinit var dotView: StatusBarIconView - - override fun toString(): String { - return "SingleBindableStatusBarIcon(" + - "slot='$slot', " + - "isCollecting=${binding.isCollecting()}, " + - "visibleState=${StatusBarIconView.getVisibleStateString(visibleState)}); " + - "viewString=${super.toString()}" - } - - override fun initView(slot: String, bindingCreator: () -> ModernStatusBarViewBinding) { - super.initView(slot, bindingCreator) - - iconView = requireViewById(R.id.icon_view) - dotView = requireViewById(R.id.status_bar_dot) - } - - companion object { - fun createView( - context: Context, - ): SingleBindableStatusBarIconView { - return LayoutInflater.from(context).inflate(R.layout.bindable_status_bar_icon, null) - as SingleBindableStatusBarIconView - } - - /** - * Using a given binding [block], create the necessary scaffolding to handle the general - * case of a single status bar icon. This includes eliding into a dot view when there is not - * enough space, and handling tint. - * - * [block] should be a simple [launch] call that handles updating the single icon view with - * its new view. Currently there is no simple way to e.g., extend to handle multiple tints - * for dual-layered icons, and any more complex logic should probably find a way to return - * its own version of [ModernStatusBarViewBinding]. - */ - fun withDefaultBinding( - view: SingleBindableStatusBarIconView, - shouldBeVisible: () -> Boolean, - block: suspend LifecycleOwner.(View) -> Unit - ): SingleBindableStatusBarIconViewBinding { - @StatusBarIconView.VisibleState - val visibilityState: MutableStateFlow<Int> = MutableStateFlow(STATE_HIDDEN) - - val iconTint: MutableStateFlow<Int> = MutableStateFlow(Color.WHITE) - val decorTint: MutableStateFlow<Int> = MutableStateFlow(Color.WHITE) - - var isCollecting: Boolean = false - - view.repeatWhenAttached { - // Child binding - block(view) - - lifecycleScope.launch { - repeatOnLifecycle(Lifecycle.State.STARTED) { - // isVisible controls the visibility state of the outer group, and thus it - // needs - // to run in the CREATED lifecycle so it can continue to watch while - // invisible - // See (b/291031862) for details - launch { - visibilityState.collect { visibilityState -> - // for b/296864006, we can not hide all the child views if - // visibilityState is STATE_HIDDEN. Because hiding all child views - // would cause the - // getWidth() of this view return 0, and that would cause the - // translation - // calculation fails in StatusIconContainer. Therefore, like class - // MobileIconBinder, instead of set the child views visibility to - // View.GONE, - // we set their visibility to View.INVISIBLE to make them invisible - // but - // keep the width. - ModernStatusBarViewVisibilityHelper.setVisibilityState( - visibilityState, - view.iconView, - view.dotView, - ) - } - } - - launch { - iconTint.collect { tint -> - val tintList = ColorStateList.valueOf(tint) - view.iconView.imageTintList = tintList - view.dotView.setDecorColor(tint) - } - } - - launch { - decorTint.collect { decorTint -> view.dotView.setDecorColor(decorTint) } - } - - try { - awaitCancellation() - } finally { - isCollecting = false - } - } - } - } - - return object : SingleBindableStatusBarIconViewBinding { - override val decorTint: Int - get() = decorTint.value - - override val iconTint: Int - get() = iconTint.value - - override fun getShouldIconBeVisible(): Boolean { - return shouldBeVisible() - } - - override fun onVisibilityStateChanged(state: Int) { - visibilityState.value = state - } - - override fun onIconTintChanged(newTint: Int, contrastTint: Int) { - iconTint.value = newTint - } - - override fun onDecorTintChanged(newTint: Int) { - decorTint.value = newTint - } - - override fun isCollecting(): Boolean { - return isCollecting - } - } - } - } -} - -@VisibleForTesting -interface SingleBindableStatusBarIconViewBinding : ModernStatusBarViewBinding { - val iconTint: Int - val decorTint: Int -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt deleted file mode 100644 index ca9df57e8798..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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.statusbar.pipeline.shared.ui.view - -import android.graphics.Rect -import android.testing.AndroidTestingRunner -import android.testing.TestableLooper -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.statusbar.StatusBarIconView -import com.google.common.truth.Truth.assertThat -import org.junit.Test -import org.junit.runner.RunWith - -/** - * Being a simple subclass of [ModernStatusBarView], use the same basic test cases to verify the - * root behavior, and add testing for the new [SingleBindableStatusBarIconView.withDefaultBinding] - * method. - */ -@SmallTest -@RunWith(AndroidTestingRunner::class) -@TestableLooper.RunWithLooper(setAsMainLooper = true) -class SingleBindableStatusBarIconViewTest : SysuiTestCase() { - private lateinit var binding: SingleBindableStatusBarIconViewBinding - - // Visibility is outsourced to view-models. This simulates it - private var isVisible = true - private var visibilityFn: () -> Boolean = { isVisible } - - @Test - fun initView_hasCorrectSlot() { - val view = createAndInitView() - - assertThat(view.slot).isEqualTo(SLOT_NAME) - } - - @Test - fun getVisibleState_icon_returnsIcon() { - val view = createAndInitView() - - view.setVisibleState(StatusBarIconView.STATE_ICON, /* animate= */ false) - - assertThat(view.visibleState).isEqualTo(StatusBarIconView.STATE_ICON) - } - - @Test - fun getVisibleState_dot_returnsDot() { - val view = createAndInitView() - - view.setVisibleState(StatusBarIconView.STATE_DOT, /* animate= */ false) - - assertThat(view.visibleState).isEqualTo(StatusBarIconView.STATE_DOT) - } - - @Test - fun getVisibleState_hidden_returnsHidden() { - val view = createAndInitView() - - view.setVisibleState(StatusBarIconView.STATE_HIDDEN, /* animate= */ false) - - assertThat(view.visibleState).isEqualTo(StatusBarIconView.STATE_HIDDEN) - } - - @Test - fun onDarkChanged_bindingReceivesIconAndDecorTint() { - val view = createAndInitView() - - view.onDarkChangedWithContrast(arrayListOf(), 0x12345678, 0x12344321) - - assertThat(binding.iconTint).isEqualTo(0x12345678) - assertThat(binding.decorTint).isEqualTo(0x12345678) - } - - @Test - fun setStaticDrawableColor_bindingReceivesIconTint() { - val view = createAndInitView() - - view.setStaticDrawableColor(0x12345678, 0x12344321) - - assertThat(binding.iconTint).isEqualTo(0x12345678) - } - - @Test - fun setDecorColor_bindingReceivesDecorColor() { - val view = createAndInitView() - - view.setDecorColor(0x23456789) - - assertThat(binding.decorTint).isEqualTo(0x23456789) - } - - @Test - fun isIconVisible_usesBinding_true() { - val view = createAndInitView() - - isVisible = true - - assertThat(view.isIconVisible).isEqualTo(true) - } - - @Test - fun isIconVisible_usesBinding_false() { - val view = createAndInitView() - - isVisible = false - - assertThat(view.isIconVisible).isEqualTo(false) - } - - @Test - fun getDrawingRect_takesTranslationIntoAccount() { - val view = createAndInitView() - - view.translationX = 50f - view.translationY = 60f - - val drawingRect = Rect() - view.getDrawingRect(drawingRect) - - assertThat(drawingRect.left).isEqualTo(view.left + 50) - assertThat(drawingRect.right).isEqualTo(view.right + 50) - assertThat(drawingRect.top).isEqualTo(view.top + 60) - assertThat(drawingRect.bottom).isEqualTo(view.bottom + 60) - } - - private fun createAndInitView(): SingleBindableStatusBarIconView { - val view = SingleBindableStatusBarIconView.createView(context) - binding = SingleBindableStatusBarIconView.withDefaultBinding(view, visibilityFn) {} - view.initView(SLOT_NAME) { binding } - return view - } - - companion object { - private const val SLOT_NAME = "test_slot" - } -} |