Loading packages/SystemUI/src/com/android/systemui/topwindoweffects/TopLevelWindowEffects.kt +8 −10 Original line number Diff line number Diff line Loading @@ -26,11 +26,11 @@ import androidx.annotation.VisibleForTesting import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.topwindoweffects.domain.interactor.SqueezeEffectInteractor import com.android.systemui.topwindoweffects.qualifiers.TopLevelWindowEffectsThread import com.android.systemui.topwindoweffects.ui.compose.EffectsWindowRoot import com.android.systemui.topwindoweffects.ui.viewmodel.SqueezeEffectViewModel import com.android.wm.shell.appzoomout.AppZoomOut Loading @@ -49,7 +49,7 @@ class TopLevelWindowEffects constructor( @Application private val context: Context, @Main private val mainDispatcher: CoroutineDispatcher, @Background private val topLevelWindowEffectsScope: CoroutineScope, @TopLevelWindowEffectsThread private val topLevelWindowEffectsScope: CoroutineScope, private val windowManager: WindowManager, private val squeezeEffectInteractor: SqueezeEffectInteractor, private val keyEventInteractor: KeyEventInteractor, Loading Loading @@ -96,24 +96,22 @@ constructor( bottomRoundedCornerResourceId = bottomRoundedCornerId, physicalPixelDisplaySizeRatio = physicalPixelDisplaySizeRatio, onEffectFinished = { runOnMainThread { if (root?.isAttachedToWindow == true) { windowManager.removeView(root) root = null } runOnMainThread { notificationShadeWindowController.setRequestTopUi(false, TAG) } }, appZoomOutOptional = appZoomOutOptional, ) root?.let { rootView -> runOnMainThread { notificationShadeWindowController.setRequestTopUi(true, TAG) runOnMainThread { notificationShadeWindowController.setRequestTopUi(true, TAG) } windowManager.addView(rootView, getWindowManagerLayoutParams()) } } } } private suspend fun runOnMainThread(block: () -> Unit) { withContext(mainDispatcher) { block() } Loading packages/SystemUI/src/com/android/systemui/topwindoweffects/qualifiers/TopLevelWindowEffectsThread.kt 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.topwindoweffects.qualifiers import javax.inject.Qualifier @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class TopLevelWindowEffectsThread packages/SystemUI/src/com/android/systemui/topwindoweffects/ui/compose/EffectsWindowRoot.kt +1 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ class EffectsWindowRoot( ) : AbstractComposeView(context) { override fun onAttachedToWindow() { ComposeInitializer.onAttachedToWindow(this) ComposeInitializer.onAttachedToWindow(this, true) super.onAttachedToWindow() } Loading packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.kt +30 −6 Original line number Diff line number Diff line Loading @@ -28,11 +28,14 @@ import com.android.systemui.dagger.qualifiers.BroadcastRunning import com.android.systemui.dagger.qualifiers.LongRunning import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.NotifInflation import com.android.systemui.topwindoweffects.qualifiers.TopLevelWindowEffectsThread import dagger.Module import dagger.Provides import java.util.concurrent.Executor import javax.inject.Named import javax.inject.Qualifier import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.asCoroutineDispatcher @Qualifier @MustBeDocumented Loading @@ -55,6 +58,7 @@ object SysUIConcurrencyModule { /** * Choreographer instance for the main thread. * * TODO(b/395887935): Lets move this to @Main and provide thread-local references */ @Provides Loading Loading @@ -85,7 +89,7 @@ object SysUIConcurrencyModule { .getLooper() .setSlowLogThresholdMs( BROADCAST_SLOW_DISPATCH_THRESHOLD, BROADCAST_SLOW_DELIVERY_THRESHOLD BROADCAST_SLOW_DELIVERY_THRESHOLD, ) return thread.getLooper() } Loading Loading @@ -113,7 +117,7 @@ object SysUIConcurrencyModule { val looper = thread.getLooper() looper.setSlowLogThresholdMs( NOTIFICATION_INFLATION_SLOW_DISPATCH_THRESHOLD, NOTIFICATION_INFLATION_SLOW_DELIVERY_THRESHOLD NOTIFICATION_INFLATION_SLOW_DELIVERY_THRESHOLD, ) return looper } Loading @@ -124,7 +128,7 @@ object SysUIConcurrencyModule { fun provideBackPanelUiThreadContext( @Main mainLooper: Looper, @Main mainHandler: Handler, @Main mainExecutor: Executor @Main mainExecutor: Executor, ): UiThreadContext { return if (Flags.edgeBackGestureHandlerThread()) { val thread = Loading @@ -132,25 +136,45 @@ object SysUIConcurrencyModule { start() looper.setSlowLogThresholdMs( LONG_SLOW_DISPATCH_THRESHOLD, LONG_SLOW_DELIVERY_THRESHOLD LONG_SLOW_DELIVERY_THRESHOLD, ) } UiThreadContext( thread.looper, thread.threadHandler, thread.threadExecutor, thread.threadHandler.runWithScissors { Choreographer.getInstance() } thread.threadHandler.runWithScissors { Choreographer.getInstance() }, ) } else { UiThreadContext( mainLooper, mainHandler, mainExecutor, mainHandler.runWithScissors { Choreographer.getInstance() } mainHandler.runWithScissors { Choreographer.getInstance() }, ) } } @Provides @SysUISingleton @TopLevelWindowEffectsThread fun provideTopLevelWindowEffectLooper(): Looper { val thread = HandlerThread("TopLevelWindowEffectsThread", Process.THREAD_PRIORITY_DISPLAY) thread.start() thread.looper.setSlowLogThresholdMs( LONG_SLOW_DISPATCH_THRESHOLD, LONG_SLOW_DELIVERY_THRESHOLD, ) return thread.looper } @Provides @SysUISingleton @TopLevelWindowEffectsThread fun provideTopLevelWindowEffectsScope( @TopLevelWindowEffectsThread looper: Looper ): CoroutineScope = CoroutineScope(ExecutorImpl(looper).asCoroutineDispatcher()) /** * Background Handler. * Loading Loading
packages/SystemUI/src/com/android/systemui/topwindoweffects/TopLevelWindowEffects.kt +8 −10 Original line number Diff line number Diff line Loading @@ -26,11 +26,11 @@ import androidx.annotation.VisibleForTesting import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.topwindoweffects.domain.interactor.SqueezeEffectInteractor import com.android.systemui.topwindoweffects.qualifiers.TopLevelWindowEffectsThread import com.android.systemui.topwindoweffects.ui.compose.EffectsWindowRoot import com.android.systemui.topwindoweffects.ui.viewmodel.SqueezeEffectViewModel import com.android.wm.shell.appzoomout.AppZoomOut Loading @@ -49,7 +49,7 @@ class TopLevelWindowEffects constructor( @Application private val context: Context, @Main private val mainDispatcher: CoroutineDispatcher, @Background private val topLevelWindowEffectsScope: CoroutineScope, @TopLevelWindowEffectsThread private val topLevelWindowEffectsScope: CoroutineScope, private val windowManager: WindowManager, private val squeezeEffectInteractor: SqueezeEffectInteractor, private val keyEventInteractor: KeyEventInteractor, Loading Loading @@ -96,24 +96,22 @@ constructor( bottomRoundedCornerResourceId = bottomRoundedCornerId, physicalPixelDisplaySizeRatio = physicalPixelDisplaySizeRatio, onEffectFinished = { runOnMainThread { if (root?.isAttachedToWindow == true) { windowManager.removeView(root) root = null } runOnMainThread { notificationShadeWindowController.setRequestTopUi(false, TAG) } }, appZoomOutOptional = appZoomOutOptional, ) root?.let { rootView -> runOnMainThread { notificationShadeWindowController.setRequestTopUi(true, TAG) runOnMainThread { notificationShadeWindowController.setRequestTopUi(true, TAG) } windowManager.addView(rootView, getWindowManagerLayoutParams()) } } } } private suspend fun runOnMainThread(block: () -> Unit) { withContext(mainDispatcher) { block() } Loading
packages/SystemUI/src/com/android/systemui/topwindoweffects/qualifiers/TopLevelWindowEffectsThread.kt 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.topwindoweffects.qualifiers import javax.inject.Qualifier @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class TopLevelWindowEffectsThread
packages/SystemUI/src/com/android/systemui/topwindoweffects/ui/compose/EffectsWindowRoot.kt +1 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ class EffectsWindowRoot( ) : AbstractComposeView(context) { override fun onAttachedToWindow() { ComposeInitializer.onAttachedToWindow(this) ComposeInitializer.onAttachedToWindow(this, true) super.onAttachedToWindow() } Loading
packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.kt +30 −6 Original line number Diff line number Diff line Loading @@ -28,11 +28,14 @@ import com.android.systemui.dagger.qualifiers.BroadcastRunning import com.android.systemui.dagger.qualifiers.LongRunning import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.NotifInflation import com.android.systemui.topwindoweffects.qualifiers.TopLevelWindowEffectsThread import dagger.Module import dagger.Provides import java.util.concurrent.Executor import javax.inject.Named import javax.inject.Qualifier import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.asCoroutineDispatcher @Qualifier @MustBeDocumented Loading @@ -55,6 +58,7 @@ object SysUIConcurrencyModule { /** * Choreographer instance for the main thread. * * TODO(b/395887935): Lets move this to @Main and provide thread-local references */ @Provides Loading Loading @@ -85,7 +89,7 @@ object SysUIConcurrencyModule { .getLooper() .setSlowLogThresholdMs( BROADCAST_SLOW_DISPATCH_THRESHOLD, BROADCAST_SLOW_DELIVERY_THRESHOLD BROADCAST_SLOW_DELIVERY_THRESHOLD, ) return thread.getLooper() } Loading Loading @@ -113,7 +117,7 @@ object SysUIConcurrencyModule { val looper = thread.getLooper() looper.setSlowLogThresholdMs( NOTIFICATION_INFLATION_SLOW_DISPATCH_THRESHOLD, NOTIFICATION_INFLATION_SLOW_DELIVERY_THRESHOLD NOTIFICATION_INFLATION_SLOW_DELIVERY_THRESHOLD, ) return looper } Loading @@ -124,7 +128,7 @@ object SysUIConcurrencyModule { fun provideBackPanelUiThreadContext( @Main mainLooper: Looper, @Main mainHandler: Handler, @Main mainExecutor: Executor @Main mainExecutor: Executor, ): UiThreadContext { return if (Flags.edgeBackGestureHandlerThread()) { val thread = Loading @@ -132,25 +136,45 @@ object SysUIConcurrencyModule { start() looper.setSlowLogThresholdMs( LONG_SLOW_DISPATCH_THRESHOLD, LONG_SLOW_DELIVERY_THRESHOLD LONG_SLOW_DELIVERY_THRESHOLD, ) } UiThreadContext( thread.looper, thread.threadHandler, thread.threadExecutor, thread.threadHandler.runWithScissors { Choreographer.getInstance() } thread.threadHandler.runWithScissors { Choreographer.getInstance() }, ) } else { UiThreadContext( mainLooper, mainHandler, mainExecutor, mainHandler.runWithScissors { Choreographer.getInstance() } mainHandler.runWithScissors { Choreographer.getInstance() }, ) } } @Provides @SysUISingleton @TopLevelWindowEffectsThread fun provideTopLevelWindowEffectLooper(): Looper { val thread = HandlerThread("TopLevelWindowEffectsThread", Process.THREAD_PRIORITY_DISPLAY) thread.start() thread.looper.setSlowLogThresholdMs( LONG_SLOW_DISPATCH_THRESHOLD, LONG_SLOW_DELIVERY_THRESHOLD, ) return thread.looper } @Provides @SysUISingleton @TopLevelWindowEffectsThread fun provideTopLevelWindowEffectsScope( @TopLevelWindowEffectsThread looper: Looper ): CoroutineScope = CoroutineScope(ExecutorImpl(looper).asCoroutineDispatcher()) /** * Background Handler. * Loading