1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.retail.data.repository 18 19 import android.database.ContentObserver 20 import android.provider.Settings 21 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow 22 import com.android.systemui.dagger.SysUISingleton 23 import com.android.systemui.dagger.qualifiers.Application 24 import com.android.systemui.dagger.qualifiers.Background 25 import com.android.systemui.util.settings.GlobalSettings 26 import javax.inject.Inject 27 import kotlinx.coroutines.CoroutineDispatcher 28 import kotlinx.coroutines.CoroutineScope 29 import kotlinx.coroutines.channels.awaitClose 30 import kotlinx.coroutines.flow.SharingStarted 31 import kotlinx.coroutines.flow.StateFlow 32 import kotlinx.coroutines.flow.flowOn 33 import kotlinx.coroutines.flow.map 34 import kotlinx.coroutines.flow.onStart 35 import kotlinx.coroutines.flow.stateIn 36 37 /** Repository to track if the device is in Retail mode */ 38 interface RetailModeRepository { 39 /** Flow of whether the device is currently in retail mode. */ 40 val retailMode: StateFlow<Boolean> 41 42 /** Last value of whether the device is in retail mode. */ 43 val inRetailMode: Boolean 44 get() = retailMode.value 45 } 46 47 /** 48 * Tracks [Settings.Global.DEVICE_DEMO_MODE]. 49 * 50 * @see UserManager.isDeviceInDemoMode 51 */ 52 @SysUISingleton 53 class RetailModeSettingsRepository 54 @Inject 55 constructor( 56 globalSettings: GlobalSettings, 57 @Background backgroundDispatcher: CoroutineDispatcher, 58 @Application scope: CoroutineScope, 59 ) : RetailModeRepository { 60 override val retailMode = <lambda>null61 conflatedCallbackFlow { 62 val observer = 63 object : ContentObserver(null) { 64 override fun onChange(selfChange: Boolean) { 65 trySend(Unit) 66 } 67 } 68 69 globalSettings.registerContentObserverSync(RETAIL_MODE_SETTING, observer) 70 71 awaitClose { globalSettings.unregisterContentObserverSync(observer) } 72 } <lambda>null73 .onStart { emit(Unit) } <lambda>null74 .map { globalSettings.getInt(RETAIL_MODE_SETTING, 0) != 0 } 75 .flowOn(backgroundDispatcher) 76 .stateIn(scope, SharingStarted.Eagerly, false) 77 78 companion object { 79 private const val RETAIL_MODE_SETTING = Settings.Global.DEVICE_DEMO_MODE 80 } 81 } 82