1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.statusbar.disableflags.data.repository 16 17 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow 18 import com.android.systemui.dagger.SysUISingleton 19 import com.android.systemui.dagger.qualifiers.Application 20 import com.android.systemui.dagger.qualifiers.DisplayId 21 import com.android.systemui.log.LogBuffer 22 import com.android.systemui.log.dagger.DisableFlagsRepositoryLog 23 import com.android.systemui.statusbar.CommandQueue 24 import com.android.systemui.statusbar.disableflags.DisableFlagsLogger 25 import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel 26 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler 27 import javax.inject.Inject 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.distinctUntilChanged 33 import kotlinx.coroutines.flow.onEach 34 import kotlinx.coroutines.flow.stateIn 35 36 /** Repository for the disable flags received from external systems. See [IStatusBar.disable]. */ 37 interface DisableFlagsRepository { 38 /** A model of the disable flags last received from [IStatusBar]. */ 39 val disableFlags: StateFlow<DisableFlagsModel> 40 } 41 42 @SysUISingleton 43 class DisableFlagsRepositoryImpl 44 @Inject 45 constructor( 46 commandQueue: CommandQueue, 47 @DisplayId private val thisDisplayId: Int, 48 @Application scope: CoroutineScope, 49 remoteInputQuickSettingsDisabler: RemoteInputQuickSettingsDisabler, 50 @DisableFlagsRepositoryLog private val logBuffer: LogBuffer, 51 private val disableFlagsLogger: DisableFlagsLogger, 52 ) : DisableFlagsRepository { 53 override val disableFlags: StateFlow<DisableFlagsModel> = <lambda>null54 conflatedCallbackFlow { 55 val callback = 56 object : CommandQueue.Callbacks { 57 override fun disable( 58 displayId: Int, 59 state1: Int, 60 state2: Int, 61 animate: Boolean, 62 ) { 63 if (displayId != thisDisplayId) { 64 return 65 } 66 trySend( 67 DisableFlagsModel( 68 state1, 69 // Ideally, [RemoteInputQuickSettingsDisabler] should instead 70 // expose a flow that gets `combine`d with this [disableFlags] 71 // flow in a [DisableFlagsInteractor] or 72 // [QuickSettingsInteractor]-type class. However, that's out of 73 // scope for the CentralSurfaces removal project. 74 remoteInputQuickSettingsDisabler.adjustDisableFlags(state2), 75 ) 76 ) 77 } 78 } 79 commandQueue.addCallback(callback) 80 awaitClose { commandQueue.removeCallback(callback) } 81 } 82 .distinctUntilChanged() <lambda>null83 .onEach { it.logChange(logBuffer, disableFlagsLogger) } 84 // Use Eagerly because we always need to know about disable flags 85 .stateIn(scope, SharingStarted.Eagerly, DisableFlagsModel()) 86 } 87