From 9cbc478574b67eb529d1222f30cd3f2d026b9cd7 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Tue, 8 Oct 2024 14:47:17 -0400 Subject: [PATCH] Split LauncherPrefs into abs class / impl. Splitting allows easily making a fake that doesn't have to override the implementation details of LauncherPrefs. The fake should not deal with SharedPreferences. LauncherPrefs could be an interface, but then the companion object has more limitations. The solution there is to have a dedicated object class, e.g. `LauncherPrefItems`. I went with an abs class to make the refactor simpler. Flag: EXEMPT refactor Bug: 369641781 Test: go/testedequals Change-Id: I97a2d495d3b5fa892fa53a11fb3f7a7dfb98515b --- .../quickstep/util/RecentsOrientedState.java | 7 +- .../android/launcher3/LauncherAppState.java | 4 +- .../launcher3/LauncherPrefChangeListener.java | 38 ++ src/com/android/launcher3/LauncherPrefs.kt | 329 ++++++++++-------- .../launcher3/states/RotationHelper.java | 7 +- .../launcher3/util/DisplayController.java | 30 +- .../AppWidgetsRestoredReceiverTest.kt | 2 +- .../android/launcher3/LauncherPrefsTest.kt | 17 +- .../launcher3/provider/RestoreDbTaskTest.java | 2 +- 9 files changed, 251 insertions(+), 185 deletions(-) create mode 100644 src/com/android/launcher3/LauncherPrefChangeListener.java diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java index 9335e7e475..a5be89af19 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java +++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java @@ -30,7 +30,6 @@ import static com.android.quickstep.BaseActivityInterface.getTaskDimension; import static java.lang.annotation.RetentionPolicy.SOURCE; import android.content.Context; -import android.content.SharedPreferences; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.PointF; @@ -45,6 +44,7 @@ import androidx.annotation.NonNull; import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.LauncherPrefChangeListener; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.touch.PagedOrientationHandler; @@ -66,8 +66,7 @@ import java.util.function.IntConsumer; * This class has initial default state assuming the device and foreground app have * no ({@link Surface#ROTATION_0} rotation. */ -public class RecentsOrientedState implements - SharedPreferences.OnSharedPreferenceChangeListener { +public class RecentsOrientedState implements LauncherPrefChangeListener { private static final String TAG = "RecentsOrientedState"; private static final boolean DEBUG = false; @@ -283,7 +282,7 @@ public class RecentsOrientedState implements } @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { + public void onPrefChanged(String s) { if (LauncherPrefs.ALLOW_ROTATION.getSharedPrefKey().equals(s)) { updateHomeRotationSetting(); } diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index 15641ab516..05a3a52463 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -266,7 +266,7 @@ public class LauncherAppState implements SafeCloseable { } private class IconObserver - implements IconProvider.IconChangeListener, OnSharedPreferenceChangeListener { + implements IconProvider.IconChangeListener, LauncherPrefChangeListener { @Override public void onAppIconChanged(String packageName, UserHandle user) { @@ -288,7 +288,7 @@ public class LauncherAppState implements SafeCloseable { } @Override - public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + public void onPrefChanged(String key) { if (Themes.KEY_THEMED_ICONS.equals(key)) { mIconProvider.setIconThemeSupported(Themes.isThemedIconEnabled(mContext)); verifyIconChanged(); diff --git a/src/com/android/launcher3/LauncherPrefChangeListener.java b/src/com/android/launcher3/LauncherPrefChangeListener.java new file mode 100644 index 0000000000..3e9a8464d9 --- /dev/null +++ b/src/com/android/launcher3/LauncherPrefChangeListener.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; + +/** + * Listener for changes in [LauncherPrefs]. + *

