[Sb refactor] Wifi demo mode
Test: WifiRepositorySwitcherTest Bug: 238425913 Change-Id: Iea3d94f6543cd599f667b297edf9d5019e841067
This commit is contained in:
@@ -1302,7 +1302,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
}
|
||||
}
|
||||
String wifi = args.getString("wifi");
|
||||
if (wifi != null) {
|
||||
if (wifi != null && !mStatusBarPipelineFlags.runNewWifiIconBackend()) {
|
||||
boolean show = wifi.equals("show");
|
||||
String level = args.getString("level");
|
||||
if (level != null) {
|
||||
|
||||
@@ -42,6 +42,8 @@ import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconStat
|
||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
|
||||
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
|
||||
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
|
||||
import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView;
|
||||
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -56,6 +58,7 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
private final int mIconSize;
|
||||
|
||||
private StatusBarWifiView mWifiView;
|
||||
private ModernStatusBarWifiView mModernWifiView;
|
||||
private boolean mDemoMode;
|
||||
private int mColor;
|
||||
|
||||
@@ -236,14 +239,14 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
|
||||
public void addDemoWifiView(WifiIconState state) {
|
||||
Log.d(TAG, "addDemoWifiView: ");
|
||||
// TODO(b/238425913): Migrate this view to {@code ModernStatusBarWifiView}.
|
||||
StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, state.slot);
|
||||
|
||||
int viewIndex = getChildCount();
|
||||
// If we have mobile views, put wifi before them
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child instanceof StatusBarMobileView) {
|
||||
if (child instanceof StatusBarMobileView
|
||||
|| child instanceof ModernStatusBarMobileView) {
|
||||
viewIndex = i;
|
||||
break;
|
||||
}
|
||||
@@ -298,6 +301,30 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
addView(view, getChildCount(), createLayoutParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link ModernStatusBarWifiView}
|
||||
*/
|
||||
public void addModernWifiView(LocationBasedWifiViewModel viewModel) {
|
||||
Log.d(TAG, "addModernDemoWifiView: ");
|
||||
ModernStatusBarWifiView view = ModernStatusBarWifiView
|
||||
.constructAndBind(mContext, "wifi", viewModel);
|
||||
|
||||
int viewIndex = getChildCount();
|
||||
// If we have mobile views, put wifi before them
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child instanceof StatusBarMobileView
|
||||
|| child instanceof ModernStatusBarMobileView) {
|
||||
viewIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mModernWifiView = view;
|
||||
mModernWifiView.setStaticDrawableColor(mColor);
|
||||
addView(view, viewIndex, createLayoutParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply an update to a mobile icon view for the given {@link MobileIconState}. For
|
||||
* compatibility with {@link MobileContextProvider}, we have to recreate the view every time we
|
||||
@@ -320,8 +347,14 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
|
||||
public void onRemoveIcon(StatusIconDisplayable view) {
|
||||
if (view.getSlot().equals("wifi")) {
|
||||
removeView(mWifiView);
|
||||
mWifiView = null;
|
||||
if (view instanceof StatusBarWifiView) {
|
||||
removeView(mWifiView);
|
||||
mWifiView = null;
|
||||
} else if (view instanceof ModernStatusBarWifiView) {
|
||||
Log.d(TAG, "onRemoveIcon: removing modern wifi view");
|
||||
removeView(mModernWifiView);
|
||||
mModernWifiView = null;
|
||||
}
|
||||
} else if (view instanceof StatusBarMobileView) {
|
||||
StatusBarMobileView mobileView = matchingMobileView(view);
|
||||
if (mobileView != null) {
|
||||
@@ -374,8 +407,14 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
if (mWifiView != null) {
|
||||
mWifiView.onDarkChanged(areas, darkIntensity, tint);
|
||||
}
|
||||
if (mModernWifiView != null) {
|
||||
mModernWifiView.onDarkChanged(areas, darkIntensity, tint);
|
||||
}
|
||||
for (StatusBarMobileView view : mMobileViews) {
|
||||
view.onDarkChanged(areas, darkIntensity, tint);
|
||||
}
|
||||
for (ModernStatusBarMobileView view : mModernMobileViews) {
|
||||
view.onDarkChanged(areas, darkIntensity, tint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,6 +497,11 @@ public interface StatusBarIconController {
|
||||
|
||||
ModernStatusBarWifiView view = onCreateModernStatusBarWifiView(slot);
|
||||
mGroup.addView(view, index, onCreateLayoutParams());
|
||||
|
||||
if (mIsInDemoMode) {
|
||||
mDemoStatusIcons.addModernWifiView(mWifiViewModel);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -688,6 +693,9 @@ public interface StatusBarIconController {
|
||||
mIsInDemoMode = true;
|
||||
if (mDemoStatusIcons == null) {
|
||||
mDemoStatusIcons = createDemoStatusIcons();
|
||||
if (mStatusBarPipelineFlags.useNewWifiIcon()) {
|
||||
mDemoStatusIcons.addModernWifiView(mWifiViewModel);
|
||||
}
|
||||
}
|
||||
mDemoStatusIcons.onDemoModeStarted();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxyIm
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryImpl
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositorySwitcher
|
||||
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
|
||||
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
|
||||
import dagger.Binds
|
||||
@@ -56,7 +56,7 @@ abstract class StatusBarPipelineModule {
|
||||
@Binds
|
||||
abstract fun connectivityRepository(impl: ConnectivityRepositoryImpl): ConnectivityRepository
|
||||
|
||||
@Binds abstract fun wifiRepository(impl: WifiRepositoryImpl): WifiRepository
|
||||
@Binds abstract fun wifiRepository(impl: WifiRepositorySwitcher): WifiRepository
|
||||
|
||||
@Binds
|
||||
abstract fun wifiInteractor(impl: WifiInteractorImpl): WifiInteractor
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.wifi.data.repository
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.demomode.DemoMode
|
||||
import com.android.systemui.demomode.DemoModeController
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository
|
||||
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.flatMapLatest
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
/**
|
||||
* Provides the [WifiRepository] interface either through the [DemoWifiRepository] implementation,
|
||||
* or the [WifiRepositoryImpl]'s prod implementation, based on the current demo mode value. In this
|
||||
* way, downstream clients can all consist of real implementations and not care about which
|
||||
* repository is responsible for the data. Graphically:
|
||||
*
|
||||
* ```
|
||||
* RealRepository
|
||||
* │
|
||||
* ├──►RepositorySwitcher──►RealInteractor──►RealViewModel
|
||||
* │
|
||||
* DemoRepository
|
||||
* ```
|
||||
*
|
||||
* When demo mode turns on, every flow will [flatMapLatest] to the current provider's version of
|
||||
* that flow.
|
||||
*/
|
||||
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class WifiRepositorySwitcher
|
||||
@Inject
|
||||
constructor(
|
||||
private val realImpl: WifiRepositoryImpl,
|
||||
private val demoImpl: DemoWifiRepository,
|
||||
private val demoModeController: DemoModeController,
|
||||
@Application scope: CoroutineScope,
|
||||
) : WifiRepository {
|
||||
private val isDemoMode =
|
||||
conflatedCallbackFlow {
|
||||
val callback =
|
||||
object : DemoMode {
|
||||
override fun dispatchDemoCommand(command: String?, args: Bundle?) {
|
||||
// Don't care
|
||||
}
|
||||
|
||||
override fun onDemoModeStarted() {
|
||||
demoImpl.startProcessingCommands()
|
||||
trySend(true)
|
||||
}
|
||||
|
||||
override fun onDemoModeFinished() {
|
||||
demoImpl.stopProcessingCommands()
|
||||
trySend(false)
|
||||
}
|
||||
}
|
||||
|
||||
demoModeController.addCallback(callback)
|
||||
awaitClose { demoModeController.removeCallback(callback) }
|
||||
}
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), demoModeController.isInDemoMode)
|
||||
|
||||
@VisibleForTesting
|
||||
val activeRepo =
|
||||
isDemoMode
|
||||
.mapLatest { isDemoMode ->
|
||||
if (isDemoMode) {
|
||||
demoImpl
|
||||
} else {
|
||||
realImpl
|
||||
}
|
||||
}
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), realImpl)
|
||||
|
||||
override val isWifiEnabled: StateFlow<Boolean> =
|
||||
activeRepo
|
||||
.flatMapLatest { it.isWifiEnabled }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), realImpl.isWifiEnabled.value)
|
||||
|
||||
override val isWifiDefault: StateFlow<Boolean> =
|
||||
activeRepo
|
||||
.flatMapLatest { it.isWifiDefault }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), realImpl.isWifiDefault.value)
|
||||
|
||||
override val wifiNetwork: StateFlow<WifiNetworkModel> =
|
||||
activeRepo
|
||||
.flatMapLatest { it.wifiNetwork }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), realImpl.wifiNetwork.value)
|
||||
|
||||
override val wifiActivity: StateFlow<DataActivityModel> =
|
||||
activeRepo
|
||||
.flatMapLatest { it.wifiActivity }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), realImpl.wifiActivity.value)
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.wifi.data.repository.demo
|
||||
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.Bundle
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.demomode.DemoMode.COMMAND_NETWORK
|
||||
import com.android.systemui.demomode.DemoModeController
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
|
||||
/** Data source to map between demo mode commands and inputs into [DemoWifiRepository]'s flows */
|
||||
@SysUISingleton
|
||||
class DemoModeWifiDataSource
|
||||
@Inject
|
||||
constructor(
|
||||
demoModeController: DemoModeController,
|
||||
@Application scope: CoroutineScope,
|
||||
) {
|
||||
private val demoCommandStream = demoModeController.demoFlowForCommand(COMMAND_NETWORK)
|
||||
private val _wifiCommands = demoCommandStream.map { args -> args.toWifiEvent() }
|
||||
val wifiEvents = _wifiCommands.shareIn(scope, SharingStarted.WhileSubscribed())
|
||||
|
||||
private fun Bundle.toWifiEvent(): FakeWifiEventModel? {
|
||||
val wifi = getString("wifi") ?: return null
|
||||
return if (wifi == "show") {
|
||||
activeWifiEvent()
|
||||
} else {
|
||||
FakeWifiEventModel.WifiDisabled
|
||||
}
|
||||
}
|
||||
|
||||
private fun Bundle.activeWifiEvent(): FakeWifiEventModel.Wifi {
|
||||
val level = getString("level")?.toInt()
|
||||
val activity = getString("activity")?.toActivity()
|
||||
val ssid = getString("ssid")
|
||||
val validated = getString("fully").toBoolean()
|
||||
|
||||
return FakeWifiEventModel.Wifi(
|
||||
level = level,
|
||||
activity = activity,
|
||||
ssid = ssid,
|
||||
validated = validated,
|
||||
)
|
||||
}
|
||||
|
||||
private fun String.toActivity(): Int =
|
||||
when (this) {
|
||||
"inout" -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT
|
||||
"in" -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN
|
||||
"out" -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT
|
||||
else -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.wifi.data.repository.demo
|
||||
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.model.toWifiDataActivityModel
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/** Demo-able wifi repository to support SystemUI demo mode commands. */
|
||||
class DemoWifiRepository
|
||||
@Inject
|
||||
constructor(
|
||||
private val dataSource: DemoModeWifiDataSource,
|
||||
@Application private val scope: CoroutineScope,
|
||||
) : WifiRepository {
|
||||
private var demoCommandJob: Job? = null
|
||||
|
||||
private val _isWifiEnabled = MutableStateFlow(false)
|
||||
override val isWifiEnabled: StateFlow<Boolean> = _isWifiEnabled
|
||||
|
||||
private val _isWifiDefault = MutableStateFlow(false)
|
||||
override val isWifiDefault: StateFlow<Boolean> = _isWifiDefault
|
||||
|
||||
private val _wifiNetwork = MutableStateFlow<WifiNetworkModel>(WifiNetworkModel.Inactive)
|
||||
override val wifiNetwork: StateFlow<WifiNetworkModel> = _wifiNetwork
|
||||
|
||||
private val _wifiActivity =
|
||||
MutableStateFlow(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
|
||||
override val wifiActivity: StateFlow<DataActivityModel> = _wifiActivity
|
||||
|
||||
fun startProcessingCommands() {
|
||||
demoCommandJob =
|
||||
scope.launch {
|
||||
dataSource.wifiEvents.filterNotNull().collect { event -> processEvent(event) }
|
||||
}
|
||||
}
|
||||
|
||||
fun stopProcessingCommands() {
|
||||
demoCommandJob?.cancel()
|
||||
}
|
||||
|
||||
private fun processEvent(event: FakeWifiEventModel) =
|
||||
when (event) {
|
||||
is FakeWifiEventModel.Wifi -> processEnabledWifiState(event)
|
||||
is FakeWifiEventModel.WifiDisabled -> processDisabledWifiState()
|
||||
}
|
||||
|
||||
private fun processDisabledWifiState() {
|
||||
_isWifiEnabled.value = false
|
||||
_isWifiDefault.value = false
|
||||
_wifiActivity.value = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
|
||||
_wifiNetwork.value = WifiNetworkModel.Inactive
|
||||
}
|
||||
|
||||
private fun processEnabledWifiState(event: FakeWifiEventModel.Wifi) {
|
||||
_isWifiEnabled.value = true
|
||||
_isWifiDefault.value = true
|
||||
_wifiActivity.value =
|
||||
event.activity?.toWifiDataActivityModel()
|
||||
?: DataActivityModel(hasActivityIn = false, hasActivityOut = false)
|
||||
_wifiNetwork.value = event.toWifiNetworkModel()
|
||||
}
|
||||
|
||||
private fun FakeWifiEventModel.Wifi.toWifiNetworkModel(): WifiNetworkModel =
|
||||
WifiNetworkModel.Active(
|
||||
networkId = DEMO_NET_ID,
|
||||
isValidated = validated ?: true,
|
||||
level = level,
|
||||
ssid = ssid,
|
||||
|
||||
// These fields below aren't supported in demo mode, since they aren't needed to satisfy
|
||||
// the interface.
|
||||
isPasspointAccessPoint = false,
|
||||
isOnlineSignUpForPasspointAccessPoint = false,
|
||||
passpointProviderFriendlyName = null,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val DEMO_NET_ID = 1234
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.wifi.data.repository.demo.model
|
||||
|
||||
/**
|
||||
* Model for demo wifi commands, ported from [NetworkControllerImpl]
|
||||
*
|
||||
* Nullable fields represent optional command line arguments
|
||||
*/
|
||||
sealed interface FakeWifiEventModel {
|
||||
data class Wifi(
|
||||
val level: Int?,
|
||||
val activity: Int?,
|
||||
val ssid: String?,
|
||||
val validated: Boolean?,
|
||||
) : FakeWifiEventModel
|
||||
|
||||
object WifiDisabled : FakeWifiEventModel
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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.wifi.data.repository
|
||||
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.wifi.WifiManager
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.demomode.DemoMode
|
||||
import com.android.systemui.demomode.DemoModeController
|
||||
import com.android.systemui.log.table.TableLogBuffer
|
||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.mockito.kotlinArgumentCaptor
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@SmallTest
|
||||
class WifiRepositorySwitcherTest : SysuiTestCase() {
|
||||
private lateinit var underTest: WifiRepositorySwitcher
|
||||
private lateinit var realImpl: WifiRepositoryImpl
|
||||
private lateinit var demoImpl: DemoWifiRepository
|
||||
|
||||
@Mock private lateinit var demoModeController: DemoModeController
|
||||
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||
@Mock private lateinit var tableLogger: TableLogBuffer
|
||||
@Mock private lateinit var connectivityManager: ConnectivityManager
|
||||
@Mock private lateinit var wifiManager: WifiManager
|
||||
@Mock private lateinit var demoModeWifiDataSource: DemoModeWifiDataSource
|
||||
private val demoModelFlow = MutableStateFlow<FakeWifiEventModel?>(null)
|
||||
|
||||
private val mainExecutor = FakeExecutor(FakeSystemClock())
|
||||
|
||||
private val testDispatcher = UnconfinedTestDispatcher()
|
||||
private val testScope = TestScope(testDispatcher)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
// Never start in demo mode
|
||||
whenever(demoModeController.isInDemoMode).thenReturn(false)
|
||||
|
||||
realImpl =
|
||||
WifiRepositoryImpl(
|
||||
fakeBroadcastDispatcher,
|
||||
connectivityManager,
|
||||
logger,
|
||||
tableLogger,
|
||||
mainExecutor,
|
||||
testScope.backgroundScope,
|
||||
wifiManager,
|
||||
)
|
||||
|
||||
whenever(demoModeWifiDataSource.wifiEvents).thenReturn(demoModelFlow)
|
||||
|
||||
demoImpl =
|
||||
DemoWifiRepository(
|
||||
demoModeWifiDataSource,
|
||||
testScope.backgroundScope,
|
||||
)
|
||||
|
||||
underTest =
|
||||
WifiRepositorySwitcher(
|
||||
realImpl,
|
||||
demoImpl,
|
||||
demoModeController,
|
||||
testScope.backgroundScope,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `switcher active repo - updates when demo mode changes`() =
|
||||
testScope.runTest {
|
||||
assertThat(underTest.activeRepo.value).isSameInstanceAs(realImpl)
|
||||
|
||||
var latest: WifiRepository? = null
|
||||
val job = underTest.activeRepo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
startDemoMode()
|
||||
|
||||
assertThat(latest).isSameInstanceAs(demoImpl)
|
||||
|
||||
finishDemoMode()
|
||||
|
||||
assertThat(latest).isSameInstanceAs(realImpl)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
private fun startDemoMode() {
|
||||
whenever(demoModeController.isInDemoMode).thenReturn(true)
|
||||
getDemoModeCallback().onDemoModeStarted()
|
||||
}
|
||||
|
||||
private fun finishDemoMode() {
|
||||
whenever(demoModeController.isInDemoMode).thenReturn(false)
|
||||
getDemoModeCallback().onDemoModeFinished()
|
||||
}
|
||||
|
||||
private fun getDemoModeCallback(): DemoMode {
|
||||
val captor = kotlinArgumentCaptor<DemoMode>()
|
||||
Mockito.verify(demoModeController).addCallback(captor.capture())
|
||||
return captor.value
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user