1 /*
2  * Copyright (C) 2024 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.qs.tiles.impl.night.domain.interactor
18 
19 import android.content.Context
20 import android.hardware.display.ColorDisplayManager
21 import android.os.UserHandle
22 import com.android.systemui.accessibility.data.repository.NightDisplayRepository
23 import com.android.systemui.dagger.qualifiers.Application
24 import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
25 import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
26 import com.android.systemui.qs.tiles.impl.night.domain.model.NightDisplayTileModel
27 import com.android.systemui.util.time.DateFormatUtil
28 import java.time.LocalTime
29 import javax.inject.Inject
30 import kotlinx.coroutines.flow.Flow
31 import kotlinx.coroutines.flow.flowOf
32 import kotlinx.coroutines.flow.map
33 
34 /** Observes screen record state changes providing the [NightDisplayTileModel]. */
35 class NightDisplayTileDataInteractor
36 @Inject
37 constructor(
38     @Application private val context: Context,
39     private val dateFormatUtil: DateFormatUtil,
40     private val nightDisplayRepository: NightDisplayRepository,
41 ) : QSTileDataInteractor<NightDisplayTileModel> {
42 
tileDatanull43     override fun tileData(
44         user: UserHandle,
45         triggers: Flow<DataUpdateTrigger>
46     ): Flow<NightDisplayTileModel> =
47         nightDisplayRepository.nightDisplayState(user).map {
48             generateModel(
49                 it.autoMode,
50                 it.isActivated,
51                 it.startTime,
52                 it.endTime,
53                 it.shouldForceAutoMode,
54                 it.locationEnabled
55             )
56         }
57 
58     /** This checks resources and there fore does not make a binder call. */
availabilitynull59     override fun availability(user: UserHandle): Flow<Boolean> =
60         flowOf(ColorDisplayManager.isNightDisplayAvailable(context))
61 
62     private fun generateModel(
63         autoMode: Int,
64         isNightDisplayActivated: Boolean,
65         customStartTime: LocalTime?,
66         customEndTime: LocalTime?,
67         shouldForceAutoMode: Boolean,
68         locationEnabled: Boolean,
69     ): NightDisplayTileModel {
70         if (autoMode == ColorDisplayManager.AUTO_MODE_TWILIGHT) {
71             return NightDisplayTileModel.AutoModeTwilight(
72                 isNightDisplayActivated,
73                 shouldForceAutoMode,
74                 locationEnabled,
75             )
76         } else if (autoMode == ColorDisplayManager.AUTO_MODE_CUSTOM_TIME) {
77             return NightDisplayTileModel.AutoModeCustom(
78                 isNightDisplayActivated,
79                 shouldForceAutoMode,
80                 customStartTime,
81                 customEndTime,
82                 dateFormatUtil.is24HourFormat,
83             )
84         } else { // auto mode off
85             return NightDisplayTileModel.AutoModeOff(isNightDisplayActivated, shouldForceAutoMode)
86         }
87     }
88 }
89