Loading packages/SystemUI/customization/src/com/android/systemui/util/ThreadAssert.kt 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * 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.systemui.util /** Injectable helper providing thread assertions. */ class ThreadAssert() { fun isMainThread() = Assert.isMainThread() fun isNotMainThread() = Assert.isNotMainThread() } packages/SystemUI/res/values/ids.xml +1 −0 Original line number Diff line number Diff line Loading @@ -228,6 +228,7 @@ <item type="id" name="ambient_indication_container" /> <item type="id" name="status_view_media_container" /> <item type="id" name="smart_space_barrier_bottom" /> <item type="id" name="small_clock_guideline_top" /> <item type="id" name="weather_clock_date_and_icons_barrier_bottom" /> <!-- Privacy dialog --> Loading packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt +2 −1 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ constructor( private val keyguardClockViewModel: KeyguardClockViewModel, private val lockscreenContentViewModel: LockscreenContentViewModel, private val lockscreenSceneBlueprintsLazy: Lazy<Set<LockscreenSceneBlueprint>>, private val keyguardBlueprintViewBinder: KeyguardBlueprintViewBinder, ) : CoreStartable { private var rootViewHandle: DisposableHandle? = null Loading Loading @@ -143,7 +144,7 @@ constructor( cs.connect(composeView.id, BOTTOM, PARENT_ID, BOTTOM) keyguardRootView.addView(composeView) } else { KeyguardBlueprintViewBinder.bind( keyguardBlueprintViewBinder.bind( keyguardRootView, keyguardBlueprintViewModel, keyguardClockViewModel, Loading packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +8 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.user.domain.interactor.SelectedUserInteractor; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.ThreadAssert; import com.android.systemui.util.kotlin.JavaAdapter; import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.settings.SystemSettings; Loading Loading @@ -223,6 +224,13 @@ public interface KeyguardModule { return new KeyguardQuickAffordancesMetricsLoggerImpl(); } /** */ @Provides @SysUISingleton static ThreadAssert providesThreadAssert() { return new ThreadAssert(); } /** Binds {@link KeyguardUpdateMonitor} as a {@link CoreStartable}. */ @Binds @IntoMap Loading packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt +33 −12 Original line number Diff line number Diff line Loading @@ -17,14 +17,16 @@ package com.android.systemui.keyguard.data.repository import android.os.Handler import android.util.Log import com.android.systemui.common.ui.data.repository.ConfigurationRepository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.shared.model.KeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT import com.android.systemui.keyguard.ui.view.layout.blueprints.KeyguardBlueprintModule import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransitionType import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransitionType.DefaultTransition import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config import com.android.systemui.util.ThreadAssert import java.io.PrintWriter import java.util.TreeMap import javax.inject.Inject Loading @@ -49,16 +51,17 @@ class KeyguardBlueprintRepository constructor( configurationRepository: ConfigurationRepository, blueprints: Set<@JvmSuppressWildcards KeyguardBlueprint>, @Main val handler: Handler, val assert: ThreadAssert, ) { // This is TreeMap so that we can order the blueprints and assign numerical values to the // blueprints in the adb tool. private val blueprintIdMap: TreeMap<String, KeyguardBlueprint> = TreeMap<String, KeyguardBlueprint>().apply { putAll(blueprints.associateBy { it.id }) } val blueprint: MutableStateFlow<KeyguardBlueprint> = MutableStateFlow(blueprintIdMap[DEFAULT]!!) val refreshBluePrint: MutableSharedFlow<Unit> = MutableSharedFlow(extraBufferCapacity = 1) val refreshBlueprintTransition: MutableSharedFlow<IntraBlueprintTransitionType> = MutableSharedFlow(extraBufferCapacity = 1) val refreshTransition = MutableSharedFlow<Config>(extraBufferCapacity = 1) val configurationChange: Flow<Unit> = configurationRepository.onAnyConfigurationChange private var targetTransitionConfig: Config? = null /** * Emits the blueprint value to the collectors. Loading Loading @@ -105,14 +108,32 @@ constructor( blueprint?.let { this.blueprint.value = it } } /** Re-emits the last emitted blueprint value if possible. */ fun refreshBlueprint() { refreshBlueprintWithTransition(DefaultTransition) /** * Re-emits the last emitted blueprint value if possible. This is delayed until next frame to * dedupe requests and determine the correct transition to execute. */ fun refreshBlueprint(config: Config = Config.DEFAULT) { fun scheduleCallback() { // We use a handler here instead of a CoroutineDipsatcher because the one provided by // @Main CoroutineDispatcher is currently Dispatchers.Main.immediate, which doesn't // delay the callback, and instead runs it imemdiately. handler.post { assert.isMainThread() targetTransitionConfig?.let { val success = refreshTransition.tryEmit(it) if (!success) { Log.e(TAG, "refreshBlueprint: Failed to emit blueprint refresh: $it") } } targetTransitionConfig = null } } fun refreshBlueprintWithTransition(type: IntraBlueprintTransitionType = DefaultTransition) { refreshBluePrint.tryEmit(Unit) refreshBlueprintTransition.tryEmit(type) assert.isMainThread() if ((targetTransitionConfig?.type?.priority ?: Int.MIN_VALUE) < config.type.priority) { if (targetTransitionConfig == null) scheduleCallback() targetTransitionConfig = config } } /** Prints all available blueprints to the PrintWriter. */ Loading Loading
packages/SystemUI/customization/src/com/android/systemui/util/ThreadAssert.kt 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * 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.systemui.util /** Injectable helper providing thread assertions. */ class ThreadAssert() { fun isMainThread() = Assert.isMainThread() fun isNotMainThread() = Assert.isNotMainThread() }
packages/SystemUI/res/values/ids.xml +1 −0 Original line number Diff line number Diff line Loading @@ -228,6 +228,7 @@ <item type="id" name="ambient_indication_container" /> <item type="id" name="status_view_media_container" /> <item type="id" name="smart_space_barrier_bottom" /> <item type="id" name="small_clock_guideline_top" /> <item type="id" name="weather_clock_date_and_icons_barrier_bottom" /> <!-- Privacy dialog --> Loading
packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt +2 −1 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ constructor( private val keyguardClockViewModel: KeyguardClockViewModel, private val lockscreenContentViewModel: LockscreenContentViewModel, private val lockscreenSceneBlueprintsLazy: Lazy<Set<LockscreenSceneBlueprint>>, private val keyguardBlueprintViewBinder: KeyguardBlueprintViewBinder, ) : CoreStartable { private var rootViewHandle: DisposableHandle? = null Loading Loading @@ -143,7 +144,7 @@ constructor( cs.connect(composeView.id, BOTTOM, PARENT_ID, BOTTOM) keyguardRootView.addView(composeView) } else { KeyguardBlueprintViewBinder.bind( keyguardBlueprintViewBinder.bind( keyguardRootView, keyguardBlueprintViewModel, keyguardClockViewModel, Loading
packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +8 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.user.domain.interactor.SelectedUserInteractor; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.ThreadAssert; import com.android.systemui.util.kotlin.JavaAdapter; import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.settings.SystemSettings; Loading Loading @@ -223,6 +224,13 @@ public interface KeyguardModule { return new KeyguardQuickAffordancesMetricsLoggerImpl(); } /** */ @Provides @SysUISingleton static ThreadAssert providesThreadAssert() { return new ThreadAssert(); } /** Binds {@link KeyguardUpdateMonitor} as a {@link CoreStartable}. */ @Binds @IntoMap Loading
packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt +33 −12 Original line number Diff line number Diff line Loading @@ -17,14 +17,16 @@ package com.android.systemui.keyguard.data.repository import android.os.Handler import android.util.Log import com.android.systemui.common.ui.data.repository.ConfigurationRepository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.shared.model.KeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT import com.android.systemui.keyguard.ui.view.layout.blueprints.KeyguardBlueprintModule import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransitionType import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransitionType.DefaultTransition import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config import com.android.systemui.util.ThreadAssert import java.io.PrintWriter import java.util.TreeMap import javax.inject.Inject Loading @@ -49,16 +51,17 @@ class KeyguardBlueprintRepository constructor( configurationRepository: ConfigurationRepository, blueprints: Set<@JvmSuppressWildcards KeyguardBlueprint>, @Main val handler: Handler, val assert: ThreadAssert, ) { // This is TreeMap so that we can order the blueprints and assign numerical values to the // blueprints in the adb tool. private val blueprintIdMap: TreeMap<String, KeyguardBlueprint> = TreeMap<String, KeyguardBlueprint>().apply { putAll(blueprints.associateBy { it.id }) } val blueprint: MutableStateFlow<KeyguardBlueprint> = MutableStateFlow(blueprintIdMap[DEFAULT]!!) val refreshBluePrint: MutableSharedFlow<Unit> = MutableSharedFlow(extraBufferCapacity = 1) val refreshBlueprintTransition: MutableSharedFlow<IntraBlueprintTransitionType> = MutableSharedFlow(extraBufferCapacity = 1) val refreshTransition = MutableSharedFlow<Config>(extraBufferCapacity = 1) val configurationChange: Flow<Unit> = configurationRepository.onAnyConfigurationChange private var targetTransitionConfig: Config? = null /** * Emits the blueprint value to the collectors. Loading Loading @@ -105,14 +108,32 @@ constructor( blueprint?.let { this.blueprint.value = it } } /** Re-emits the last emitted blueprint value if possible. */ fun refreshBlueprint() { refreshBlueprintWithTransition(DefaultTransition) /** * Re-emits the last emitted blueprint value if possible. This is delayed until next frame to * dedupe requests and determine the correct transition to execute. */ fun refreshBlueprint(config: Config = Config.DEFAULT) { fun scheduleCallback() { // We use a handler here instead of a CoroutineDipsatcher because the one provided by // @Main CoroutineDispatcher is currently Dispatchers.Main.immediate, which doesn't // delay the callback, and instead runs it imemdiately. handler.post { assert.isMainThread() targetTransitionConfig?.let { val success = refreshTransition.tryEmit(it) if (!success) { Log.e(TAG, "refreshBlueprint: Failed to emit blueprint refresh: $it") } } targetTransitionConfig = null } } fun refreshBlueprintWithTransition(type: IntraBlueprintTransitionType = DefaultTransition) { refreshBluePrint.tryEmit(Unit) refreshBlueprintTransition.tryEmit(type) assert.isMainThread() if ((targetTransitionConfig?.type?.priority ?: Int.MIN_VALUE) < config.type.priority) { if (targetTransitionConfig == null) scheduleCallback() targetTransitionConfig = config } } /** Prints all available blueprints to the PrintWriter. */ Loading