Merge "[SB Refactor] Create an airplane mode repo/interactor/view model and use it to determine when to show the wifi<->airplane spacer." into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
fd6c30921f
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.airplane.data.repository
|
||||||
|
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.UserHandle
|
||||||
|
import android.provider.Settings.Global
|
||||||
|
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||||
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
|
import com.android.systemui.dagger.qualifiers.Background
|
||||||
|
import com.android.systemui.qs.SettingObserver
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
|
||||||
|
import com.android.systemui.util.settings.GlobalSettings
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides data related to airplane mode.
|
||||||
|
*
|
||||||
|
* IMPORTANT: This is currently *not* used to render any airplane mode information anywhere. It is
|
||||||
|
* only used to help [com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel]
|
||||||
|
* determine what parts of the wifi icon view should be shown.
|
||||||
|
*
|
||||||
|
* TODO(b/238425913): Consider migrating the status bar airplane mode icon to use this repo.
|
||||||
|
*/
|
||||||
|
interface AirplaneModeRepository {
|
||||||
|
/** Observable for whether the device is currently in airplane mode. */
|
||||||
|
val isAirplaneMode: StateFlow<Boolean>
|
||||||
|
}
|
||||||
|
|
||||||
|
@SysUISingleton
|
||||||
|
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
class AirplaneModeRepositoryImpl
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
@Background private val bgHandler: Handler,
|
||||||
|
private val globalSettings: GlobalSettings,
|
||||||
|
logger: ConnectivityPipelineLogger,
|
||||||
|
@Application scope: CoroutineScope,
|
||||||
|
) : AirplaneModeRepository {
|
||||||
|
// TODO(b/254848912): Replace this with a generic SettingObserver coroutine once we have it.
|
||||||
|
override val isAirplaneMode: StateFlow<Boolean> =
|
||||||
|
conflatedCallbackFlow {
|
||||||
|
val observer =
|
||||||
|
object :
|
||||||
|
SettingObserver(
|
||||||
|
globalSettings,
|
||||||
|
bgHandler,
|
||||||
|
Global.AIRPLANE_MODE_ON,
|
||||||
|
UserHandle.USER_ALL
|
||||||
|
) {
|
||||||
|
override fun handleValueChanged(value: Int, observedChange: Boolean) {
|
||||||
|
trySend(value == 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
observer.isListening = true
|
||||||
|
trySend(observer.value == 1)
|
||||||
|
awaitClose { observer.isListening = false }
|
||||||
|
}
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logInputChange(logger, "isAirplaneMode")
|
||||||
|
.stateIn(
|
||||||
|
scope,
|
||||||
|
started = SharingStarted.WhileSubscribed(),
|
||||||
|
// When the observer starts listening, the flow will emit the current value so the
|
||||||
|
// initialValue here is irrelevant.
|
||||||
|
initialValue = false,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.airplane.domain.interactor
|
||||||
|
|
||||||
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The business logic layer for airplane mode.
|
||||||
|
*
|
||||||
|
* IMPORTANT: This is currently *not* used to render any airplane mode information anywhere. See
|
||||||
|
* [AirplaneModeRepository] for more details.
|
||||||
|
*/
|
||||||
|
@SysUISingleton
|
||||||
|
class AirplaneModeInteractor
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
airplaneModeRepository: AirplaneModeRepository,
|
||||||
|
connectivityRepository: ConnectivityRepository,
|
||||||
|
) {
|
||||||
|
/** True if the device is currently in airplane mode. */
|
||||||
|
val isAirplaneMode: Flow<Boolean> = airplaneModeRepository.isAirplaneMode
|
||||||
|
|
||||||
|
/** True if we're configured to force-hide the airplane mode icon and false otherwise. */
|
||||||
|
val isForceHidden: Flow<Boolean> =
|
||||||
|
connectivityRepository.forceHiddenSlots.map { it.contains(ConnectivitySlot.AIRPLANE) }
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.airplane.ui.viewmodel
|
||||||
|
|
||||||
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models the UI state for the status bar airplane mode icon.
|
||||||
|
*
|
||||||
|
* IMPORTANT: This is currently *not* used to render any airplane mode information anywhere. See
|
||||||
|
* [com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository] for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
@SysUISingleton
|
||||||
|
class AirplaneModeViewModel
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
interactor: AirplaneModeInteractor,
|
||||||
|
logger: ConnectivityPipelineLogger,
|
||||||
|
@Application private val scope: CoroutineScope,
|
||||||
|
) {
|
||||||
|
/** True if the airplane mode icon is currently visible in the status bar. */
|
||||||
|
val isAirplaneModeIconVisible: StateFlow<Boolean> =
|
||||||
|
combine(interactor.isAirplaneMode, interactor.isForceHidden) {
|
||||||
|
isAirplaneMode,
|
||||||
|
isAirplaneIconForceHidden ->
|
||||||
|
isAirplaneMode && !isAirplaneIconForceHidden
|
||||||
|
}
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logOutputChange(logger, "isAirplaneModeIconVisible")
|
||||||
|
.stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false)
|
||||||
|
}
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.pipeline.dagger
|
package com.android.systemui.statusbar.pipeline.dagger
|
||||||
|
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepositoryImpl
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileSubscriptionRepository
|
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileSubscriptionRepository
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileSubscriptionRepositoryImpl
|
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileSubscriptionRepositoryImpl
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
|
import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
|
||||||
@@ -29,6 +31,9 @@ import dagger.Module
|
|||||||
|
|
||||||
@Module
|
@Module
|
||||||
abstract class StatusBarPipelineModule {
|
abstract class StatusBarPipelineModule {
|
||||||
|
@Binds
|
||||||
|
abstract fun airplaneModeRepository(impl: AirplaneModeRepositoryImpl): AirplaneModeRepository
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun connectivityRepository(impl: ConnectivityRepositoryImpl): ConnectivityRepository
|
abstract fun connectivityRepository(impl: ConnectivityRepositoryImpl): ConnectivityRepository
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ object WifiViewBinder {
|
|||||||
val activityInView = view.requireViewById<ImageView>(R.id.wifi_in)
|
val activityInView = view.requireViewById<ImageView>(R.id.wifi_in)
|
||||||
val activityOutView = view.requireViewById<ImageView>(R.id.wifi_out)
|
val activityOutView = view.requireViewById<ImageView>(R.id.wifi_out)
|
||||||
val activityContainerView = view.requireViewById<View>(R.id.inout_container)
|
val activityContainerView = view.requireViewById<View>(R.id.inout_container)
|
||||||
|
val airplaneSpacer = view.requireViewById<View>(R.id.wifi_airplane_spacer)
|
||||||
|
|
||||||
view.isVisible = true
|
view.isVisible = true
|
||||||
iconView.isVisible = true
|
iconView.isVisible = true
|
||||||
@@ -142,6 +143,12 @@ object WifiViewBinder {
|
|||||||
activityContainerView.isVisible = visible
|
activityContainerView.isVisible = visible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.isAirplaneSpacerVisible.distinctUntilChanged().collect { visible ->
|
||||||
|
airplaneSpacer.isVisible = visible
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class HomeWifiViewModel(
|
|||||||
isActivityInViewVisible: Flow<Boolean>,
|
isActivityInViewVisible: Flow<Boolean>,
|
||||||
isActivityOutViewVisible: Flow<Boolean>,
|
isActivityOutViewVisible: Flow<Boolean>,
|
||||||
isActivityContainerVisible: Flow<Boolean>,
|
isActivityContainerVisible: Flow<Boolean>,
|
||||||
|
isAirplaneSpacerVisible: Flow<Boolean>,
|
||||||
) :
|
) :
|
||||||
LocationBasedWifiViewModel(
|
LocationBasedWifiViewModel(
|
||||||
statusBarPipelineFlags,
|
statusBarPipelineFlags,
|
||||||
@@ -40,4 +41,5 @@ class HomeWifiViewModel(
|
|||||||
isActivityInViewVisible,
|
isActivityInViewVisible,
|
||||||
isActivityOutViewVisible,
|
isActivityOutViewVisible,
|
||||||
isActivityContainerVisible,
|
isActivityContainerVisible,
|
||||||
|
isAirplaneSpacerVisible,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class KeyguardWifiViewModel(
|
|||||||
isActivityInViewVisible: Flow<Boolean>,
|
isActivityInViewVisible: Flow<Boolean>,
|
||||||
isActivityOutViewVisible: Flow<Boolean>,
|
isActivityOutViewVisible: Flow<Boolean>,
|
||||||
isActivityContainerVisible: Flow<Boolean>,
|
isActivityContainerVisible: Flow<Boolean>,
|
||||||
|
isAirplaneSpacerVisible: Flow<Boolean>,
|
||||||
) :
|
) :
|
||||||
LocationBasedWifiViewModel(
|
LocationBasedWifiViewModel(
|
||||||
statusBarPipelineFlags,
|
statusBarPipelineFlags,
|
||||||
@@ -37,4 +38,5 @@ class KeyguardWifiViewModel(
|
|||||||
isActivityInViewVisible,
|
isActivityInViewVisible,
|
||||||
isActivityOutViewVisible,
|
isActivityOutViewVisible,
|
||||||
isActivityContainerVisible,
|
isActivityContainerVisible,
|
||||||
|
isAirplaneSpacerVisible,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ abstract class LocationBasedWifiViewModel(
|
|||||||
|
|
||||||
/** True if the activity container view should be visible. */
|
/** True if the activity container view should be visible. */
|
||||||
val isActivityContainerVisible: Flow<Boolean>,
|
val isActivityContainerVisible: Flow<Boolean>,
|
||||||
|
|
||||||
|
/** True if the airplane spacer view should be visible. */
|
||||||
|
val isAirplaneSpacerVisible: Flow<Boolean>,
|
||||||
) {
|
) {
|
||||||
/** The color that should be used to tint the icon. */
|
/** The color that should be used to tint the icon. */
|
||||||
val tint: Flow<Int> =
|
val tint: Flow<Int> =
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class QsWifiViewModel(
|
|||||||
isActivityInViewVisible: Flow<Boolean>,
|
isActivityInViewVisible: Flow<Boolean>,
|
||||||
isActivityOutViewVisible: Flow<Boolean>,
|
isActivityOutViewVisible: Flow<Boolean>,
|
||||||
isActivityContainerVisible: Flow<Boolean>,
|
isActivityContainerVisible: Flow<Boolean>,
|
||||||
|
isAirplaneSpacerVisible: Flow<Boolean>,
|
||||||
) :
|
) :
|
||||||
LocationBasedWifiViewModel(
|
LocationBasedWifiViewModel(
|
||||||
statusBarPipelineFlags,
|
statusBarPipelineFlags,
|
||||||
@@ -37,4 +38,5 @@ class QsWifiViewModel(
|
|||||||
isActivityInViewVisible,
|
isActivityInViewVisible,
|
||||||
isActivityOutViewVisible,
|
isActivityOutViewVisible,
|
||||||
isActivityContainerVisible,
|
isActivityContainerVisible,
|
||||||
|
isAirplaneSpacerVisible,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
|
|||||||
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
|
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
|
||||||
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
|
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
|
||||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
|
||||||
@@ -66,6 +67,7 @@ import kotlinx.coroutines.flow.stateIn
|
|||||||
class WifiViewModel
|
class WifiViewModel
|
||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
|
airplaneModeViewModel: AirplaneModeViewModel,
|
||||||
connectivityConstants: ConnectivityConstants,
|
connectivityConstants: ConnectivityConstants,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
logger: ConnectivityPipelineLogger,
|
logger: ConnectivityPipelineLogger,
|
||||||
@@ -177,6 +179,12 @@ constructor(
|
|||||||
}
|
}
|
||||||
.stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false)
|
.stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false)
|
||||||
|
|
||||||
|
// TODO(b/238425913): It isn't ideal for the wifi icon to need to know about whether the
|
||||||
|
// airplane icon is visible. Instead, we should have a parent StatusBarSystemIconsViewModel
|
||||||
|
// that appropriately knows about both icons and sets the padding appropriately.
|
||||||
|
private val isAirplaneSpacerVisible: Flow<Boolean> =
|
||||||
|
airplaneModeViewModel.isAirplaneModeIconVisible
|
||||||
|
|
||||||
/** A view model for the status bar on the home screen. */
|
/** A view model for the status bar on the home screen. */
|
||||||
val home: HomeWifiViewModel =
|
val home: HomeWifiViewModel =
|
||||||
HomeWifiViewModel(
|
HomeWifiViewModel(
|
||||||
@@ -185,6 +193,7 @@ constructor(
|
|||||||
isActivityInViewVisible,
|
isActivityInViewVisible,
|
||||||
isActivityOutViewVisible,
|
isActivityOutViewVisible,
|
||||||
isActivityContainerVisible,
|
isActivityContainerVisible,
|
||||||
|
isAirplaneSpacerVisible,
|
||||||
)
|
)
|
||||||
|
|
||||||
/** A view model for the status bar on keyguard. */
|
/** A view model for the status bar on keyguard. */
|
||||||
@@ -195,6 +204,7 @@ constructor(
|
|||||||
isActivityInViewVisible,
|
isActivityInViewVisible,
|
||||||
isActivityOutViewVisible,
|
isActivityOutViewVisible,
|
||||||
isActivityContainerVisible,
|
isActivityContainerVisible,
|
||||||
|
isAirplaneSpacerVisible,
|
||||||
)
|
)
|
||||||
|
|
||||||
/** A view model for the status bar in quick settings. */
|
/** A view model for the status bar in quick settings. */
|
||||||
@@ -205,6 +215,7 @@ constructor(
|
|||||||
isActivityInViewVisible,
|
isActivityInViewVisible,
|
||||||
isActivityOutViewVisible,
|
isActivityOutViewVisible,
|
||||||
isActivityContainerVisible,
|
isActivityContainerVisible,
|
||||||
|
isAirplaneSpacerVisible,
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.airplane.data.repository
|
||||||
|
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.os.UserHandle
|
||||||
|
import android.provider.Settings.Global
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
|
import com.android.systemui.util.settings.FakeSettings
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.yield
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@SmallTest
|
||||||
|
class AirplaneModeRepositoryImplTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
private lateinit var underTest: AirplaneModeRepositoryImpl
|
||||||
|
|
||||||
|
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||||
|
private lateinit var bgHandler: Handler
|
||||||
|
private lateinit var scope: CoroutineScope
|
||||||
|
private lateinit var settings: FakeSettings
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
bgHandler = Handler(Looper.getMainLooper())
|
||||||
|
scope = CoroutineScope(IMMEDIATE)
|
||||||
|
settings = FakeSettings()
|
||||||
|
settings.userId = UserHandle.USER_ALL
|
||||||
|
|
||||||
|
underTest =
|
||||||
|
AirplaneModeRepositoryImpl(
|
||||||
|
bgHandler,
|
||||||
|
settings,
|
||||||
|
logger,
|
||||||
|
scope,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
scope.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAirplaneMode_initiallyGetsSettingsValue() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
settings.putInt(Global.AIRPLANE_MODE_ON, 1)
|
||||||
|
|
||||||
|
underTest =
|
||||||
|
AirplaneModeRepositoryImpl(
|
||||||
|
bgHandler,
|
||||||
|
settings,
|
||||||
|
logger,
|
||||||
|
scope,
|
||||||
|
)
|
||||||
|
|
||||||
|
val job = underTest.isAirplaneMode.launchIn(this)
|
||||||
|
|
||||||
|
assertThat(underTest.isAirplaneMode.value).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAirplaneMode_settingUpdated_valueUpdated() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
val job = underTest.isAirplaneMode.launchIn(this)
|
||||||
|
|
||||||
|
settings.putInt(Global.AIRPLANE_MODE_ON, 0)
|
||||||
|
yield()
|
||||||
|
assertThat(underTest.isAirplaneMode.value).isFalse()
|
||||||
|
|
||||||
|
settings.putInt(Global.AIRPLANE_MODE_ON, 1)
|
||||||
|
yield()
|
||||||
|
assertThat(underTest.isAirplaneMode.value).isTrue()
|
||||||
|
|
||||||
|
settings.putInt(Global.AIRPLANE_MODE_ON, 0)
|
||||||
|
yield()
|
||||||
|
assertThat(underTest.isAirplaneMode.value).isFalse()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val IMMEDIATE = Dispatchers.Main.immediate
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.airplane.data.repository
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
|
class FakeAirplaneModeRepository : AirplaneModeRepository {
|
||||||
|
private val _isAirplaneMode = MutableStateFlow(false)
|
||||||
|
override val isAirplaneMode: StateFlow<Boolean> = _isAirplaneMode
|
||||||
|
|
||||||
|
fun setIsAirplaneMode(isAirplaneMode: Boolean) {
|
||||||
|
_isAirplaneMode.value = isAirplaneMode
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.airplane.domain.interactor
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.yield
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
|
||||||
|
class AirplaneModeInteractorTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
private lateinit var underTest: AirplaneModeInteractor
|
||||||
|
|
||||||
|
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
|
||||||
|
private lateinit var connectivityRepository: FakeConnectivityRepository
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
airplaneModeRepository = FakeAirplaneModeRepository()
|
||||||
|
connectivityRepository = FakeConnectivityRepository()
|
||||||
|
underTest = AirplaneModeInteractor(airplaneModeRepository, connectivityRepository)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAirplaneMode_matchesRepo() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.isAirplaneMode.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
airplaneModeRepository.setIsAirplaneMode(true)
|
||||||
|
yield()
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
airplaneModeRepository.setIsAirplaneMode(false)
|
||||||
|
yield()
|
||||||
|
assertThat(latest).isFalse()
|
||||||
|
|
||||||
|
airplaneModeRepository.setIsAirplaneMode(true)
|
||||||
|
yield()
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isForceHidden_repoHasWifiHidden_outputsTrue() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.AIRPLANE))
|
||||||
|
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isForceHidden_repoDoesNotHaveWifiHidden_outputsFalse() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
connectivityRepository.setForceHiddenIcons(setOf())
|
||||||
|
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
assertThat(latest).isFalse()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val IMMEDIATE = Dispatchers.Main.immediate
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.airplane.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
|
||||||
|
class AirplaneModeViewModelTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
private lateinit var underTest: AirplaneModeViewModel
|
||||||
|
|
||||||
|
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||||
|
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
|
||||||
|
private lateinit var connectivityRepository: FakeConnectivityRepository
|
||||||
|
private lateinit var interactor: AirplaneModeInteractor
|
||||||
|
private lateinit var scope: CoroutineScope
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
airplaneModeRepository = FakeAirplaneModeRepository()
|
||||||
|
connectivityRepository = FakeConnectivityRepository()
|
||||||
|
interactor = AirplaneModeInteractor(airplaneModeRepository, connectivityRepository)
|
||||||
|
scope = CoroutineScope(IMMEDIATE)
|
||||||
|
|
||||||
|
underTest =
|
||||||
|
AirplaneModeViewModel(
|
||||||
|
interactor,
|
||||||
|
logger,
|
||||||
|
scope,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAirplaneModeIconVisible_notAirplaneMode_outputsFalse() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
connectivityRepository.setForceHiddenIcons(setOf())
|
||||||
|
airplaneModeRepository.setIsAirplaneMode(false)
|
||||||
|
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.isAirplaneModeIconVisible.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
assertThat(latest).isFalse()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAirplaneModeIconVisible_forceHidden_outputsFalse() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.AIRPLANE))
|
||||||
|
airplaneModeRepository.setIsAirplaneMode(true)
|
||||||
|
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.isAirplaneModeIconVisible.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
assertThat(latest).isFalse()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAirplaneModeIconVisible_isAirplaneModeAndNotForceHidden_outputsTrue() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
connectivityRepository.setForceHiddenIcons(setOf())
|
||||||
|
airplaneModeRepository.setIsAirplaneMode(true)
|
||||||
|
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.isAirplaneModeIconVisible.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val IMMEDIATE = Dispatchers.Main.immediate
|
||||||
@@ -30,6 +30,9 @@ import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
|
|||||||
import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
|
import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
|
||||||
import com.android.systemui.statusbar.phone.StatusBarLocation
|
import com.android.systemui.statusbar.phone.StatusBarLocation
|
||||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
|
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
|
||||||
@@ -63,11 +66,13 @@ class ModernStatusBarWifiViewTest : SysuiTestCase() {
|
|||||||
private lateinit var connectivityConstants: ConnectivityConstants
|
private lateinit var connectivityConstants: ConnectivityConstants
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var wifiConstants: WifiConstants
|
private lateinit var wifiConstants: WifiConstants
|
||||||
|
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
|
||||||
private lateinit var connectivityRepository: FakeConnectivityRepository
|
private lateinit var connectivityRepository: FakeConnectivityRepository
|
||||||
private lateinit var wifiRepository: FakeWifiRepository
|
private lateinit var wifiRepository: FakeWifiRepository
|
||||||
private lateinit var interactor: WifiInteractor
|
private lateinit var interactor: WifiInteractor
|
||||||
private lateinit var viewModel: WifiViewModel
|
private lateinit var viewModel: WifiViewModel
|
||||||
private lateinit var scope: CoroutineScope
|
private lateinit var scope: CoroutineScope
|
||||||
|
private lateinit var airplaneModeViewModel: AirplaneModeViewModel
|
||||||
|
|
||||||
@JvmField @Rule
|
@JvmField @Rule
|
||||||
val instantTaskExecutor = InstantTaskExecutorRule()
|
val instantTaskExecutor = InstantTaskExecutorRule()
|
||||||
@@ -77,12 +82,22 @@ class ModernStatusBarWifiViewTest : SysuiTestCase() {
|
|||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
testableLooper = TestableLooper.get(this)
|
testableLooper = TestableLooper.get(this)
|
||||||
|
|
||||||
|
airplaneModeRepository = FakeAirplaneModeRepository()
|
||||||
connectivityRepository = FakeConnectivityRepository()
|
connectivityRepository = FakeConnectivityRepository()
|
||||||
wifiRepository = FakeWifiRepository()
|
wifiRepository = FakeWifiRepository()
|
||||||
wifiRepository.setIsWifiEnabled(true)
|
wifiRepository.setIsWifiEnabled(true)
|
||||||
interactor = WifiInteractor(connectivityRepository, wifiRepository)
|
interactor = WifiInteractor(connectivityRepository, wifiRepository)
|
||||||
scope = CoroutineScope(Dispatchers.Unconfined)
|
scope = CoroutineScope(Dispatchers.Unconfined)
|
||||||
|
airplaneModeViewModel = AirplaneModeViewModel(
|
||||||
|
AirplaneModeInteractor(
|
||||||
|
airplaneModeRepository,
|
||||||
|
connectivityRepository,
|
||||||
|
),
|
||||||
|
logger,
|
||||||
|
scope,
|
||||||
|
)
|
||||||
viewModel = WifiViewModel(
|
viewModel = WifiViewModel(
|
||||||
|
airplaneModeViewModel,
|
||||||
connectivityConstants,
|
connectivityConstants,
|
||||||
context,
|
context,
|
||||||
logger,
|
logger,
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
|
|||||||
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
|
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
|
||||||
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
|
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
|
||||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
|
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
|
||||||
@@ -64,19 +67,31 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase
|
|||||||
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||||
@Mock private lateinit var connectivityConstants: ConnectivityConstants
|
@Mock private lateinit var connectivityConstants: ConnectivityConstants
|
||||||
@Mock private lateinit var wifiConstants: WifiConstants
|
@Mock private lateinit var wifiConstants: WifiConstants
|
||||||
|
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
|
||||||
private lateinit var connectivityRepository: FakeConnectivityRepository
|
private lateinit var connectivityRepository: FakeConnectivityRepository
|
||||||
private lateinit var wifiRepository: FakeWifiRepository
|
private lateinit var wifiRepository: FakeWifiRepository
|
||||||
private lateinit var interactor: WifiInteractor
|
private lateinit var interactor: WifiInteractor
|
||||||
|
private lateinit var airplaneModeViewModel: AirplaneModeViewModel
|
||||||
private lateinit var scope: CoroutineScope
|
private lateinit var scope: CoroutineScope
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
|
airplaneModeRepository = FakeAirplaneModeRepository()
|
||||||
connectivityRepository = FakeConnectivityRepository()
|
connectivityRepository = FakeConnectivityRepository()
|
||||||
wifiRepository = FakeWifiRepository()
|
wifiRepository = FakeWifiRepository()
|
||||||
wifiRepository.setIsWifiEnabled(true)
|
wifiRepository.setIsWifiEnabled(true)
|
||||||
interactor = WifiInteractor(connectivityRepository, wifiRepository)
|
interactor = WifiInteractor(connectivityRepository, wifiRepository)
|
||||||
scope = CoroutineScope(IMMEDIATE)
|
scope = CoroutineScope(IMMEDIATE)
|
||||||
|
airplaneModeViewModel =
|
||||||
|
AirplaneModeViewModel(
|
||||||
|
AirplaneModeInteractor(
|
||||||
|
airplaneModeRepository,
|
||||||
|
connectivityRepository,
|
||||||
|
),
|
||||||
|
logger,
|
||||||
|
scope,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -102,6 +117,7 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase
|
|||||||
.thenReturn(testCase.hasDataCapabilities)
|
.thenReturn(testCase.hasDataCapabilities)
|
||||||
underTest =
|
underTest =
|
||||||
WifiViewModel(
|
WifiViewModel(
|
||||||
|
airplaneModeViewModel,
|
||||||
connectivityConstants,
|
connectivityConstants,
|
||||||
context,
|
context,
|
||||||
logger,
|
logger,
|
||||||
|
|||||||
@@ -20,8 +20,12 @@ import androidx.test.filters.SmallTest
|
|||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.common.shared.model.Icon
|
import com.android.systemui.common.shared.model.Icon
|
||||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
|
||||||
|
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
|
||||||
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
|
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
|
||||||
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
|
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
|
||||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
|
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
|
||||||
@@ -55,19 +59,31 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||||
@Mock private lateinit var connectivityConstants: ConnectivityConstants
|
@Mock private lateinit var connectivityConstants: ConnectivityConstants
|
||||||
@Mock private lateinit var wifiConstants: WifiConstants
|
@Mock private lateinit var wifiConstants: WifiConstants
|
||||||
|
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
|
||||||
private lateinit var connectivityRepository: FakeConnectivityRepository
|
private lateinit var connectivityRepository: FakeConnectivityRepository
|
||||||
private lateinit var wifiRepository: FakeWifiRepository
|
private lateinit var wifiRepository: FakeWifiRepository
|
||||||
private lateinit var interactor: WifiInteractor
|
private lateinit var interactor: WifiInteractor
|
||||||
|
private lateinit var airplaneModeViewModel: AirplaneModeViewModel
|
||||||
private lateinit var scope: CoroutineScope
|
private lateinit var scope: CoroutineScope
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
|
airplaneModeRepository = FakeAirplaneModeRepository()
|
||||||
connectivityRepository = FakeConnectivityRepository()
|
connectivityRepository = FakeConnectivityRepository()
|
||||||
wifiRepository = FakeWifiRepository()
|
wifiRepository = FakeWifiRepository()
|
||||||
wifiRepository.setIsWifiEnabled(true)
|
wifiRepository.setIsWifiEnabled(true)
|
||||||
interactor = WifiInteractor(connectivityRepository, wifiRepository)
|
interactor = WifiInteractor(connectivityRepository, wifiRepository)
|
||||||
scope = CoroutineScope(IMMEDIATE)
|
scope = CoroutineScope(IMMEDIATE)
|
||||||
|
airplaneModeViewModel = AirplaneModeViewModel(
|
||||||
|
AirplaneModeInteractor(
|
||||||
|
airplaneModeRepository,
|
||||||
|
connectivityRepository,
|
||||||
|
),
|
||||||
|
logger,
|
||||||
|
scope,
|
||||||
|
)
|
||||||
|
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,11 +478,64 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
job.cancel()
|
job.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun airplaneSpacer_notAirplaneMode_outputsFalse() = runBlocking(IMMEDIATE) {
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest
|
||||||
|
.qs
|
||||||
|
.isAirplaneSpacerVisible
|
||||||
|
.onEach { latest = it }
|
||||||
|
.launchIn(this)
|
||||||
|
|
||||||
|
airplaneModeRepository.setIsAirplaneMode(false)
|
||||||
|
yield()
|
||||||
|
|
||||||
|
assertThat(latest).isFalse()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun airplaneSpacer_airplaneForceHidden_outputsFalse() = runBlocking(IMMEDIATE) {
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest
|
||||||
|
.qs
|
||||||
|
.isAirplaneSpacerVisible
|
||||||
|
.onEach { latest = it }
|
||||||
|
.launchIn(this)
|
||||||
|
|
||||||
|
airplaneModeRepository.setIsAirplaneMode(true)
|
||||||
|
connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.AIRPLANE))
|
||||||
|
yield()
|
||||||
|
|
||||||
|
assertThat(latest).isFalse()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun airplaneSpacer_airplaneIconVisible_outputsTrue() = runBlocking(IMMEDIATE) {
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest
|
||||||
|
.qs
|
||||||
|
.isAirplaneSpacerVisible
|
||||||
|
.onEach { latest = it }
|
||||||
|
.launchIn(this)
|
||||||
|
|
||||||
|
airplaneModeRepository.setIsAirplaneMode(true)
|
||||||
|
yield()
|
||||||
|
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
private fun createAndSetViewModel() {
|
private fun createAndSetViewModel() {
|
||||||
// [WifiViewModel] creates its flows as soon as it's instantiated, and some of those flow
|
// [WifiViewModel] creates its flows as soon as it's instantiated, and some of those flow
|
||||||
// creations rely on certain config values that we mock out in individual tests. This method
|
// creations rely on certain config values that we mock out in individual tests. This method
|
||||||
// allows tests to create the view model only after those configs are correctly set up.
|
// allows tests to create the view model only after those configs are correctly set up.
|
||||||
underTest = WifiViewModel(
|
underTest = WifiViewModel(
|
||||||
|
airplaneModeViewModel,
|
||||||
connectivityConstants,
|
connectivityConstants,
|
||||||
context,
|
context,
|
||||||
logger,
|
logger,
|
||||||
|
|||||||
Reference in New Issue
Block a user