Fixed leak and no clock carousel (1/3)
Previously, ClockRegistry is bond to activity lifecycle and it's not stable with unregister call followed by register in a short period of time.
Remove the register/unregister ClockRegistry from ClockRegistryProvider (used in activity), and move to app level singleton. Register ClockRegistry listeners when app started and cleaned up when app ended.
Bug: 285348630
Bug: 285321790
Test: resume/destroy WPP then launch LS tab
Test: rotate foldable inner screen
Test: run profiler check no related leaks
Change-Id: I5b9d8eba17b3164a3da5f81058c5c6c90f6a2272
diff --git a/src/com/android/customization/module/CustomizationInjector.kt b/src/com/android/customization/module/CustomizationInjector.kt
index b3400bc..8b0d90f 100644
--- a/src/com/android/customization/module/CustomizationInjector.kt
+++ b/src/com/android/customization/module/CustomizationInjector.kt
@@ -18,7 +18,6 @@
import android.content.Context
import androidx.activity.ComponentActivity
import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.LifecycleOwner
import com.android.customization.model.theme.OverlayManagerCompat
import com.android.customization.model.theme.ThemeBundleProvider
import com.android.customization.model.theme.ThemeManager
@@ -48,13 +47,12 @@
context: Context,
): KeyguardQuickAffordancePickerInteractor
- fun getClockRegistry(context: Context, lifecycleOwner: LifecycleOwner): ClockRegistry
+ fun getClockRegistry(context: Context): ClockRegistry?
fun getClockPickerInteractor(context: Context): ClockPickerInteractor
fun getClockSectionViewModel(
context: Context,
- lifecycleOwner: LifecycleOwner
): ClockSectionViewModel
fun getColorPickerInteractor(
@@ -77,6 +75,5 @@
context: Context,
wallpaperColorsViewModel: WallpaperColorsViewModel,
clockViewFactory: ClockViewFactory,
- lifecycleOwner: LifecycleOwner,
): ClockSettingsViewModel.Factory
}
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index 6c747d7..4988c6b 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -196,23 +196,19 @@
override fun getSnapshotRestorers(
context: Context,
- lifecycleOwner: LifecycleOwner
): Map<Int, SnapshotRestorer> {
- return super<WallpaperPicker2Injector>.getSnapshotRestorers(context, lifecycleOwner)
- .toMutableMap()
- .apply {
- this[KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER] =
- getKeyguardQuickAffordanceSnapshotRestorer(context)
- this[KEY_WALLPAPER_SNAPSHOT_RESTORER] = getWallpaperSnapshotRestorer(context)
- this[KEY_NOTIFICATIONS_SNAPSHOT_RESTORER] =
- getNotificationsSnapshotRestorer(context)
- this[KEY_DARK_MODE_SNAPSHOT_RESTORER] = getDarkModeSnapshotRestorer(context)
- this[KEY_THEMED_ICON_SNAPSHOT_RESTORER] = getThemedIconSnapshotRestorer(context)
- this[KEY_APP_GRID_SNAPSHOT_RESTORER] = getGridSnapshotRestorer(context)
- this[KEY_COLOR_PICKER_SNAPSHOT_RESTORER] =
- getColorPickerSnapshotRestorer(context, getWallpaperColorsViewModel())
- this[KEY_CLOCKS_SNAPSHOT_RESTORER] = getClockPickerSnapshotRestorer(context)
- }
+ return super<WallpaperPicker2Injector>.getSnapshotRestorers(context).toMutableMap().apply {
+ this[KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER] =
+ getKeyguardQuickAffordanceSnapshotRestorer(context)
+ this[KEY_WALLPAPER_SNAPSHOT_RESTORER] = getWallpaperSnapshotRestorer(context)
+ this[KEY_NOTIFICATIONS_SNAPSHOT_RESTORER] = getNotificationsSnapshotRestorer(context)
+ this[KEY_DARK_MODE_SNAPSHOT_RESTORER] = getDarkModeSnapshotRestorer(context)
+ this[KEY_THEMED_ICON_SNAPSHOT_RESTORER] = getThemedIconSnapshotRestorer(context)
+ this[KEY_APP_GRID_SNAPSHOT_RESTORER] = getGridSnapshotRestorer(context)
+ this[KEY_COLOR_PICKER_SNAPSHOT_RESTORER] =
+ getColorPickerSnapshotRestorer(context, getWallpaperColorsViewModel())
+ this[KEY_CLOCKS_SNAPSHOT_RESTORER] = getClockPickerSnapshotRestorer(context)
+ }
}
override fun getCustomizationPreferences(context: Context): CustomizationPreferences {
@@ -347,7 +343,7 @@
.also { notificationsSnapshotRestorer = it }
}
- override fun getClockRegistry(context: Context, lifecycleOwner: LifecycleOwner): ClockRegistry {
+ override fun getClockRegistry(context: Context): ClockRegistry {
return (clockRegistryProvider
?: ClockRegistryProvider(
context = context.applicationContext,
@@ -356,7 +352,7 @@
backgroundDispatcher = Dispatchers.IO,
)
.also { clockRegistryProvider = it })
- .getForOwner(lifecycleOwner)
+ .get()
}
override fun getClockPickerInteractor(
@@ -367,9 +363,8 @@
?: ClockPickerInteractor(
repository =
ClockPickerRepositoryImpl(
- secureSettingsRepository = getSecureSettingsRepository(context),
- // TODO (b/285978251): remove second argument once b/285348630 is fixed
- registry = getClockRegistry(context, context as LifecycleOwner),
+ secureSettingsRepository = getSecureSettingsRepository(appContext),
+ registry = getClockRegistry(appContext),
scope = getApplicationCoroutineScope(),
mainDispatcher = Dispatchers.Main,
),
@@ -380,10 +375,12 @@
override fun getClockSectionViewModel(
context: Context,
- lifecycleOwner: LifecycleOwner
): ClockSectionViewModel {
return clockSectionViewModel
- ?: ClockSectionViewModel(context.applicationContext, getClockPickerInteractor(context))
+ ?: ClockSectionViewModel(
+ context.applicationContext,
+ getClockPickerInteractor(context.applicationContext)
+ )
.also { clockSectionViewModel = it }
}
@@ -404,10 +401,7 @@
ScreenSizeCalculator.getInstance()
.getScreenSize(activity.windowManager.defaultDisplay),
WallpaperManager.getInstance(activity.applicationContext),
- getClockRegistry(
- context = activity.applicationContext,
- lifecycleOwner = activity,
- ),
+ getClockRegistry(activity.applicationContext),
)
.also {
clockViewFactories[activityHashCode] = it
@@ -521,7 +515,6 @@
context: Context,
wallpaperColorsViewModel: WallpaperColorsViewModel,
clockViewFactory: ClockViewFactory,
- lifecycleOwner: LifecycleOwner,
): ClockSettingsViewModel.Factory {
return clockSettingsViewModelFactory
?: ClockSettingsViewModel.Factory(
diff --git a/src/com/android/customization/picker/clock/data/repository/ClockRegistryProvider.kt b/src/com/android/customization/picker/clock/data/repository/ClockRegistryProvider.kt
index 52c3c4e..652ffdd 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockRegistryProvider.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockRegistryProvider.kt
@@ -19,8 +19,6 @@
import android.content.ComponentName
import android.content.Context
import android.view.LayoutInflater
-import androidx.lifecycle.DefaultLifecycleObserver
-import androidx.lifecycle.LifecycleOwner
import com.android.systemui.plugins.Plugin
import com.android.systemui.plugins.PluginManager
import com.android.systemui.shared.clocks.ClockRegistry
@@ -45,50 +43,28 @@
private val mainDispatcher: CoroutineDispatcher,
private val backgroundDispatcher: CoroutineDispatcher,
) {
- private val lifecycleOwners = mutableSetOf<Int>()
- private val pluginManager: PluginManager by lazy { createPluginManager(context) }
private val clockRegistry: ClockRegistry by lazy {
ClockRegistry(
- context,
- pluginManager,
- coroutineScope,
- mainDispatcher,
- backgroundDispatcher,
- isEnabled = true,
- handleAllUsers = false,
- DefaultClockProvider(context, LayoutInflater.from(context), context.resources),
- keepAllLoaded = true,
- subTag = "Picker",
- )
- .apply { registerListeners() }
- }
-
- fun getForOwner(lifecycleOwner: LifecycleOwner): ClockRegistry {
- registerLifecycleOwner(lifecycleOwner)
- return clockRegistry
- }
-
- private fun registerLifecycleOwner(lifecycleOwner: LifecycleOwner) {
- lifecycleOwners.add(lifecycleOwner.hashCode())
-
- lifecycleOwner.lifecycle.addObserver(
- object : DefaultLifecycleObserver {
- override fun onDestroy(owner: LifecycleOwner) {
- super.onDestroy(owner)
- unregisterLifecycleOwner(owner)
- }
- }
+ context,
+ createPluginManager(context),
+ coroutineScope,
+ mainDispatcher,
+ backgroundDispatcher,
+ isEnabled = true,
+ handleAllUsers = false,
+ DefaultClockProvider(context, LayoutInflater.from(context), context.resources),
+ keepAllLoaded = true,
+ subTag = "Picker",
)
}
- private fun unregisterLifecycleOwner(lifecycleOwner: LifecycleOwner) {
- lifecycleOwners.remove(lifecycleOwner.hashCode())
-
- if (lifecycleOwners.isEmpty()) {
- clockRegistry.unregisterListeners()
- }
+ init {
+ // Listeners in ClockRegistry get cleaned up when app ended
+ clockRegistry.registerListeners()
}
+ fun get() = clockRegistry
+
private fun createPluginManager(context: Context): PluginManager {
val privilegedPlugins = listOf<String>()
val isDebugDevice = true
diff --git a/src/com/android/customization/picker/clock/ui/fragment/ClockCustomDemoFragment.kt b/src/com/android/customization/picker/clock/ui/fragment/ClockCustomDemoFragment.kt
index 6203e24..f138d6a 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockCustomDemoFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockCustomDemoFragment.kt
@@ -37,7 +37,6 @@
clockRegistry =
(InjectorProvider.getInjector() as ThemePickerInjector).getClockRegistry(
requireContext(),
- this
)
val listInUse = clockRegistry.getClocks().filter { "NOT_IN_USE" !in it.clockId }
diff --git a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
index d19b33c..e476d6a 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
@@ -123,7 +123,6 @@
context,
injector.getWallpaperColorsViewModel(),
injector.getClockViewFactory(activity),
- activity,
),
)
.get(),