+ * The listener also serves as an [OnSharedPreferenceChangeListener] where + * [onSharedPreferenceChanged] delegates to [onPrefChanged]. Overriding [onSharedPreferenceChanged] + * breaks compatibility with [SharedPreferences]. + */ +public interface LauncherPrefChangeListener extends OnSharedPreferenceChangeListener { + + /** Callback invoked when the preference for [key] has changed. */ + void onPrefChanged(String key); + + @Override + default void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + onPrefChanged(key); + } +} diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt index 13181e87f2..7ebfc1818a 100644 --- a/src/com/android/launcher3/LauncherPrefs.kt +++ b/src/com/android/launcher3/LauncherPrefs.kt @@ -18,7 +18,6 @@ package com.android.launcher3 import android.content.Context import android.content.Context.MODE_PRIVATE import android.content.SharedPreferences -import android.content.SharedPreferences.OnSharedPreferenceChangeListener import androidx.annotation.VisibleForTesting import com.android.launcher3.BuildConfig.WIDGET_ON_FIRST_SCREEN import com.android.launcher3.LauncherFiles.DEVICE_PREFERENCES_KEY @@ -34,11 +33,177 @@ import com.android.launcher3.util.SafeCloseable import com.android.launcher3.util.Themes /** - * Use same context for shared preferences, so that we use a single cached instance + * Manages Launcher [SharedPreferences] through [Item] instances. * * TODO(b/262721340): Replace all direct SharedPreference refs with LauncherPrefs / Item methods. */ -class LauncherPrefs(private val encryptedContext: Context) : SafeCloseable { +abstract class LauncherPrefs : SafeCloseable { + + /** Returns the value with type [T] for [item]. */ + abstract fun get(item: ContextualItem): T + + /** Returns the value with type [T] for [item]. */ + abstract fun get(item: ConstantItem): T + + /** Stores the values for each item in preferences. */ + abstract fun put(vararg itemsToValues: Pair) + + /** Stores the [value] with type [T] for [item] in preferences. */ + abstract fun put(item: Item, value: T) + + /** Synchronous version of [put]. */ + abstract fun putSync(vararg itemsToValues: Pair) + + /** Registers [listener] for [items]. */ + abstract fun addListener(listener: LauncherPrefChangeListener, vararg items: Item) + + /** Unregisters [listener] for [items]. */ + abstract fun removeListener(listener: LauncherPrefChangeListener, vararg items: Item) + + /** Returns `true` iff all [items] have a value. */ + abstract fun has(vararg items: Item): Boolean + + /** Removes the value for each item in [items]. */ + abstract fun remove(vararg items: Item) + + /** Synchronous version of [remove]. */ + abstract fun removeSync(vararg items: Item) + + companion object { + @VisibleForTesting const val BOOT_AWARE_PREFS_KEY = "boot_aware_prefs" + + @JvmField + var INSTANCE = MainThreadInitializedObject { LauncherPrefsImpl(it) } + + @JvmStatic fun get(context: Context): LauncherPrefs = INSTANCE.get(context) + + const val TASKBAR_PINNING_KEY = "TASKBAR_PINNING_KEY" + const val TASKBAR_PINNING_DESKTOP_MODE_KEY = "TASKBAR_PINNING_DESKTOP_MODE_KEY" + const val SHOULD_SHOW_SMARTSPACE_KEY = "SHOULD_SHOW_SMARTSPACE_KEY" + @JvmField + val ICON_STATE = nonRestorableItem("pref_icon_shape_path", "", EncryptionType.ENCRYPTED) + + @JvmField + val ENABLE_TWOLINE_ALLAPPS_TOGGLE = backedUpItem("pref_enable_two_line_toggle", false) + @JvmField + val THEMED_ICONS = backedUpItem(Themes.KEY_THEMED_ICONS, false, EncryptionType.ENCRYPTED) + @JvmField val PROMISE_ICON_IDS = backedUpItem(InstallSessionHelper.PROMISE_ICON_IDS, "") + @JvmField val WORK_EDU_STEP = backedUpItem("showed_work_profile_edu", 0) + @JvmField + val WORKSPACE_SIZE = + backedUpItem(DeviceGridState.KEY_WORKSPACE_SIZE, "", EncryptionType.ENCRYPTED) + @JvmField + val HOTSEAT_COUNT = + backedUpItem(DeviceGridState.KEY_HOTSEAT_COUNT, -1, EncryptionType.ENCRYPTED) + @JvmField + val TASKBAR_PINNING = + backedUpItem(TASKBAR_PINNING_KEY, false, EncryptionType.DEVICE_PROTECTED) + @JvmField + val TASKBAR_PINNING_IN_DESKTOP_MODE = + backedUpItem(TASKBAR_PINNING_DESKTOP_MODE_KEY, true, EncryptionType.DEVICE_PROTECTED) + + @JvmField + val DEVICE_TYPE = + backedUpItem( + DeviceGridState.KEY_DEVICE_TYPE, + InvariantDeviceProfile.TYPE_PHONE, + EncryptionType.ENCRYPTED, + ) + @JvmField + val DB_FILE = backedUpItem(DeviceGridState.KEY_DB_FILE, "", EncryptionType.ENCRYPTED) + @JvmField + val SHOULD_SHOW_SMARTSPACE = + backedUpItem( + SHOULD_SHOW_SMARTSPACE_KEY, + WIDGET_ON_FIRST_SCREEN, + EncryptionType.DEVICE_PROTECTED, + ) + @JvmField + val RESTORE_DEVICE = + backedUpItem( + RestoreDbTask.RESTORED_DEVICE_TYPE, + InvariantDeviceProfile.TYPE_PHONE, + EncryptionType.ENCRYPTED, + ) + @JvmField + val IS_FIRST_LOAD_AFTER_RESTORE = + nonRestorableItem(FIRST_LOAD_AFTER_RESTORE_KEY, false, EncryptionType.ENCRYPTED) + @JvmField val APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_IDS, "") + @JvmField val OLD_APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_OLD_IDS, "") + @JvmField + val GRID_NAME = + ConstantItem( + "idp_grid_name", + isBackedUp = true, + defaultValue = null, + encryptionType = EncryptionType.ENCRYPTED, + type = String::class.java, + ) + @JvmField + val ALLOW_ROTATION = + backedUpItem(RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY, Boolean::class.java) { + RotationHelper.getAllowRotationDefaultValue(DisplayController.INSTANCE.get(it).info) + } + + // Preferences for widget configurations + @JvmField + val RECONFIGURABLE_WIDGET_EDUCATION_TIP_SEEN = + backedUpItem("launcher.reconfigurable_widget_education_tip_seen", false) + + @JvmStatic + fun backedUpItem( + sharedPrefKey: String, + defaultValue: T, + encryptionType: EncryptionType = EncryptionType.ENCRYPTED, + ): ConstantItem = + ConstantItem(sharedPrefKey, isBackedUp = true, defaultValue, encryptionType) + + @JvmStatic + fun backedUpItem( + sharedPrefKey: String, + type: Class, + encryptionType: EncryptionType = EncryptionType.ENCRYPTED, + defaultValueFromContext: (c: Context) -> T, + ): ContextualItem = + ContextualItem( + sharedPrefKey, + isBackedUp = true, + defaultValueFromContext, + encryptionType, + type, + ) + + @JvmStatic + fun nonRestorableItem( + sharedPrefKey: String, + defaultValue: T, + encryptionType: EncryptionType = EncryptionType.ENCRYPTED, + ): ConstantItem = + ConstantItem(sharedPrefKey, isBackedUp = false, defaultValue, encryptionType) + + @Deprecated("Don't use shared preferences directly. Use other LauncherPref methods.") + @JvmStatic + fun getPrefs(context: Context): SharedPreferences { + // Use application context for shared preferences, so we use single cached instance + return context.applicationContext.getSharedPreferences( + SHARED_PREFERENCES_KEY, + MODE_PRIVATE, + ) + } + + @Deprecated("Don't use shared preferences directly. Use other LauncherPref methods.") + @JvmStatic + fun getDevicePrefs(context: Context): SharedPreferences { + // Use application context for shared preferences, so we use a single cached instance + return context.applicationContext.getSharedPreferences( + DEVICE_PREFERENCES_KEY, + MODE_PRIVATE, + ) + } + } +} + +private class LauncherPrefsImpl(private val encryptedContext: Context) : LauncherPrefs() { private val deviceProtectedStorageContext = encryptedContext.createDeviceProtectedStorageContext() @@ -54,11 +219,11 @@ class LauncherPrefs(private val encryptedContext: Context) : SafeCloseable { else item.encryptedPrefs /** Wrapper around `getInner` for a `ContextualItem` */ - fun get(item: ContextualItem): T = + override fun get(item: ContextualItem): T = getInner(item, item.defaultValueFromContext(encryptedContext)) /** Wrapper around `getInner` for an `Item` */ - fun get(item: ConstantItem): T = getInner(item, item.defaultValue) + override fun get(item: ConstantItem): T = getInner(item, item.defaultValue) /** * Retrieves the value for an [Item] from [SharedPreferences]. It handles method typing via the @@ -97,17 +262,17 @@ class LauncherPrefs(private val encryptedContext: Context) : SafeCloseable { * prepareToPutValue(itemsToValues) for every distinct `SharedPreferences` file present in the * provided item configurations. */ - fun put(vararg itemsToValues: Pair): Unit = + override fun put(vararg itemsToValues: Pair): Unit = prepareToPutValues(itemsToValues).forEach { it.apply() } /** See referenced `put` method above. */ - fun put(item: Item, value: T): Unit = put(item.to(value)) + override fun put(item: Item, value: T): Unit = put(item.to(value)) /** * Synchronously stores all the values provided according to their associated Item * configuration. */ - fun putSync(vararg itemsToValues: Pair): Unit = + override fun putSync(vararg itemsToValues: Pair): Unit = prepareToPutValues(itemsToValues).forEach { it.commit() } /** @@ -152,7 +317,7 @@ class LauncherPrefs(private val encryptedContext: Context) : SafeCloseable { @Suppress("UNCHECKED_CAST") private fun SharedPreferences.Editor.putValue( item: Item, - value: Any? + value: Any?, ): SharedPreferences.Editor = when (item.type) { String::class.java -> putString(item.sharedPrefKey, value as? String) @@ -176,7 +341,7 @@ class LauncherPrefs(private val encryptedContext: Context) : SafeCloseable { * `SharedPreferences` files associated with the provided list of items. The listener will need * to filter update notifications so they don't activate for non-relevant updates. */ - fun addListener(listener: OnSharedPreferenceChangeListener, vararg items: Item) { + override fun addListener(listener: LauncherPrefChangeListener, vararg items: Item) { items .map { chooseSharedPreferences(it) } .distinct() @@ -187,7 +352,7 @@ class LauncherPrefs(private val encryptedContext: Context) : SafeCloseable { * Stops the listener from getting notified of any more updates to any of the * `SharedPreferences` files associated with any of the provided list of [Item]. */ - fun removeListener(listener: OnSharedPreferenceChangeListener, vararg items: Item) { + override fun removeListener(listener: LauncherPrefChangeListener, vararg items: Item) { // If a listener is not registered to a SharedPreference, unregistering it does nothing items .map { chooseSharedPreferences(it) } @@ -199,7 +364,7 @@ class LauncherPrefs(private val encryptedContext: Context) : SafeCloseable { * Checks if all the provided [Item] have values stored in their corresponding * `SharedPreferences` files. */ - fun has(vararg items: Item): Boolean { + override fun has(vararg items: Item): Boolean { items .groupBy { chooseSharedPreferences(it) } .forEach { (prefs, itemsSublist) -> @@ -211,10 +376,10 @@ class LauncherPrefs(private val encryptedContext: Context) : SafeCloseable { /** * Asynchronously removes the [Item]'s value from its corresponding `SharedPreferences` file. */ - fun remove(vararg items: Item) = prepareToRemove(items).forEach { it.apply() } + override fun remove(vararg items: Item) = prepareToRemove(items).forEach { it.apply() } /** Synchronously removes the [Item]'s value from its corresponding `SharedPreferences` file. */ - fun removeSync(vararg items: Item) = prepareToRemove(items).forEach { it.commit() } + override fun removeSync(vararg items: Item) = prepareToRemove(items).forEach { it.commit() } /** * Removes the key value pairs stored in `SharedPreferences` for each corresponding Item. If the @@ -244,138 +409,6 @@ class LauncherPrefs(private val encryptedContext: Context) : SafeCloseable { } override fun close() {} - - companion object { - @VisibleForTesting const val BOOT_AWARE_PREFS_KEY = "boot_aware_prefs" - - @JvmField var INSTANCE = MainThreadInitializedObject { LauncherPrefs(it) } - - @JvmStatic fun get(context: Context): LauncherPrefs = INSTANCE.get(context) - - const val TASKBAR_PINNING_KEY = "TASKBAR_PINNING_KEY" - const val TASKBAR_PINNING_DESKTOP_MODE_KEY = "TASKBAR_PINNING_DESKTOP_MODE_KEY" - const val SHOULD_SHOW_SMARTSPACE_KEY = "SHOULD_SHOW_SMARTSPACE_KEY" - @JvmField - val ICON_STATE = nonRestorableItem("pref_icon_shape_path", "", EncryptionType.ENCRYPTED) - - @JvmField - val ENABLE_TWOLINE_ALLAPPS_TOGGLE = backedUpItem("pref_enable_two_line_toggle", false) - @JvmField - val THEMED_ICONS = backedUpItem(Themes.KEY_THEMED_ICONS, false, EncryptionType.ENCRYPTED) - @JvmField val PROMISE_ICON_IDS = backedUpItem(InstallSessionHelper.PROMISE_ICON_IDS, "") - @JvmField val WORK_EDU_STEP = backedUpItem("showed_work_profile_edu", 0) - @JvmField - val WORKSPACE_SIZE = - backedUpItem(DeviceGridState.KEY_WORKSPACE_SIZE, "", EncryptionType.ENCRYPTED) - @JvmField - val HOTSEAT_COUNT = - backedUpItem(DeviceGridState.KEY_HOTSEAT_COUNT, -1, EncryptionType.ENCRYPTED) - @JvmField - val TASKBAR_PINNING = - backedUpItem(TASKBAR_PINNING_KEY, false, EncryptionType.DEVICE_PROTECTED) - @JvmField - val TASKBAR_PINNING_IN_DESKTOP_MODE = - backedUpItem(TASKBAR_PINNING_DESKTOP_MODE_KEY, true, EncryptionType.DEVICE_PROTECTED) - - @JvmField - val DEVICE_TYPE = - backedUpItem( - DeviceGridState.KEY_DEVICE_TYPE, - InvariantDeviceProfile.TYPE_PHONE, - EncryptionType.ENCRYPTED - ) - @JvmField - val DB_FILE = backedUpItem(DeviceGridState.KEY_DB_FILE, "", EncryptionType.ENCRYPTED) - @JvmField - val SHOULD_SHOW_SMARTSPACE = - backedUpItem( - SHOULD_SHOW_SMARTSPACE_KEY, - WIDGET_ON_FIRST_SCREEN, - EncryptionType.DEVICE_PROTECTED - ) - @JvmField - val RESTORE_DEVICE = - backedUpItem( - RestoreDbTask.RESTORED_DEVICE_TYPE, - InvariantDeviceProfile.TYPE_PHONE, - EncryptionType.ENCRYPTED - ) - @JvmField - val IS_FIRST_LOAD_AFTER_RESTORE = - nonRestorableItem(FIRST_LOAD_AFTER_RESTORE_KEY, false, EncryptionType.ENCRYPTED) - @JvmField val APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_IDS, "") - @JvmField val OLD_APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_OLD_IDS, "") - @JvmField - val GRID_NAME = - ConstantItem( - "idp_grid_name", - isBackedUp = true, - defaultValue = null, - encryptionType = EncryptionType.ENCRYPTED, - type = String::class.java - ) - @JvmField - val ALLOW_ROTATION = - backedUpItem(RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY, Boolean::class.java) { - RotationHelper.getAllowRotationDefaultValue(DisplayController.INSTANCE.get(it).info) - } - - // Preferences for widget configurations - @JvmField - val RECONFIGURABLE_WIDGET_EDUCATION_TIP_SEEN = - backedUpItem("launcher.reconfigurable_widget_education_tip_seen", false) - - @JvmStatic - fun backedUpItem( - sharedPrefKey: String, - defaultValue: T, - encryptionType: EncryptionType = EncryptionType.ENCRYPTED - ): ConstantItem = - ConstantItem(sharedPrefKey, isBackedUp = true, defaultValue, encryptionType) - - @JvmStatic - fun backedUpItem( - sharedPrefKey: String, - type: Class, - encryptionType: EncryptionType = EncryptionType.ENCRYPTED, - defaultValueFromContext: (c: Context) -> T - ): ContextualItem = - ContextualItem( - sharedPrefKey, - isBackedUp = true, - defaultValueFromContext, - encryptionType, - type - ) - - @JvmStatic - fun nonRestorableItem( - sharedPrefKey: String, - defaultValue: T, - encryptionType: EncryptionType = EncryptionType.ENCRYPTED - ): ConstantItem = - ConstantItem(sharedPrefKey, isBackedUp = false, defaultValue, encryptionType) - - @Deprecated("Don't use shared preferences directly. Use other LauncherPref methods.") - @JvmStatic - fun getPrefs(context: Context): SharedPreferences { - // Use application context for shared preferences, so we use single cached instance - return context.applicationContext.getSharedPreferences( - SHARED_PREFERENCES_KEY, - MODE_PRIVATE - ) - } - - @Deprecated("Don't use shared preferences directly. Use other LauncherPref methods.") - @JvmStatic - fun getDevicePrefs(context: Context): SharedPreferences { - // Use application context for shared preferences, so we use a single cached instance - return context.applicationContext.getSharedPreferences( - DEVICE_PREFERENCES_KEY, - MODE_PRIVATE - ) - } - } } abstract class Item { @@ -395,7 +428,7 @@ data class ConstantItem( val defaultValue: T, override val encryptionType: EncryptionType, // The default value can be null. If so, the type needs to be explicitly stated, or else NPE - override val type: Class = defaultValue!!::class.java + override val type: Class = defaultValue!!::class.java, ) : Item() { fun get(c: Context): T = LauncherPrefs.get(c).get(this) @@ -406,7 +439,7 @@ data class ContextualItem( override val isBackedUp: Boolean, private val defaultSupplier: (c: Context) -> T, override val encryptionType: EncryptionType, - override val type: Class + override val type: Class, ) : Item() { private var default: T? = null diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java index fdb37f0dcd..b3bcada148 100644 --- a/src/com/android/launcher3/states/RotationHelper.java +++ b/src/com/android/launcher3/states/RotationHelper.java @@ -26,8 +26,6 @@ import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH; import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Handler; import android.os.Message; @@ -36,13 +34,14 @@ import androidx.annotation.WorkerThread; import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.LauncherPrefChangeListener; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.util.DisplayController; /** * Utility class to manage launcher rotation */ -public class RotationHelper implements OnSharedPreferenceChangeListener, +public class RotationHelper implements LauncherPrefChangeListener, DeviceProfile.OnDeviceProfileChangeListener, DisplayController.DisplayInfoChangeListener { @@ -112,7 +111,7 @@ public class RotationHelper implements OnSharedPreferenceChangeListener, } @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { + public void onPrefChanged(String s) { if (mDestroyed || mIgnoreAutoRotateSettings) return; boolean wasRotationEnabled = mHomeRotationEnabled; mHomeRotationEnabled = LauncherPrefs.get(mActivity).get(ALLOW_ROTATION); diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java index c59cc81c47..0b45118e82 100644 --- a/src/com/android/launcher3/util/DisplayController.java +++ b/src/com/android/launcher3/util/DisplayController.java @@ -35,7 +35,6 @@ import android.annotation.SuppressLint; import android.content.ComponentCallbacks; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; @@ -51,6 +50,7 @@ import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; import com.android.launcher3.InvariantDeviceProfile.DeviceType; +import com.android.launcher3.LauncherPrefChangeListener; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.Utilities; import com.android.launcher3.logging.FileLog; @@ -116,8 +116,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { private Info mInfo; private boolean mDestroyed = false; - private SharedPreferences.OnSharedPreferenceChangeListener - mTaskbarPinningPreferenceChangeListener; + private LauncherPrefChangeListener mTaskbarPinningPreferenceChangeListener; @VisibleForTesting protected DisplayController(Context context) { @@ -142,19 +141,18 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { } private void attachTaskbarPinningSharedPreferenceChangeListener(Context context) { - mTaskbarPinningPreferenceChangeListener = - (sharedPreferences, key) -> { - LauncherPrefs prefs = LauncherPrefs.get(mContext); - boolean isTaskbarPinningChanged = TASKBAR_PINNING_KEY.equals(key) - && mInfo.mIsTaskbarPinned != prefs.get(TASKBAR_PINNING); - boolean isTaskbarPinningDesktopModeChanged = - TASKBAR_PINNING_DESKTOP_MODE_KEY.equals(key) - && mInfo.mIsTaskbarPinnedInDesktopMode != prefs.get( - TASKBAR_PINNING_IN_DESKTOP_MODE); - if (isTaskbarPinningChanged || isTaskbarPinningDesktopModeChanged) { - notifyConfigChange(); - } - }; + mTaskbarPinningPreferenceChangeListener = key -> { + LauncherPrefs prefs = LauncherPrefs.get(mContext); + boolean isTaskbarPinningChanged = TASKBAR_PINNING_KEY.equals(key) + && mInfo.mIsTaskbarPinned != prefs.get(TASKBAR_PINNING); + boolean isTaskbarPinningDesktopModeChanged = + TASKBAR_PINNING_DESKTOP_MODE_KEY.equals(key) + && mInfo.mIsTaskbarPinnedInDesktopMode != prefs.get( + TASKBAR_PINNING_IN_DESKTOP_MODE); + if (isTaskbarPinningChanged || isTaskbarPinningDesktopModeChanged) { + notifyConfigChange(); + } + }; LauncherPrefs.get(context).addListener( mTaskbarPinningPreferenceChangeListener, TASKBAR_PINNING); diff --git a/tests/multivalentTests/src/com/android/launcher3/AppWidgetsRestoredReceiverTest.kt b/tests/multivalentTests/src/com/android/launcher3/AppWidgetsRestoredReceiverTest.kt index 21abab4d49..0e06051adf 100644 --- a/tests/multivalentTests/src/com/android/launcher3/AppWidgetsRestoredReceiverTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/AppWidgetsRestoredReceiverTest.kt @@ -29,7 +29,7 @@ class AppWidgetsRestoredReceiverTest { @Before fun setup() { - launcherPrefs = LauncherPrefs(DeviceHelpers.context) + launcherPrefs = LauncherPrefs.get(DeviceHelpers.context) receiverUnderTest = AppWidgetsRestoredReceiver() } diff --git a/tests/multivalentTests/src/com/android/launcher3/LauncherPrefsTest.kt b/tests/multivalentTests/src/com/android/launcher3/LauncherPrefsTest.kt index b81309506a..4aeef2e671 100644 --- a/tests/multivalentTests/src/com/android/launcher3/LauncherPrefsTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/LauncherPrefsTest.kt @@ -17,7 +17,6 @@ package com.android.launcher3 import android.content.Context import android.content.SharedPreferences -import android.content.SharedPreferences.OnSharedPreferenceChangeListener import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry @@ -63,7 +62,7 @@ class LauncherPrefsTest { @Test fun addListener_listeningForStringItemUpdates_isCorrectlyNotifiedOfUpdates() { val latch = CountDownLatch(1) - val listener = OnSharedPreferenceChangeListener { _, _ -> latch.countDown() } + val listener = LauncherPrefChangeListener { latch.countDown() } with(launcherPrefs) { putSync(TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue)) @@ -78,7 +77,7 @@ class LauncherPrefsTest { @Test fun removeListener_previouslyListeningForStringItemUpdates_isNoLongerNotifiedOfUpdates() { val latch = CountDownLatch(1) - val listener = OnSharedPreferenceChangeListener { _, _ -> latch.countDown() } + val listener = LauncherPrefChangeListener { latch.countDown() } with(launcherPrefs) { addListener(listener, TEST_STRING_ITEM) @@ -94,14 +93,14 @@ class LauncherPrefsTest { @Test fun addListenerAndRemoveListener_forMultipleItems_bothWorkProperly() { var latch = CountDownLatch(3) - val listener = OnSharedPreferenceChangeListener { _, _ -> latch.countDown() } + val listener = LauncherPrefChangeListener { latch.countDown() } with(launcherPrefs) { addListener(listener, TEST_INT_ITEM, TEST_STRING_ITEM, TEST_BOOLEAN_ITEM) putSync( TEST_INT_ITEM.to(TEST_INT_ITEM.defaultValue + 123), TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue + "abc"), - TEST_BOOLEAN_ITEM.to(!TEST_BOOLEAN_ITEM.defaultValue) + TEST_BOOLEAN_ITEM.to(!TEST_BOOLEAN_ITEM.defaultValue), ) assertThat(latch.await(WAIT_TIME_IN_SECONDS, TimeUnit.SECONDS)).isTrue() @@ -110,7 +109,7 @@ class LauncherPrefsTest { putSync( TEST_INT_ITEM.to(TEST_INT_ITEM.defaultValue), TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue), - TEST_BOOLEAN_ITEM.to(TEST_BOOLEAN_ITEM.defaultValue) + TEST_BOOLEAN_ITEM.to(TEST_BOOLEAN_ITEM.defaultValue), ) remove(TEST_INT_ITEM, TEST_STRING_ITEM, TEST_BOOLEAN_ITEM) @@ -150,7 +149,7 @@ class LauncherPrefsTest { putSync( TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue), TEST_INT_ITEM.to(TEST_INT_ITEM.defaultValue), - TEST_BOOLEAN_ITEM.to(TEST_BOOLEAN_ITEM.defaultValue) + TEST_BOOLEAN_ITEM.to(TEST_BOOLEAN_ITEM.defaultValue), ) assertThat(has(TEST_BOOLEAN_ITEM, TEST_INT_ITEM, TEST_STRING_ITEM)).isTrue() remove(TEST_STRING_ITEM, TEST_INT_ITEM, TEST_BOOLEAN_ITEM) @@ -191,7 +190,7 @@ class LauncherPrefsTest { LauncherPrefs.backedUpItem( TEST_PREF_KEY, TEST_DEFAULT_VALUE, - EncryptionType.DEVICE_PROTECTED + EncryptionType.DEVICE_PROTECTED, ) val bootAwarePrefs: SharedPreferences = @@ -212,7 +211,7 @@ class LauncherPrefsTest { LauncherPrefs.backedUpItem( TEST_PREF_KEY, TEST_DEFAULT_VALUE, - EncryptionType.DEVICE_PROTECTED + EncryptionType.DEVICE_PROTECTED, ) val bootAwarePrefs: SharedPreferences = diff --git a/tests/multivalentTests/src/com/android/launcher3/provider/RestoreDbTaskTest.java b/tests/multivalentTests/src/com/android/launcher3/provider/RestoreDbTaskTest.java index b3675a6e0c..d0c168a8d1 100644 --- a/tests/multivalentTests/src/com/android/launcher3/provider/RestoreDbTaskTest.java +++ b/tests/multivalentTests/src/com/android/launcher3/provider/RestoreDbTaskTest.java @@ -101,7 +101,7 @@ public class RestoreDbTaskTest { mMockController = Mockito.mock(ModelDbController.class); mMockDb = mock(SQLiteDatabase.class); mMockCursor = mock(Cursor.class); - mPrefs = new LauncherPrefs(mContext); + mPrefs = LauncherPrefs.get(mContext); mMockRestoreEventLogger = mock(LauncherRestoreEventLogger.class); }