Adds Retail mode repository
If the device is in retail mode, tiles are set to a different list and cannot be edited. Fixes: 277776030 Test: manual, device in demo mode Test: atest TileSpecSettingsRepositoryTest Test: atest RetailModeSettingsRepositoryTest Test: atest QSFooterViewControllerTest Change-Id: Ie3102bab7f658482ee4b128ec0689f19f69c1945
This commit is contained in:
committed by
Fabian Kozynski
parent
01b56bb057
commit
07b7d22777
@@ -66,6 +66,7 @@ import com.android.systemui.qs.FgsManagerControllerImpl;
|
||||
import com.android.systemui.qs.QSFragmentStartableModule;
|
||||
import com.android.systemui.qs.footer.dagger.FooterActionsModule;
|
||||
import com.android.systemui.recents.Recents;
|
||||
import com.android.systemui.retail.dagger.RetailModeModule;
|
||||
import com.android.systemui.screenrecord.ScreenRecordModule;
|
||||
import com.android.systemui.screenshot.dagger.ScreenshotModule;
|
||||
import com.android.systemui.security.data.repository.SecurityRepositoryModule;
|
||||
@@ -170,6 +171,7 @@ import javax.inject.Named;
|
||||
PrivacyModule.class,
|
||||
QRCodeScannerModule.class,
|
||||
QSFragmentStartableModule.class,
|
||||
RetailModeModule.class,
|
||||
ScreenshotModule.class,
|
||||
SensorModule.class,
|
||||
SecurityRepositoryModule.class,
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.plugins.ActivityStarter;
|
||||
import com.android.systemui.plugins.FalsingManager;
|
||||
import com.android.systemui.qs.dagger.QSScope;
|
||||
import com.android.systemui.retail.domain.interactor.RetailModeInteractor;
|
||||
import com.android.systemui.settings.UserTracker;
|
||||
import com.android.systemui.util.ViewController;
|
||||
|
||||
@@ -45,18 +46,22 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
|
||||
private final View mEditButton;
|
||||
private final FalsingManager mFalsingManager;
|
||||
private final ActivityStarter mActivityStarter;
|
||||
private final RetailModeInteractor mRetailModeInteractor;
|
||||
|
||||
@Inject
|
||||
QSFooterViewController(QSFooterView view,
|
||||
UserTracker userTracker,
|
||||
FalsingManager falsingManager,
|
||||
ActivityStarter activityStarter,
|
||||
QSPanelController qsPanelController) {
|
||||
QSPanelController qsPanelController,
|
||||
RetailModeInteractor retailModeInteractor
|
||||
) {
|
||||
super(view);
|
||||
mUserTracker = userTracker;
|
||||
mQsPanelController = qsPanelController;
|
||||
mFalsingManager = falsingManager;
|
||||
mActivityStarter = activityStarter;
|
||||
mRetailModeInteractor = retailModeInteractor;
|
||||
|
||||
mBuildText = mView.findViewById(R.id.build);
|
||||
mPageIndicator = mView.findViewById(R.id.footer_page_indicator);
|
||||
@@ -96,6 +101,8 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
|
||||
@Override
|
||||
public void setVisibility(int visibility) {
|
||||
mView.setVisibility(visibility);
|
||||
mEditButton
|
||||
.setVisibility(mRetailModeInteractor.isInRetailMode() ? View.GONE : View.VISIBLE);
|
||||
mEditButton.setClickable(visibility == View.VISIBLE);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.annotation.UserIdInt
|
||||
import android.content.res.Resources
|
||||
import android.database.ContentObserver
|
||||
import android.provider.Settings
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
@@ -27,12 +28,16 @@ import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.qs.QSHost
|
||||
import com.android.systemui.qs.pipeline.shared.TileSpec
|
||||
import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
|
||||
import com.android.systemui.retail.data.repository.RetailModeRepository
|
||||
import com.android.systemui.util.settings.SecureSettings
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@@ -84,6 +89,9 @@ interface TileSpecRepository {
|
||||
* [Settings.Secure.QS_TILES].
|
||||
*
|
||||
* All operations against [Settings] will be performed in a background thread.
|
||||
*
|
||||
* If the device is in retail mode, the tiles are fixed to the value of
|
||||
* [R.string.quick_settings_tiles_retail_mode].
|
||||
*/
|
||||
@SysUISingleton
|
||||
class TileSpecSettingsRepository
|
||||
@@ -92,9 +100,31 @@ constructor(
|
||||
private val secureSettings: SecureSettings,
|
||||
@Main private val resources: Resources,
|
||||
private val logger: QSPipelineLogger,
|
||||
private val retailModeRepository: RetailModeRepository,
|
||||
@Background private val backgroundDispatcher: CoroutineDispatcher,
|
||||
) : TileSpecRepository {
|
||||
|
||||
private val retailModeTiles by lazy {
|
||||
resources
|
||||
.getString(R.string.quick_settings_tiles_retail_mode)
|
||||
.split(DELIMITER)
|
||||
.map(TileSpec::create)
|
||||
.filter { it !is TileSpec.Invalid }
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun tilesSpecs(userId: Int): Flow<List<TileSpec>> {
|
||||
return retailModeRepository.retailMode.flatMapLatest { inRetailMode ->
|
||||
if (inRetailMode) {
|
||||
logger.logUsingRetailTiles()
|
||||
flowOf(retailModeTiles)
|
||||
} else {
|
||||
settingsTiles(userId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun settingsTiles(userId: Int): Flow<List<TileSpec>> {
|
||||
return conflatedCallbackFlow {
|
||||
val observer =
|
||||
object : ContentObserver(null) {
|
||||
@@ -157,6 +187,10 @@ constructor(
|
||||
}
|
||||
|
||||
private suspend fun storeTiles(@UserIdInt forUser: Int, tiles: List<TileSpec>) {
|
||||
if (retailModeRepository.inRetailMode) {
|
||||
// No storing tiles when in retail mode
|
||||
return
|
||||
}
|
||||
val toStore =
|
||||
tiles
|
||||
.filter { it !is TileSpec.Invalid }
|
||||
|
||||
@@ -120,6 +120,10 @@ constructor(
|
||||
)
|
||||
}
|
||||
|
||||
fun logUsingRetailTiles() {
|
||||
tileListLogBuffer.log(TILE_LIST_TAG, LogLevel.DEBUG, {}, { "Using retail tiles" })
|
||||
}
|
||||
|
||||
/** Reasons for destroying an existing tile. */
|
||||
enum class TileDestroyedReason(val readable: String) {
|
||||
TILE_REMOVED("Tile removed from current set"),
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.retail.dagger
|
||||
|
||||
import com.android.systemui.retail.data.repository.RetailModeRepository
|
||||
import com.android.systemui.retail.data.repository.RetailModeSettingsRepository
|
||||
import com.android.systemui.retail.domain.interactor.RetailModeInteractor
|
||||
import com.android.systemui.retail.domain.interactor.RetailModeInteractorImpl
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
|
||||
@Module
|
||||
abstract class RetailModeModule {
|
||||
|
||||
@Binds
|
||||
abstract fun bindsRetailModeRepository(impl: RetailModeSettingsRepository): RetailModeRepository
|
||||
|
||||
@Binds
|
||||
abstract fun bindsRetailModeInteractor(impl: RetailModeInteractorImpl): RetailModeInteractor
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.retail.data.repository
|
||||
|
||||
import android.database.ContentObserver
|
||||
import android.provider.Settings
|
||||
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.util.settings.GlobalSettings
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
/** Repository to track if the device is in Retail mode */
|
||||
interface RetailModeRepository {
|
||||
/** Flow of whether the device is currently in retail mode. */
|
||||
val retailMode: StateFlow<Boolean>
|
||||
|
||||
/** Last value of whether the device is in retail mode. */
|
||||
val inRetailMode: Boolean
|
||||
get() = retailMode.value
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks [Settings.Global.DEVICE_DEMO_MODE].
|
||||
*
|
||||
* @see UserManager.isDeviceInDemoMode
|
||||
*/
|
||||
@SysUISingleton
|
||||
class RetailModeSettingsRepository
|
||||
@Inject
|
||||
constructor(
|
||||
globalSettings: GlobalSettings,
|
||||
@Background backgroundDispatcher: CoroutineDispatcher,
|
||||
@Application scope: CoroutineScope,
|
||||
) : RetailModeRepository {
|
||||
override val retailMode =
|
||||
conflatedCallbackFlow {
|
||||
val observer =
|
||||
object : ContentObserver(null) {
|
||||
override fun onChange(selfChange: Boolean) {
|
||||
trySend(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
globalSettings.registerContentObserver(RETAIL_MODE_SETTING, observer)
|
||||
|
||||
awaitClose { globalSettings.unregisterContentObserver(observer) }
|
||||
}
|
||||
.onStart { emit(Unit) }
|
||||
.map { globalSettings.getInt(RETAIL_MODE_SETTING, 0) != 0 }
|
||||
.flowOn(backgroundDispatcher)
|
||||
.stateIn(scope, SharingStarted.Eagerly, false)
|
||||
|
||||
companion object {
|
||||
private const val RETAIL_MODE_SETTING = Settings.Global.DEVICE_DEMO_MODE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.retail.domain.interactor
|
||||
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.retail.data.repository.RetailModeRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
/** Interactor to determine if the device is currently in retail mode */
|
||||
interface RetailModeInteractor {
|
||||
/** Whether the device is currently in retail mode */
|
||||
val isInRetailMode: Boolean
|
||||
}
|
||||
|
||||
@SysUISingleton
|
||||
class RetailModeInteractorImpl
|
||||
@Inject
|
||||
constructor(
|
||||
private val repository: RetailModeRepository,
|
||||
) : RetailModeInteractor {
|
||||
override val isInRetailMode: Boolean
|
||||
get() = repository.inRetailMode
|
||||
}
|
||||
@@ -37,6 +37,8 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.plugins.ActivityStarter;
|
||||
import com.android.systemui.plugins.FalsingManager;
|
||||
import com.android.systemui.retail.data.repository.FakeRetailModeRepository;
|
||||
import com.android.systemui.retail.domain.interactor.RetailModeInteractorImpl;
|
||||
import com.android.systemui.settings.UserTracker;
|
||||
import com.android.systemui.utils.leaks.LeakCheckedTest;
|
||||
|
||||
@@ -67,6 +69,8 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
|
||||
@Mock
|
||||
private ActivityStarter mActivityStarter;
|
||||
|
||||
private FakeRetailModeRepository mRetailModeRepository;
|
||||
|
||||
private QSFooterViewController mController;
|
||||
private View mEditButton;
|
||||
|
||||
@@ -74,6 +78,9 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
|
||||
public void setup() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mRetailModeRepository = new FakeRetailModeRepository();
|
||||
mRetailModeRepository.setRetailMode(false);
|
||||
|
||||
mEditButton = new View(mContext);
|
||||
|
||||
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
|
||||
@@ -89,7 +96,8 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
|
||||
when(mView.findViewById(android.R.id.edit)).thenReturn(mEditButton);
|
||||
|
||||
mController = new QSFooterViewController(mView, mUserTracker, mFalsingManager,
|
||||
mActivityStarter, mQSPanelController);
|
||||
mActivityStarter, mQSPanelController,
|
||||
new RetailModeInteractorImpl(mRetailModeRepository));
|
||||
|
||||
mController.init();
|
||||
}
|
||||
@@ -132,4 +140,20 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
|
||||
captor.getValue().run();
|
||||
verify(mQSPanelController).showEdit(mEditButton);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditButton_notRetailMode_visible() {
|
||||
mRetailModeRepository.setRetailMode(false);
|
||||
|
||||
mController.setVisibility(View.VISIBLE);
|
||||
assertThat(mEditButton.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditButton_retailMode_notVisible() {
|
||||
mRetailModeRepository.setRetailMode(true);
|
||||
|
||||
mController.setVisibility(View.VISIBLE);
|
||||
assertThat(mEditButton.getVisibility()).isEqualTo(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.android.systemui.coroutines.collectLastValue
|
||||
import com.android.systemui.qs.QSHost
|
||||
import com.android.systemui.qs.pipeline.shared.TileSpec
|
||||
import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
|
||||
import com.android.systemui.retail.data.repository.FakeRetailModeRepository
|
||||
import com.android.systemui.util.settings.FakeSettings
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
@@ -44,6 +45,7 @@ import org.mockito.MockitoAnnotations
|
||||
class TileSpecSettingsRepositoryTest : SysuiTestCase() {
|
||||
|
||||
private lateinit var secureSettings: FakeSettings
|
||||
private lateinit var retailModeRepository: FakeRetailModeRepository
|
||||
|
||||
@Mock private lateinit var logger: QSPipelineLogger
|
||||
|
||||
@@ -57,9 +59,12 @@ class TileSpecSettingsRepositoryTest : SysuiTestCase() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
secureSettings = FakeSettings()
|
||||
retailModeRepository = FakeRetailModeRepository()
|
||||
retailModeRepository.setRetailMode(false)
|
||||
|
||||
with(context.orCreateTestableResources) {
|
||||
addOverride(R.string.quick_settings_tiles_default, DEFAULT_TILES)
|
||||
addOverride(R.string.quick_settings_tiles_retail_mode, RETAIL_TILES)
|
||||
}
|
||||
|
||||
underTest =
|
||||
@@ -67,6 +72,7 @@ class TileSpecSettingsRepositoryTest : SysuiTestCase() {
|
||||
secureSettings,
|
||||
context.resources,
|
||||
logger,
|
||||
retailModeRepository,
|
||||
testDispatcher,
|
||||
)
|
||||
}
|
||||
@@ -346,6 +352,26 @@ class TileSpecSettingsRepositoryTest : SysuiTestCase() {
|
||||
assertThat(tiles).isEqualTo("b".toTileSpecs())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun retailMode_usesRetailTiles() =
|
||||
testScope.runTest {
|
||||
retailModeRepository.setRetailMode(true)
|
||||
|
||||
val tiles by collectLastValue(underTest.tilesSpecs(0))
|
||||
|
||||
assertThat(tiles).isEqualTo(RETAIL_TILES.toTileSpecs())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun retailMode_cannotModifyTiles() =
|
||||
testScope.runTest {
|
||||
retailModeRepository.setRetailMode(true)
|
||||
|
||||
underTest.setTiles(0, DEFAULT_TILES.toTileSpecs())
|
||||
|
||||
assertThat(loadTilesForUser(0)).isNull()
|
||||
}
|
||||
|
||||
private fun getDefaultTileSpecs(): List<TileSpec> {
|
||||
return QSHost.getDefaultSpecs(context.resources).map(TileSpec::create)
|
||||
}
|
||||
@@ -360,6 +386,7 @@ class TileSpecSettingsRepositoryTest : SysuiTestCase() {
|
||||
|
||||
companion object {
|
||||
private const val DEFAULT_TILES = "a,b,c"
|
||||
private const val RETAIL_TILES = "d"
|
||||
private const val SETTING = Settings.Secure.QS_TILES
|
||||
|
||||
private fun String.toTileSpecs(): List<TileSpec> {
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.retail.data.repository
|
||||
|
||||
import android.provider.Settings
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.coroutines.collectLastValue
|
||||
import com.android.systemui.util.settings.FakeSettings
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
class RetailModeSettingsRepositoryTest : SysuiTestCase() {
|
||||
|
||||
private val globalSettings = FakeSettings()
|
||||
|
||||
private val testDispatcher = StandardTestDispatcher()
|
||||
private val testScope = TestScope(testDispatcher)
|
||||
|
||||
private val underTest =
|
||||
RetailModeSettingsRepository(
|
||||
globalSettings,
|
||||
backgroundDispatcher = testDispatcher,
|
||||
scope = testScope.backgroundScope,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun retailMode_defaultFalse() =
|
||||
testScope.runTest {
|
||||
val value by collectLastValue(underTest.retailMode)
|
||||
|
||||
assertThat(value).isFalse()
|
||||
assertThat(underTest.inRetailMode).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun retailMode_false() =
|
||||
testScope.runTest {
|
||||
val value by collectLastValue(underTest.retailMode)
|
||||
|
||||
globalSettings.putInt(SETTING, 0)
|
||||
|
||||
assertThat(value).isFalse()
|
||||
assertThat(underTest.inRetailMode).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun retailMode_true() =
|
||||
testScope.runTest {
|
||||
val value by collectLastValue(underTest.retailMode)
|
||||
|
||||
globalSettings.putInt(SETTING, 1)
|
||||
|
||||
assertThat(value).isTrue()
|
||||
assertThat(underTest.inRetailMode).isTrue()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val SETTING = Settings.Global.DEVICE_DEMO_MODE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.retail.domain.interactor
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.retail.data.repository.FakeRetailModeRepository
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
class RetailModeInteractorImplTest : SysuiTestCase() {
|
||||
|
||||
private val retailModeRepository = FakeRetailModeRepository()
|
||||
|
||||
private val underTest = RetailModeInteractorImpl(retailModeRepository)
|
||||
|
||||
@Test
|
||||
fun retailMode_false() {
|
||||
retailModeRepository.setRetailMode(false)
|
||||
|
||||
assertThat(underTest.isInRetailMode).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun retailMode_true() {
|
||||
retailModeRepository.setRetailMode(true)
|
||||
|
||||
assertThat(underTest.isInRetailMode).isTrue()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.retail.data.repository
|
||||
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
|
||||
class FakeRetailModeRepository : RetailModeRepository {
|
||||
|
||||
private val _retailMode = MutableStateFlow(false)
|
||||
override val retailMode: StateFlow<Boolean> = _retailMode.asStateFlow()
|
||||
|
||||
private var _retailModeValue = false
|
||||
override val inRetailMode: Boolean
|
||||
get() = _retailModeValue
|
||||
|
||||
fun setRetailMode(value: Boolean) {
|
||||
_retailMode.value = value
|
||||
_retailModeValue = value
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user