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 distributed under the
11  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
12  * KIND, either express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 package com.android.systemui.unfold.util
16 
17 import android.content.ContentResolver
18 import android.database.ContentObserver
19 import android.provider.Settings
20 import com.android.systemui.unfold.UnfoldTransitionProgressProvider
21 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
22 import dagger.assisted.Assisted
23 import dagger.assisted.AssistedFactory
24 import dagger.assisted.AssistedInject
25 
26 /** Wraps [UnfoldTransitionProgressProvider] to disable transitions when animations are disabled. */
27 class ScaleAwareTransitionProgressProvider
28 @AssistedInject
29 constructor(
30     @Assisted progressProviderToWrap: UnfoldTransitionProgressProvider,
31     private val contentResolver: ContentResolver
32 ) : UnfoldTransitionProgressProvider {
33 
34     private val scopedUnfoldTransitionProgressProvider =
35         ScopedUnfoldTransitionProgressProvider(progressProviderToWrap)
36 
37     private val animatorDurationScaleObserver =
38         object : ContentObserver(null) {
onChangenull39             override fun onChange(selfChange: Boolean) {
40                 onAnimatorScaleChanged()
41             }
42         }
43 
44     init {
45         contentResolver.registerContentObserver(
46             Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),
47             /* notifyForDescendants= */ false,
48             animatorDurationScaleObserver
49         )
50         onAnimatorScaleChanged()
51     }
52 
onAnimatorScaleChangednull53     private fun onAnimatorScaleChanged() {
54         scopedUnfoldTransitionProgressProvider.setReadyToHandleTransition(
55             contentResolver.areAnimationsEnabled()
56         )
57     }
58 
addCallbacknull59     override fun addCallback(listener: TransitionProgressListener) {
60         scopedUnfoldTransitionProgressProvider.addCallback(listener)
61     }
62 
removeCallbacknull63     override fun removeCallback(listener: TransitionProgressListener) {
64         scopedUnfoldTransitionProgressProvider.removeCallback(listener)
65     }
66 
destroynull67     override fun destroy() {
68         contentResolver.unregisterContentObserver(animatorDurationScaleObserver)
69         scopedUnfoldTransitionProgressProvider.destroy()
70     }
71 
72     @AssistedFactory
73     interface Factory {
wrapnull74         fun wrap(
75             progressProvider: UnfoldTransitionProgressProvider
76         ): ScaleAwareTransitionProgressProvider
77     }
78 
79     companion object {
80         fun ContentResolver.areAnimationsEnabled(): Boolean {
81             val animationScale =
82                 Settings.Global.getString(
83                         this,
84                         Settings.Global.ANIMATOR_DURATION_SCALE,
85                     )
86                     ?.toFloatOrNull()
87                     ?: 1f
88             return animationScale != 0f
89         }
90     }
91 }
92