Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/systemstatusicons/ethernet/ui/viewmodel/EthernetIconViewModelTest.kt 0 → 100644 +144 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.systemstatusicons.ethernet.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.AccessibilityContentDescriptions import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.lifecycle.activateIn import com.android.systemui.res.R import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.statusbar.pipeline.shared.data.repository.connectivityRepository import com.android.systemui.statusbar.pipeline.shared.data.repository.fake import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class EthernetIconViewModelTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val fakeConnectivityRepository: FakeConnectivityRepository by lazy { kosmos.connectivityRepository.fake } private val underTest = kosmos.ethernetIconViewModelFactory.create() @Before fun setUp() { underTest.activateIn(kosmos.testScope) } @Test fun icon_default_validated() = kosmos.runTest { // Ethernet is the default connection and validated fakeConnectivityRepository.setEthernetConnected(default = true, validated = true) // Icon is the 'fully connected' ethernet icon val expected = Icon.Resource( R.drawable.stat_sys_ethernet_fully, ContentDescription.Resource( AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES[1] ), ) assertThat(underTest.icon).isEqualTo(expected) } @Test fun icon_default_notValidated() = kosmos.runTest { // Ethernet is the default connection but not validated fakeConnectivityRepository.setEthernetConnected(default = true, validated = false) // Icon is the 'connected, not validated' ethernet icon val expected = Icon.Resource( R.drawable.stat_sys_ethernet, ContentDescription.Resource( AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES[0] ), ) assertThat(underTest.icon).isEqualTo(expected) } @Test fun icon_notDefault_validated() = kosmos.runTest { // Ethernet is connected and validated, but NOT the default connection fakeConnectivityRepository.setEthernetConnected(default = false, validated = true) // Icon is null (we only show the icon for the default connection) assertThat(underTest.icon).isNull() } @Test fun icon_notDefault_notValidated() = kosmos.runTest { // Ethernet is connected, but NOT validated and NOT the default connection fakeConnectivityRepository.setEthernetConnected(default = false, validated = false) // Icon is null assertThat(underTest.icon).isNull() } @Test fun icon_updatesWhenConnectivityChanges() = kosmos.runTest { // Start default and validated fakeConnectivityRepository.setEthernetConnected(default = true, validated = true) val expectedFully = Icon.Resource( R.drawable.stat_sys_ethernet_fully, ContentDescription.Resource( AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES[1] ), ) assertThat(underTest.icon).isEqualTo(expectedFully) // Change to default but not validated fakeConnectivityRepository.setEthernetConnected(default = true, validated = false) val expectedNotValidated = Icon.Resource( R.drawable.stat_sys_ethernet, ContentDescription.Resource( AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES[0] ), ) assertThat(underTest.icon).isEqualTo(expectedNotValidated) // Change to not default fakeConnectivityRepository.setEthernetConnected(default = false, validated = false) assertThat(underTest.icon).isNull() // Change back to default and validated fakeConnectivityRepository.setEthernetConnected(default = true, validated = true) assertThat(underTest.icon).isEqualTo(expectedFully) } } packages/SystemUI/src/com/android/systemui/statusbar/systemstatusicons/ethernet/ui/viewmodel/EthernetIconViewModel.kt 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.systemstatusicons.ethernet.ui.viewmodel import androidx.compose.runtime.getValue import com.android.systemui.common.shared.model.Icon import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.lifecycle.Hydrator import com.android.systemui.statusbar.pipeline.ethernet.domain.EthernetInteractor import com.android.systemui.statusbar.systemstatusicons.SystemStatusIconsInCompose import com.android.systemui.statusbar.systemstatusicons.ui.viewmodel.SystemStatusIconViewModel import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject /** * View model for the ethernet system status icon. Emits an icon when ethernet is connected and the * default connection. Null icon otherwise. */ class EthernetIconViewModel @AssistedInject constructor(interactor: EthernetInteractor) : SystemStatusIconViewModel, ExclusiveActivatable() { init { /* check if */ SystemStatusIconsInCompose.isUnexpectedlyInLegacyMode() } private val hydrator = Hydrator("EthernetIconViewModel.hydrator") override val icon: Icon? by hydrator.hydratedStateOf(traceName = null, initialValue = null, source = interactor.icon) override suspend fun onActivated(): Nothing { hydrator.activate() } @AssistedFactory interface Factory { fun create(): EthernetIconViewModel } } packages/SystemUI/src/com/android/systemui/statusbar/systemstatusicons/ui/viewmodel/SystemStatusIconsViewModel.kt +17 −4 Original line number Diff line number Diff line Loading @@ -20,8 +20,12 @@ import com.android.systemui.common.shared.model.Icon import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.statusbar.systemstatusicons.SystemStatusIconsInCompose import com.android.systemui.statusbar.systemstatusicons.airplane.ui.viewmodel.AirplaneModeIconViewModel import com.android.systemui.statusbar.systemstatusicons.ethernet.ui.viewmodel.EthernetIconViewModel import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch /** * ViewModel for managing and displaying a list of system status icons. Loading @@ -31,21 +35,30 @@ import dagger.assisted.AssistedInject */ class SystemStatusIconsViewModel @AssistedInject constructor(airplaneModeIconViewModelFactory: AirplaneModeIconViewModel.Factory) : ExclusiveActivatable() { constructor( airplaneModeIconViewModelFactory: AirplaneModeIconViewModel.Factory, ethernetIconViewModelFactory: EthernetIconViewModel.Factory, ) : ExclusiveActivatable() { init { /* check if */ SystemStatusIconsInCompose.isUnexpectedlyInLegacyMode() } private val airplaneModeIcon by lazy { airplaneModeIconViewModelFactory.create() } private val iconViewModels by lazy { listOf(airplaneModeIcon) } private val ethernetIcon by lazy { ethernetIconViewModelFactory.create() } private val iconViewModels: List<SystemStatusIconViewModel> by lazy { listOf(ethernetIcon, airplaneModeIcon) } val icons: List<Icon> get() = iconViewModels.mapNotNull { viewModel -> viewModel.icon } override suspend fun onActivated(): Nothing { airplaneModeIcon.activate() coroutineScope { launch { ethernetIcon.activate() } launch { airplaneModeIcon.activate() } } awaitCancellation() } @AssistedFactory Loading packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/systemstatusicons/ethernet/ui/viewmodel/EthernetIconViewModelKosmos.kt 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.systemstatusicons.ethernet.ui.viewmodel import com.android.systemui.kosmos.Kosmos import com.android.systemui.statusbar.pipeline.ethernet.domain.ethernetInteractor private val Kosmos.ethernetIconViewModel: EthernetIconViewModel by Kosmos.Fixture { EthernetIconViewModel(ethernetInteractor) } val Kosmos.ethernetIconViewModelFactory: EthernetIconViewModel.Factory by Kosmos.Fixture { object : EthernetIconViewModel.Factory { override fun create(): EthernetIconViewModel = ethernetIconViewModel } } packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/systemstatusicons/ui/viewmodel/SystemStatusIconsViewModelKosmos.kt +3 −1 Original line number Diff line number Diff line Loading @@ -18,11 +18,13 @@ package com.android.systemui.statusbar.systemstatusicons.ui.viewmodel import com.android.systemui.kosmos.Kosmos import com.android.systemui.statusbar.systemstatusicons.airplane.ui.viewmodel.airplaneModeIconViewModelFactory import com.android.systemui.statusbar.systemstatusicons.ethernet.ui.viewmodel.ethernetIconViewModelFactory val Kosmos.systemStatusIconsViewModel by Kosmos.Fixture { SystemStatusIconsViewModel( airplaneModeIconViewModelFactory = airplaneModeIconViewModelFactory airplaneModeIconViewModelFactory = airplaneModeIconViewModelFactory, ethernetIconViewModelFactory = ethernetIconViewModelFactory, ) } Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/systemstatusicons/ethernet/ui/viewmodel/EthernetIconViewModelTest.kt 0 → 100644 +144 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.systemstatusicons.ethernet.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.AccessibilityContentDescriptions import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.lifecycle.activateIn import com.android.systemui.res.R import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.statusbar.pipeline.shared.data.repository.connectivityRepository import com.android.systemui.statusbar.pipeline.shared.data.repository.fake import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class EthernetIconViewModelTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val fakeConnectivityRepository: FakeConnectivityRepository by lazy { kosmos.connectivityRepository.fake } private val underTest = kosmos.ethernetIconViewModelFactory.create() @Before fun setUp() { underTest.activateIn(kosmos.testScope) } @Test fun icon_default_validated() = kosmos.runTest { // Ethernet is the default connection and validated fakeConnectivityRepository.setEthernetConnected(default = true, validated = true) // Icon is the 'fully connected' ethernet icon val expected = Icon.Resource( R.drawable.stat_sys_ethernet_fully, ContentDescription.Resource( AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES[1] ), ) assertThat(underTest.icon).isEqualTo(expected) } @Test fun icon_default_notValidated() = kosmos.runTest { // Ethernet is the default connection but not validated fakeConnectivityRepository.setEthernetConnected(default = true, validated = false) // Icon is the 'connected, not validated' ethernet icon val expected = Icon.Resource( R.drawable.stat_sys_ethernet, ContentDescription.Resource( AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES[0] ), ) assertThat(underTest.icon).isEqualTo(expected) } @Test fun icon_notDefault_validated() = kosmos.runTest { // Ethernet is connected and validated, but NOT the default connection fakeConnectivityRepository.setEthernetConnected(default = false, validated = true) // Icon is null (we only show the icon for the default connection) assertThat(underTest.icon).isNull() } @Test fun icon_notDefault_notValidated() = kosmos.runTest { // Ethernet is connected, but NOT validated and NOT the default connection fakeConnectivityRepository.setEthernetConnected(default = false, validated = false) // Icon is null assertThat(underTest.icon).isNull() } @Test fun icon_updatesWhenConnectivityChanges() = kosmos.runTest { // Start default and validated fakeConnectivityRepository.setEthernetConnected(default = true, validated = true) val expectedFully = Icon.Resource( R.drawable.stat_sys_ethernet_fully, ContentDescription.Resource( AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES[1] ), ) assertThat(underTest.icon).isEqualTo(expectedFully) // Change to default but not validated fakeConnectivityRepository.setEthernetConnected(default = true, validated = false) val expectedNotValidated = Icon.Resource( R.drawable.stat_sys_ethernet, ContentDescription.Resource( AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES[0] ), ) assertThat(underTest.icon).isEqualTo(expectedNotValidated) // Change to not default fakeConnectivityRepository.setEthernetConnected(default = false, validated = false) assertThat(underTest.icon).isNull() // Change back to default and validated fakeConnectivityRepository.setEthernetConnected(default = true, validated = true) assertThat(underTest.icon).isEqualTo(expectedFully) } }
packages/SystemUI/src/com/android/systemui/statusbar/systemstatusicons/ethernet/ui/viewmodel/EthernetIconViewModel.kt 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.systemstatusicons.ethernet.ui.viewmodel import androidx.compose.runtime.getValue import com.android.systemui.common.shared.model.Icon import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.lifecycle.Hydrator import com.android.systemui.statusbar.pipeline.ethernet.domain.EthernetInteractor import com.android.systemui.statusbar.systemstatusicons.SystemStatusIconsInCompose import com.android.systemui.statusbar.systemstatusicons.ui.viewmodel.SystemStatusIconViewModel import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject /** * View model for the ethernet system status icon. Emits an icon when ethernet is connected and the * default connection. Null icon otherwise. */ class EthernetIconViewModel @AssistedInject constructor(interactor: EthernetInteractor) : SystemStatusIconViewModel, ExclusiveActivatable() { init { /* check if */ SystemStatusIconsInCompose.isUnexpectedlyInLegacyMode() } private val hydrator = Hydrator("EthernetIconViewModel.hydrator") override val icon: Icon? by hydrator.hydratedStateOf(traceName = null, initialValue = null, source = interactor.icon) override suspend fun onActivated(): Nothing { hydrator.activate() } @AssistedFactory interface Factory { fun create(): EthernetIconViewModel } }
packages/SystemUI/src/com/android/systemui/statusbar/systemstatusicons/ui/viewmodel/SystemStatusIconsViewModel.kt +17 −4 Original line number Diff line number Diff line Loading @@ -20,8 +20,12 @@ import com.android.systemui.common.shared.model.Icon import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.statusbar.systemstatusicons.SystemStatusIconsInCompose import com.android.systemui.statusbar.systemstatusicons.airplane.ui.viewmodel.AirplaneModeIconViewModel import com.android.systemui.statusbar.systemstatusicons.ethernet.ui.viewmodel.EthernetIconViewModel import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch /** * ViewModel for managing and displaying a list of system status icons. Loading @@ -31,21 +35,30 @@ import dagger.assisted.AssistedInject */ class SystemStatusIconsViewModel @AssistedInject constructor(airplaneModeIconViewModelFactory: AirplaneModeIconViewModel.Factory) : ExclusiveActivatable() { constructor( airplaneModeIconViewModelFactory: AirplaneModeIconViewModel.Factory, ethernetIconViewModelFactory: EthernetIconViewModel.Factory, ) : ExclusiveActivatable() { init { /* check if */ SystemStatusIconsInCompose.isUnexpectedlyInLegacyMode() } private val airplaneModeIcon by lazy { airplaneModeIconViewModelFactory.create() } private val iconViewModels by lazy { listOf(airplaneModeIcon) } private val ethernetIcon by lazy { ethernetIconViewModelFactory.create() } private val iconViewModels: List<SystemStatusIconViewModel> by lazy { listOf(ethernetIcon, airplaneModeIcon) } val icons: List<Icon> get() = iconViewModels.mapNotNull { viewModel -> viewModel.icon } override suspend fun onActivated(): Nothing { airplaneModeIcon.activate() coroutineScope { launch { ethernetIcon.activate() } launch { airplaneModeIcon.activate() } } awaitCancellation() } @AssistedFactory Loading
packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/systemstatusicons/ethernet/ui/viewmodel/EthernetIconViewModelKosmos.kt 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.systemstatusicons.ethernet.ui.viewmodel import com.android.systemui.kosmos.Kosmos import com.android.systemui.statusbar.pipeline.ethernet.domain.ethernetInteractor private val Kosmos.ethernetIconViewModel: EthernetIconViewModel by Kosmos.Fixture { EthernetIconViewModel(ethernetInteractor) } val Kosmos.ethernetIconViewModelFactory: EthernetIconViewModel.Factory by Kosmos.Fixture { object : EthernetIconViewModel.Factory { override fun create(): EthernetIconViewModel = ethernetIconViewModel } }
packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/systemstatusicons/ui/viewmodel/SystemStatusIconsViewModelKosmos.kt +3 −1 Original line number Diff line number Diff line Loading @@ -18,11 +18,13 @@ package com.android.systemui.statusbar.systemstatusicons.ui.viewmodel import com.android.systemui.kosmos.Kosmos import com.android.systemui.statusbar.systemstatusicons.airplane.ui.viewmodel.airplaneModeIconViewModelFactory import com.android.systemui.statusbar.systemstatusicons.ethernet.ui.viewmodel.ethernetIconViewModelFactory val Kosmos.systemStatusIconsViewModel by Kosmos.Fixture { SystemStatusIconsViewModel( airplaneModeIconViewModelFactory = airplaneModeIconViewModelFactory airplaneModeIconViewModelFactory = airplaneModeIconViewModelFactory, ethernetIconViewModelFactory = ethernetIconViewModelFactory, ) } Loading