• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.statusbar.pipeline.airplane.data.repository
18 
19 import android.net.ConnectivityManager
20 import android.os.Handler
21 import android.provider.Settings.Global
22 import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
23 import com.android.systemui.dagger.SysUISingleton
24 import com.android.systemui.dagger.qualifiers.Background
25 import com.android.systemui.log.table.TableLogBuffer
26 import com.android.systemui.log.table.logDiffsForTable
27 import com.android.systemui.qs.SettingObserver
28 import com.android.systemui.statusbar.pipeline.dagger.AirplaneTableLog
29 import com.android.systemui.util.settings.GlobalSettings
30 import javax.inject.Inject
31 import kotlin.coroutines.CoroutineContext
32 import kotlinx.coroutines.CoroutineScope
33 import kotlinx.coroutines.channels.awaitClose
34 import kotlinx.coroutines.flow.SharingStarted
35 import kotlinx.coroutines.flow.StateFlow
36 import kotlinx.coroutines.flow.distinctUntilChanged
37 import kotlinx.coroutines.flow.stateIn
38 import kotlinx.coroutines.withContext
39 
40 /**
41  * Provides data related to airplane mode.
42  *
43  * IMPORTANT: This is currently *not* used to render any airplane mode information anywhere. It is
44  * only used to help [com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel]
45  * determine what parts of the wifi icon view should be shown.
46  *
47  * TODO(b/238425913): Consider migrating the status bar airplane mode icon to use this repo.
48  */
49 interface AirplaneModeRepository {
50     /** Observable for whether the device is currently in airplane mode. */
51     val isAirplaneMode: StateFlow<Boolean>
52 
53     /** Sets airplane mode state. */
setIsAirplaneModenull54     suspend fun setIsAirplaneMode(isEnabled: Boolean)
55 }
56 
57 @SysUISingleton
58 @Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
59 class AirplaneModeRepositoryImpl
60 @Inject
61 constructor(
62     private val connectivityManager: ConnectivityManager,
63     @Background private val bgHandler: Handler?,
64     @Background private val backgroundContext: CoroutineContext,
65     private val globalSettings: GlobalSettings,
66     @AirplaneTableLog logger: TableLogBuffer,
67     @Background scope: CoroutineScope,
68 ) : AirplaneModeRepository {
69     // TODO(b/254848912): Replace this with a generic SettingObserver coroutine once we have it.
70     override val isAirplaneMode: StateFlow<Boolean> =
71         conflatedCallbackFlow {
72                 val observer =
73                     object : SettingObserver(globalSettings, bgHandler, Global.AIRPLANE_MODE_ON) {
74                         override fun handleValueChanged(value: Int, observedChange: Boolean) {
75                             trySend(value == 1)
76                         }
77                     }
78 
79                 observer.isListening = true
80                 trySend(observer.value == 1)
81                 awaitClose { observer.isListening = false }
82             }
83             .distinctUntilChanged()
84             .logDiffsForTable(logger, columnName = "isAirplaneMode", initialValue = false)
85             .stateIn(
86                 scope,
87                 started = SharingStarted.WhileSubscribed(),
88                 // When the observer starts listening, the flow will emit the current value so the
89                 // initialValue here is irrelevant.
90                 initialValue = false,
91             )
92 
93     override suspend fun setIsAirplaneMode(isEnabled: Boolean) =
94         withContext(backgroundContext) { connectivityManager.setAirplaneMode(isEnabled) }
95 }
96