• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * 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.settings.accessibility
18 
19 import android.annotation.DrawableRes
20 import android.app.settings.SettingsEnums.ACTION_REMOVE_ANIMATION
21 import android.content.Context
22 import android.provider.Settings
23 import com.android.settings.R
24 import com.android.settings.contract.KEY_REMOVE_ANIMATION
25 import com.android.settings.metrics.PreferenceActionMetricsProvider
26 import com.android.settingslib.datastore.HandlerExecutor
27 import com.android.settingslib.datastore.KeyValueStore
28 import com.android.settingslib.datastore.KeyedObserver
29 import com.android.settingslib.datastore.NoOpKeyedObservable
30 import com.android.settingslib.datastore.SettingsGlobalStore
31 import com.android.settingslib.metadata.PreferenceLifecycleContext
32 import com.android.settingslib.metadata.PreferenceLifecycleProvider
33 import com.android.settingslib.metadata.ReadWritePermit
34 import com.android.settingslib.metadata.SensitivityLevel
35 import com.android.settingslib.metadata.SwitchPreference
36 
37 class RemoveAnimationsPreference :
38     SwitchPreference(
39         KEY,
40         R.string.accessibility_disable_animations,
41         R.string.accessibility_disable_animations_summary,
42     ),
43     PreferenceActionMetricsProvider,
44     PreferenceLifecycleProvider {
45 
46     private var mSettingsKeyedObserver: KeyedObserver<String>? = null
47 
48     override val icon: Int
49         @DrawableRes get() = R.drawable.ic_accessibility_animation
50 
51     override val preferenceActionMetrics: Int
52         get() = ACTION_REMOVE_ANIMATION
53 
54     override fun tags(context: Context) = arrayOf(KEY_REMOVE_ANIMATION)
55 
56     override fun onStart(context: PreferenceLifecycleContext) {
57         val observer = KeyedObserver<String> { _, _ -> context.notifyPreferenceChange(KEY) }
58         mSettingsKeyedObserver = observer
59         val storage = SettingsGlobalStore.get(context)
60         for (key in getAnimationKeys()) {
61             storage.addObserver(key, observer, HandlerExecutor.main)
62         }
63     }
64 
65     override fun onStop(context: PreferenceLifecycleContext) {
66         mSettingsKeyedObserver?.let {
67             val storage = SettingsGlobalStore.get(context)
68             for (key in getAnimationKeys()) {
69                 storage.removeObserver(key, it)
70             }
71             mSettingsKeyedObserver = null
72         }
73     }
74 
75     override fun storage(context: Context): KeyValueStore = RemoveAnimationsStorage(context)
76 
77     override fun getReadPermissions(context: Context) = SettingsGlobalStore.getReadPermissions()
78 
79     override fun getWritePermissions(context: Context) = SettingsGlobalStore.getWritePermissions()
80 
81     override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) =
82         ReadWritePermit.ALLOW
83 
84     override fun getWritePermit(
85         context: Context,
86         value: Boolean?,
87         callingPid: Int,
88         callingUid: Int,
89     ) = ReadWritePermit.ALLOW
90 
91     override val sensitivityLevel
92         get() = SensitivityLevel.NO_SENSITIVITY
93 
94     @Suppress("UNCHECKED_CAST")
95     private class RemoveAnimationsStorage(private val context: Context) :
96         NoOpKeyedObservable<String>(), KeyValueStore {
97         override fun contains(key: String) = key == KEY
98 
99         override fun <T : Any> getValue(key: String, valueType: Class<T>) =
100             when {
101                 key == KEY && valueType == Boolean::class.javaObjectType ->
102                     !isAnimationEnabled(context) as T
103                 else -> null
104             }
105 
106         override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
107             if (key == KEY && value is Boolean) {
108                 setAnimationEnabled(context, !value)
109             }
110         }
111     }
112 
113     companion object {
114         // This KEY must match the key used in accessibility_color_and_motion.xml for this
115         // preference, at least until the entire screen is migrated to Catalyst and that XML
116         // is deleted. Use any key from the set of 3 toggle animation keys.
117         const val KEY = Settings.Global.ANIMATOR_DURATION_SCALE
118 
119         const val ANIMATION_ON_VALUE: Float = 1.0f
120         const val ANIMATION_OFF_VALUE: Float = 0.0f
121 
122         fun isAnimationEnabled(context: Context): Boolean {
123             val storage = SettingsGlobalStore.get(context)
124             // This pref treats animation as enabled if *any* of the animation types are enabled.
125             for (animationSetting in getAnimationKeys()) {
126                 val animationValue: Float? = storage.getFloat(animationSetting)
127                 // Animation is enabled by default, so treat null as enabled.
128                 if (animationValue == null || animationValue > ANIMATION_OFF_VALUE) {
129                     return true
130                 }
131             }
132             return false
133         }
134 
135         fun setAnimationEnabled(context: Context, enabled: Boolean) {
136             val storage = SettingsGlobalStore.get(context)
137             val value = if (enabled) ANIMATION_ON_VALUE else ANIMATION_OFF_VALUE
138             for (animationSetting in getAnimationKeys()) {
139                 storage.setFloat(animationSetting, value)
140             }
141         }
142 
143         fun getAnimationKeys() =
144             listOf(
145                 Settings.Global.WINDOW_ANIMATION_SCALE,
146                 Settings.Global.TRANSITION_ANIMATION_SCALE,
147                 Settings.Global.ANIMATOR_DURATION_SCALE,
148             )
149     }
150 }
151