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 package com.android.systemui.util.animation.data.repository
17 
18 import android.content.ContentResolver
19 import android.database.ContentObserver
20 import android.os.Handler
21 import android.provider.Settings
22 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
23 import com.android.systemui.dagger.qualifiers.Background
24 import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider.Companion.areAnimationsEnabled
25 import javax.inject.Inject
26 import kotlinx.coroutines.CoroutineDispatcher
27 import kotlinx.coroutines.channels.awaitClose
28 import kotlinx.coroutines.flow.Flow
29 import kotlinx.coroutines.flow.flowOn
30 
31 /** Utility class that could give information about if animation are enabled in the system */
32 interface AnimationStatusRepository {
areAnimationsEnablednull33     fun areAnimationsEnabled(): Flow<Boolean>
34 }
35 
36 class AnimationStatusRepositoryImpl
37 @Inject
38 constructor(
39     private val resolver: ContentResolver,
40     @Background private val backgroundHandler: Handler,
41     @Background private val backgroundDispatcher: CoroutineDispatcher
42 ) : AnimationStatusRepository {
43 
44     /**
45      * Emits true if animations are enabled in the system, after subscribing it immediately emits
46      * the current state
47      */
48     override fun areAnimationsEnabled(): Flow<Boolean> =
49         conflatedCallbackFlow {
50                 val initialValue = resolver.areAnimationsEnabled()
51                 trySend(initialValue)
52 
53                 val observer =
54                     object : ContentObserver(backgroundHandler) {
55                         override fun onChange(selfChange: Boolean) {
56                             val updatedValue = resolver.areAnimationsEnabled()
57                             trySend(updatedValue)
58                         }
59                     }
60 
61                 resolver.registerContentObserver(
62                     Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),
63                     /* notifyForDescendants= */ false,
64                     observer
65                 )
66 
67                 awaitClose { resolver.unregisterContentObserver(observer) }
68             }
69             .flowOn(backgroundDispatcher)
70 }
71