1 /* 2 * Copyright (C) 2025 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.launcher3 18 19 import android.content.Context 20 import android.database.ContentObserver 21 import android.net.Uri 22 import android.os.Handler 23 import android.os.Looper 24 import android.provider.Settings 25 import android.provider.Settings.Global.ANIMATOR_DURATION_SCALE 26 import android.provider.Settings.Global.TRANSITION_ANIMATION_SCALE 27 import android.provider.Settings.Global.WINDOW_ANIMATION_SCALE 28 import com.android.launcher3.dagger.ApplicationContext 29 import com.android.launcher3.dagger.LauncherAppComponent 30 import com.android.launcher3.dagger.LauncherAppSingleton 31 import com.android.launcher3.util.DaggerSingletonObject 32 import com.android.launcher3.util.DaggerSingletonTracker 33 import com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR 34 import java.util.concurrent.ConcurrentHashMap 35 import javax.inject.Inject 36 37 /** Tracker Class for when user turns on/off remove animation setting. */ 38 @LauncherAppSingleton 39 class RemoveAnimationSettingsTracker 40 @Inject 41 constructor(@ApplicationContext val context: Context, tracker: DaggerSingletonTracker) : 42 ContentObserver(Handler(Looper.getMainLooper())) { 43 44 private val contentResolver = context.contentResolver 45 46 /** Caches the last seen value for registered keys. */ 47 private val cache: MutableMap<Uri, Float> = ConcurrentHashMap() 48 49 init { <lambda>null50 UI_HELPER_EXECUTOR.execute { 51 contentResolver.registerContentObserver(WINDOW_ANIMATION_SCALE_URI, false, this) 52 contentResolver.registerContentObserver(TRANSITION_ANIMATION_SCALE_URI, false, this) 53 contentResolver.registerContentObserver(ANIMATOR_DURATION_SCALE_URI, false, this) 54 } 55 <lambda>null56 tracker.addCloseable { 57 UI_HELPER_EXECUTOR.execute { contentResolver.unregisterContentObserver(this) } 58 } 59 } 60 61 /** 62 * Returns the value for this classes key from the cache. If not in cache, will call 63 * [updateValue] to fetch. 64 */ getValuenull65 fun getValue(uri: Uri): Float { 66 return getValue(uri, 1f) 67 } 68 69 /** 70 * Returns the value for this classes key from the cache. If not in cache, will call 71 * [getValueFromSettingsGlobal] to fetch. 72 */ getValuenull73 private fun getValue(uri: Uri, defaultValue: Float): Float { 74 return cache.computeIfAbsent(uri) { getValueFromSettingsGlobal(uri, defaultValue) } 75 } 76 77 /** Returns if user has opted into having no animation on their device. */ isRemoveAnimationEnablednull78 fun isRemoveAnimationEnabled(): Boolean { 79 return getValue(WINDOW_ANIMATION_SCALE_URI) == 0f && 80 getValue(TRANSITION_ANIMATION_SCALE_URI) == 0f && 81 getValue(ANIMATOR_DURATION_SCALE_URI) == 0f 82 } 83 onChangenull84 override fun onChange(selfChange: Boolean, uri: Uri?) { 85 if (uri == null) return 86 updateValue(uri) 87 } 88 getValueFromSettingsGlobalnull89 private fun getValueFromSettingsGlobal(uri: Uri, defaultValue: Float = 1f): Float { 90 return Settings.Global.getFloat(contentResolver, uri.lastPathSegment, defaultValue) 91 } 92 updateValuenull93 private fun updateValue(uri: Uri, defaultValue: Float = 1f) { 94 val newValue = getValueFromSettingsGlobal(uri, defaultValue) 95 cache[uri] = newValue 96 } 97 98 companion object { 99 @JvmField 100 val INSTANCE = 101 DaggerSingletonObject(LauncherAppComponent::getRemoveAnimationSettingsTracker) 102 @JvmField 103 val WINDOW_ANIMATION_SCALE_URI: Uri = Settings.Global.getUriFor(WINDOW_ANIMATION_SCALE) 104 @JvmField 105 val TRANSITION_ANIMATION_SCALE_URI: Uri = 106 Settings.Global.getUriFor(TRANSITION_ANIMATION_SCALE) 107 @JvmField 108 val ANIMATOR_DURATION_SCALE_URI: Uri = Settings.Global.getUriFor(ANIMATOR_DURATION_SCALE) 109 } 110 } 111