Loading packages/SystemUI/customization/src/com/android/systemui/util/Assert.java +15 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,21 @@ public class Assert { } } /** * Asserts that the current thread is the same as the given thread, or that the current thread * is the test thread. * @param expected The looper we expected to be running on */ public static void isCurrentThread(Looper expected) { if (!expected.isCurrentThread() && (sTestThread == null || sTestThread != Thread.currentThread())) { throw new IllegalStateException("Called on wrong thread thread." + " wanted " + expected.getThread().getName() + " but instead got Thread.currentThread()=" + Thread.currentThread().getName()); } } public static void isNotMainThread() { if (sMainLooper.isCurrentThread() && (sTestThread == null || sTestThread == Thread.currentThread())) { Loading packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt +9 −9 Original line number Diff line number Diff line Loading @@ -36,11 +36,12 @@ import androidx.dynamicanimation.animation.DynamicAnimation import com.android.internal.jank.Cuj import com.android.internal.jank.InteractionJankMonitor import com.android.internal.util.LatencyTracker import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.NavigationEdgeBackPlugin import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.ViewController import com.android.systemui.util.concurrency.BackPanelUiThread import com.android.systemui.util.concurrency.UiThreadContext import com.android.systemui.util.time.SystemClock import java.io.PrintWriter import javax.inject.Inject Loading Loading @@ -84,11 +85,11 @@ internal constructor( context: Context, private val windowManager: WindowManager, private val viewConfiguration: ViewConfiguration, @Main private val mainHandler: Handler, private val mainHandler: Handler, private val systemClock: SystemClock, private val vibratorHelper: VibratorHelper, private val configurationController: ConfigurationController, private val latencyTracker: LatencyTracker, latencyTracker: LatencyTracker, private val interactionJankMonitor: InteractionJankMonitor, ) : ViewController<BackPanel>(BackPanel(context, latencyTracker)), NavigationEdgeBackPlugin { Loading @@ -103,7 +104,7 @@ internal constructor( constructor( private val windowManager: WindowManager, private val viewConfiguration: ViewConfiguration, @Main private val mainHandler: Handler, @BackPanelUiThread private val uiThreadContext: UiThreadContext, private val systemClock: SystemClock, private val vibratorHelper: VibratorHelper, private val configurationController: ConfigurationController, Loading @@ -112,20 +113,19 @@ internal constructor( ) { /** Construct a [BackPanelController]. */ fun create(context: Context): BackPanelController { val backPanelController = BackPanelController( uiThreadContext.isCurrentThread() return BackPanelController( context, windowManager, viewConfiguration, mainHandler, uiThreadContext.handler, systemClock, vibratorHelper, configurationController, latencyTracker, interactionJankMonitor ) backPanelController.init() return backPanelController .also { it.init() } } } Loading packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +64 −66 Original line number Diff line number Diff line Loading @@ -44,8 +44,6 @@ import android.graphics.Rect; import android.graphics.Region; import android.hardware.input.InputManager; import android.icu.text.SimpleDateFormat; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; Loading @@ -55,7 +53,6 @@ import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.Choreographer; import android.view.ISystemGestureExclusionListener; import android.view.IWindowManager; import android.view.InputDevice; Loading @@ -75,7 +72,6 @@ import androidx.annotation.DimenRes; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.policy.GestureNavigationSettingsObserver; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.FalsingManager; Loading @@ -94,7 +90,8 @@ import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.util.Assert; import com.android.systemui.util.concurrency.BackPanelUiThread; import com.android.systemui.util.concurrency.UiThreadContext; import com.android.wm.shell.back.BackAnimation; import com.android.wm.shell.desktopmode.DesktopMode; import com.android.wm.shell.pip.Pip; Loading Loading @@ -136,7 +133,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack public void onSystemGestureExclusionChanged(int displayId, Region systemGestureExclusion, Region unrestrictedOrNull) { if (displayId == mDisplayId) { mMainExecutor.execute(() -> { mUiThreadContext.getExecutor().execute(() -> { mExcludeRegion.set(systemGestureExclusion); mUnrestrictedExcludeRegion.set(unrestrictedOrNull != null ? unrestrictedOrNull : systemGestureExclusion); Loading Loading @@ -215,8 +212,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack private final Point mDisplaySize = new Point(); private final int mDisplayId; private final Executor mMainExecutor; private final Handler mMainHandler; private final UiThreadContext mUiThreadContext; private final Executor mBackgroundExecutor; private final Rect mPipExcludedBounds = new Rect(); Loading Loading @@ -411,8 +407,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack OverviewProxyService overviewProxyService, SysUiState sysUiState, PluginManager pluginManager, @Main Executor executor, @Main Handler handler, @BackPanelUiThread UiThreadContext uiThreadContext, @Background Executor backgroundExecutor, UserTracker userTracker, NavigationModeController navigationModeController, Loading @@ -428,8 +423,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack Provider<LightBarController> lightBarControllerProvider) { mContext = context; mDisplayId = context.getDisplayId(); mMainExecutor = executor; mMainHandler = handler; mUiThreadContext = uiThreadContext; mBackgroundExecutor = backgroundExecutor; mUserTracker = userTracker; mOverviewProxyService = overviewProxyService; Loading Loading @@ -478,7 +472,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack ViewConfiguration.getLongPressTimeout()); mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver( mMainHandler, mContext, this::onNavigationSettingsChanged); mUiThreadContext.getHandler(), mContext, this::onNavigationSettingsChanged); updateCurrentUserResources(); } Loading Loading @@ -564,13 +558,15 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mIsAttached = true; mOverviewProxyService.addCallback(mQuickSwitchListener); mSysUiState.addCallback(mSysUiStateCallback); mInputManager.registerInputDeviceListener(mInputDeviceListener, mMainHandler); mInputManager.registerInputDeviceListener( mInputDeviceListener, mUiThreadContext.getHandler()); int[] inputDevices = mInputManager.getInputDeviceIds(); for (int inputDeviceId : inputDevices) { mInputDeviceListener.onInputDeviceAdded(inputDeviceId); } updateIsEnabled(); mUserTracker.addCallback(mUserChangedCallback, mMainExecutor); mUserTracker.addCallback(mUserChangedCallback, mUiThreadContext.getExecutor()); } /** Loading Loading @@ -617,6 +613,10 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } private void updateIsEnabled() { mUiThreadContext.runWithScissors(this::updateIsEnabledInner); } private void updateIsEnabledInner() { try { Trace.beginSection("EdgeBackGestureHandler#updateIsEnabled"); Loading Loading @@ -661,12 +661,12 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack TaskStackChangeListeners.getInstance().registerTaskStackListener( mTaskStackListener); DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mMainExecutor::execute, mOnPropertiesChangedListener); mUiThreadContext.getExecutor()::execute, mOnPropertiesChangedListener); mPipOptional.ifPresent(pip -> pip.setOnIsInPipStateChangedListener( mOnIsInPipStateChangedListener)); mDesktopModeOptional.ifPresent( dm -> dm.addDesktopGestureExclusionRegionListener( mDesktopCornersChangedListener, mMainExecutor)); mDesktopCornersChangedListener, mUiThreadContext.getExecutor())); try { mWindowManagerService.registerSystemGestureExclusionListener( Loading @@ -677,8 +677,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack // Register input event receiver mInputMonitor = new InputMonitorCompat("edge-swipe", mDisplayId); mInputEventReceiver = mInputMonitor.getInputReceiver(Looper.getMainLooper(), Choreographer.getInstance(), this::onInputEvent); mInputEventReceiver = mInputMonitor.getInputReceiver(mUiThreadContext.getLooper(), mUiThreadContext.getChoreographer(), this::onInputEvent); // Add a nav bar panel window resetEdgeBackPlugin(); Loading Loading @@ -773,7 +773,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mUseMLModel = newState; if (mUseMLModel) { Assert.isMainThread(); mUiThreadContext.isCurrentThread(); if (mMLModelIsLoading) { Log.d(TAG, "Model tried to load while already loading."); return; Loading Loading @@ -804,12 +804,13 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } BackGestureTfClassifierProvider finalProvider = provider; Map<String, Integer> finalVocab = vocab; mMainExecutor.execute(() -> onMLModelLoadFinished(finalProvider, finalVocab, threshold)); mUiThreadContext.getExecutor().execute( () -> onMLModelLoadFinished(finalProvider, finalVocab, threshold)); } private void onMLModelLoadFinished(BackGestureTfClassifierProvider provider, Map<String, Integer> vocab, float threshold) { Assert.isMainThread(); mUiThreadContext.isCurrentThread(); mMLModelIsLoading = false; if (!mUseMLModel) { // This can happen if the user disables Gesture Nav while the model is loading. Loading Loading @@ -1291,7 +1292,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack updateBackAnimationThresholds(); if (mLightBarControllerProvider.get() != null) { mBackAnimation.setStatusBarCustomizer((appearance) -> { mMainExecutor.execute(() -> mUiThreadContext.getExecutor().execute(() -> mLightBarControllerProvider.get() .customizeStatusBarAppearance(appearance)); }); Loading @@ -1308,8 +1309,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack private final OverviewProxyService mOverviewProxyService; private final SysUiState mSysUiState; private final PluginManager mPluginManager; private final Executor mExecutor; private final Handler mHandler; private final UiThreadContext mUiThreadContext; private final Executor mBackgroundExecutor; private final UserTracker mUserTracker; private final NavigationModeController mNavigationModeController; Loading @@ -1329,8 +1329,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack public Factory(OverviewProxyService overviewProxyService, SysUiState sysUiState, PluginManager pluginManager, @Main Executor executor, @Main Handler handler, @BackPanelUiThread UiThreadContext uiThreadContext, @Background Executor backgroundExecutor, UserTracker userTracker, NavigationModeController navigationModeController, Loading @@ -1348,8 +1347,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mOverviewProxyService = overviewProxyService; mSysUiState = sysUiState; mPluginManager = pluginManager; mExecutor = executor; mHandler = handler; mUiThreadContext = uiThreadContext; mBackgroundExecutor = backgroundExecutor; mUserTracker = userTracker; mNavigationModeController = navigationModeController; Loading @@ -1367,13 +1365,13 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack /** Construct a {@link EdgeBackGestureHandler}. */ public EdgeBackGestureHandler create(Context context) { return new EdgeBackGestureHandler( return mUiThreadContext.runWithScissors( () -> new EdgeBackGestureHandler( context, mOverviewProxyService, mSysUiState, mPluginManager, mExecutor, mHandler, mUiThreadContext, mBackgroundExecutor, mUserTracker, mNavigationModeController, Loading @@ -1386,7 +1384,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mDesktopModeOptional, mFalsingManager, mBackGestureTfClassifierProviderProvider, mLightBarControllerProvider); mLightBarControllerProvider)); } } Loading packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.kt +40 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import android.os.Handler import android.os.HandlerThread import android.os.Looper import android.os.Process import android.view.Choreographer import com.android.systemui.Dependency import com.android.systemui.Flags import com.android.systemui.dagger.SysUISingleton Loading @@ -31,6 +32,12 @@ import dagger.Module import dagger.Provides import java.util.concurrent.Executor import javax.inject.Named import javax.inject.Qualifier @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class BackPanelUiThread /** Dagger Module for classes found within the concurrent package. */ @Module Loading Loading @@ -106,6 +113,39 @@ object SysUIConcurrencyModule { return looper } @Provides @SysUISingleton @BackPanelUiThread fun provideBackPanelUiThreadContext( @Main mainLooper: Looper, @Main mainHandler: Handler, @Main mainExecutor: Executor ): UiThreadContext { return if (Flags.edgeBackGestureHandlerThread()) { val thread = HandlerThread("BackPanelUiThread", Process.THREAD_PRIORITY_DISPLAY).apply { start() looper.setSlowLogThresholdMs( LONG_SLOW_DISPATCH_THRESHOLD, LONG_SLOW_DELIVERY_THRESHOLD ) } UiThreadContext( thread.looper, thread.threadHandler, thread.threadExecutor, thread.threadHandler.runWithScissors { Choreographer.getInstance() } ) } else { UiThreadContext( mainLooper, mainHandler, mainExecutor, mainHandler.runWithScissors { Choreographer.getInstance() } ) } } /** * Background Handler. * Loading packages/SystemUI/src/com/android/systemui/util/concurrency/UiThreadContext.kt 0 → 100644 +51 −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.concurrency import android.os.Handler import android.os.Looper import android.view.Choreographer import com.android.systemui.util.Assert import java.util.concurrent.Executor import java.util.concurrent.atomic.AtomicReference private const val DEFAULT_TIMEOUT = 150L class UiThreadContext( val looper: Looper, val handler: Handler, val executor: Executor, val choreographer: Choreographer ) { fun isCurrentThread() { Assert.isCurrentThread(looper) } fun <T> runWithScissors(block: () -> T): T { return handler.runWithScissors(block) } fun runWithScissors(block: Runnable) { handler.runWithScissors(block, DEFAULT_TIMEOUT) } } fun <T> Handler.runWithScissors(block: () -> T): T { val returnedValue = AtomicReference<T>() runWithScissors({ returnedValue.set(block()) }, DEFAULT_TIMEOUT) return returnedValue.get()!! } Loading
packages/SystemUI/customization/src/com/android/systemui/util/Assert.java +15 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,21 @@ public class Assert { } } /** * Asserts that the current thread is the same as the given thread, or that the current thread * is the test thread. * @param expected The looper we expected to be running on */ public static void isCurrentThread(Looper expected) { if (!expected.isCurrentThread() && (sTestThread == null || sTestThread != Thread.currentThread())) { throw new IllegalStateException("Called on wrong thread thread." + " wanted " + expected.getThread().getName() + " but instead got Thread.currentThread()=" + Thread.currentThread().getName()); } } public static void isNotMainThread() { if (sMainLooper.isCurrentThread() && (sTestThread == null || sTestThread == Thread.currentThread())) { Loading
packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt +9 −9 Original line number Diff line number Diff line Loading @@ -36,11 +36,12 @@ import androidx.dynamicanimation.animation.DynamicAnimation import com.android.internal.jank.Cuj import com.android.internal.jank.InteractionJankMonitor import com.android.internal.util.LatencyTracker import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.NavigationEdgeBackPlugin import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.ViewController import com.android.systemui.util.concurrency.BackPanelUiThread import com.android.systemui.util.concurrency.UiThreadContext import com.android.systemui.util.time.SystemClock import java.io.PrintWriter import javax.inject.Inject Loading Loading @@ -84,11 +85,11 @@ internal constructor( context: Context, private val windowManager: WindowManager, private val viewConfiguration: ViewConfiguration, @Main private val mainHandler: Handler, private val mainHandler: Handler, private val systemClock: SystemClock, private val vibratorHelper: VibratorHelper, private val configurationController: ConfigurationController, private val latencyTracker: LatencyTracker, latencyTracker: LatencyTracker, private val interactionJankMonitor: InteractionJankMonitor, ) : ViewController<BackPanel>(BackPanel(context, latencyTracker)), NavigationEdgeBackPlugin { Loading @@ -103,7 +104,7 @@ internal constructor( constructor( private val windowManager: WindowManager, private val viewConfiguration: ViewConfiguration, @Main private val mainHandler: Handler, @BackPanelUiThread private val uiThreadContext: UiThreadContext, private val systemClock: SystemClock, private val vibratorHelper: VibratorHelper, private val configurationController: ConfigurationController, Loading @@ -112,20 +113,19 @@ internal constructor( ) { /** Construct a [BackPanelController]. */ fun create(context: Context): BackPanelController { val backPanelController = BackPanelController( uiThreadContext.isCurrentThread() return BackPanelController( context, windowManager, viewConfiguration, mainHandler, uiThreadContext.handler, systemClock, vibratorHelper, configurationController, latencyTracker, interactionJankMonitor ) backPanelController.init() return backPanelController .also { it.init() } } } Loading
packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +64 −66 Original line number Diff line number Diff line Loading @@ -44,8 +44,6 @@ import android.graphics.Rect; import android.graphics.Region; import android.hardware.input.InputManager; import android.icu.text.SimpleDateFormat; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; Loading @@ -55,7 +53,6 @@ import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.Choreographer; import android.view.ISystemGestureExclusionListener; import android.view.IWindowManager; import android.view.InputDevice; Loading @@ -75,7 +72,6 @@ import androidx.annotation.DimenRes; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.policy.GestureNavigationSettingsObserver; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.FalsingManager; Loading @@ -94,7 +90,8 @@ import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.util.Assert; import com.android.systemui.util.concurrency.BackPanelUiThread; import com.android.systemui.util.concurrency.UiThreadContext; import com.android.wm.shell.back.BackAnimation; import com.android.wm.shell.desktopmode.DesktopMode; import com.android.wm.shell.pip.Pip; Loading Loading @@ -136,7 +133,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack public void onSystemGestureExclusionChanged(int displayId, Region systemGestureExclusion, Region unrestrictedOrNull) { if (displayId == mDisplayId) { mMainExecutor.execute(() -> { mUiThreadContext.getExecutor().execute(() -> { mExcludeRegion.set(systemGestureExclusion); mUnrestrictedExcludeRegion.set(unrestrictedOrNull != null ? unrestrictedOrNull : systemGestureExclusion); Loading Loading @@ -215,8 +212,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack private final Point mDisplaySize = new Point(); private final int mDisplayId; private final Executor mMainExecutor; private final Handler mMainHandler; private final UiThreadContext mUiThreadContext; private final Executor mBackgroundExecutor; private final Rect mPipExcludedBounds = new Rect(); Loading Loading @@ -411,8 +407,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack OverviewProxyService overviewProxyService, SysUiState sysUiState, PluginManager pluginManager, @Main Executor executor, @Main Handler handler, @BackPanelUiThread UiThreadContext uiThreadContext, @Background Executor backgroundExecutor, UserTracker userTracker, NavigationModeController navigationModeController, Loading @@ -428,8 +423,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack Provider<LightBarController> lightBarControllerProvider) { mContext = context; mDisplayId = context.getDisplayId(); mMainExecutor = executor; mMainHandler = handler; mUiThreadContext = uiThreadContext; mBackgroundExecutor = backgroundExecutor; mUserTracker = userTracker; mOverviewProxyService = overviewProxyService; Loading Loading @@ -478,7 +472,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack ViewConfiguration.getLongPressTimeout()); mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver( mMainHandler, mContext, this::onNavigationSettingsChanged); mUiThreadContext.getHandler(), mContext, this::onNavigationSettingsChanged); updateCurrentUserResources(); } Loading Loading @@ -564,13 +558,15 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mIsAttached = true; mOverviewProxyService.addCallback(mQuickSwitchListener); mSysUiState.addCallback(mSysUiStateCallback); mInputManager.registerInputDeviceListener(mInputDeviceListener, mMainHandler); mInputManager.registerInputDeviceListener( mInputDeviceListener, mUiThreadContext.getHandler()); int[] inputDevices = mInputManager.getInputDeviceIds(); for (int inputDeviceId : inputDevices) { mInputDeviceListener.onInputDeviceAdded(inputDeviceId); } updateIsEnabled(); mUserTracker.addCallback(mUserChangedCallback, mMainExecutor); mUserTracker.addCallback(mUserChangedCallback, mUiThreadContext.getExecutor()); } /** Loading Loading @@ -617,6 +613,10 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } private void updateIsEnabled() { mUiThreadContext.runWithScissors(this::updateIsEnabledInner); } private void updateIsEnabledInner() { try { Trace.beginSection("EdgeBackGestureHandler#updateIsEnabled"); Loading Loading @@ -661,12 +661,12 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack TaskStackChangeListeners.getInstance().registerTaskStackListener( mTaskStackListener); DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mMainExecutor::execute, mOnPropertiesChangedListener); mUiThreadContext.getExecutor()::execute, mOnPropertiesChangedListener); mPipOptional.ifPresent(pip -> pip.setOnIsInPipStateChangedListener( mOnIsInPipStateChangedListener)); mDesktopModeOptional.ifPresent( dm -> dm.addDesktopGestureExclusionRegionListener( mDesktopCornersChangedListener, mMainExecutor)); mDesktopCornersChangedListener, mUiThreadContext.getExecutor())); try { mWindowManagerService.registerSystemGestureExclusionListener( Loading @@ -677,8 +677,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack // Register input event receiver mInputMonitor = new InputMonitorCompat("edge-swipe", mDisplayId); mInputEventReceiver = mInputMonitor.getInputReceiver(Looper.getMainLooper(), Choreographer.getInstance(), this::onInputEvent); mInputEventReceiver = mInputMonitor.getInputReceiver(mUiThreadContext.getLooper(), mUiThreadContext.getChoreographer(), this::onInputEvent); // Add a nav bar panel window resetEdgeBackPlugin(); Loading Loading @@ -773,7 +773,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mUseMLModel = newState; if (mUseMLModel) { Assert.isMainThread(); mUiThreadContext.isCurrentThread(); if (mMLModelIsLoading) { Log.d(TAG, "Model tried to load while already loading."); return; Loading Loading @@ -804,12 +804,13 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } BackGestureTfClassifierProvider finalProvider = provider; Map<String, Integer> finalVocab = vocab; mMainExecutor.execute(() -> onMLModelLoadFinished(finalProvider, finalVocab, threshold)); mUiThreadContext.getExecutor().execute( () -> onMLModelLoadFinished(finalProvider, finalVocab, threshold)); } private void onMLModelLoadFinished(BackGestureTfClassifierProvider provider, Map<String, Integer> vocab, float threshold) { Assert.isMainThread(); mUiThreadContext.isCurrentThread(); mMLModelIsLoading = false; if (!mUseMLModel) { // This can happen if the user disables Gesture Nav while the model is loading. Loading Loading @@ -1291,7 +1292,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack updateBackAnimationThresholds(); if (mLightBarControllerProvider.get() != null) { mBackAnimation.setStatusBarCustomizer((appearance) -> { mMainExecutor.execute(() -> mUiThreadContext.getExecutor().execute(() -> mLightBarControllerProvider.get() .customizeStatusBarAppearance(appearance)); }); Loading @@ -1308,8 +1309,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack private final OverviewProxyService mOverviewProxyService; private final SysUiState mSysUiState; private final PluginManager mPluginManager; private final Executor mExecutor; private final Handler mHandler; private final UiThreadContext mUiThreadContext; private final Executor mBackgroundExecutor; private final UserTracker mUserTracker; private final NavigationModeController mNavigationModeController; Loading @@ -1329,8 +1329,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack public Factory(OverviewProxyService overviewProxyService, SysUiState sysUiState, PluginManager pluginManager, @Main Executor executor, @Main Handler handler, @BackPanelUiThread UiThreadContext uiThreadContext, @Background Executor backgroundExecutor, UserTracker userTracker, NavigationModeController navigationModeController, Loading @@ -1348,8 +1347,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mOverviewProxyService = overviewProxyService; mSysUiState = sysUiState; mPluginManager = pluginManager; mExecutor = executor; mHandler = handler; mUiThreadContext = uiThreadContext; mBackgroundExecutor = backgroundExecutor; mUserTracker = userTracker; mNavigationModeController = navigationModeController; Loading @@ -1367,13 +1365,13 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack /** Construct a {@link EdgeBackGestureHandler}. */ public EdgeBackGestureHandler create(Context context) { return new EdgeBackGestureHandler( return mUiThreadContext.runWithScissors( () -> new EdgeBackGestureHandler( context, mOverviewProxyService, mSysUiState, mPluginManager, mExecutor, mHandler, mUiThreadContext, mBackgroundExecutor, mUserTracker, mNavigationModeController, Loading @@ -1386,7 +1384,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mDesktopModeOptional, mFalsingManager, mBackGestureTfClassifierProviderProvider, mLightBarControllerProvider); mLightBarControllerProvider)); } } Loading
packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.kt +40 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import android.os.Handler import android.os.HandlerThread import android.os.Looper import android.os.Process import android.view.Choreographer import com.android.systemui.Dependency import com.android.systemui.Flags import com.android.systemui.dagger.SysUISingleton Loading @@ -31,6 +32,12 @@ import dagger.Module import dagger.Provides import java.util.concurrent.Executor import javax.inject.Named import javax.inject.Qualifier @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class BackPanelUiThread /** Dagger Module for classes found within the concurrent package. */ @Module Loading Loading @@ -106,6 +113,39 @@ object SysUIConcurrencyModule { return looper } @Provides @SysUISingleton @BackPanelUiThread fun provideBackPanelUiThreadContext( @Main mainLooper: Looper, @Main mainHandler: Handler, @Main mainExecutor: Executor ): UiThreadContext { return if (Flags.edgeBackGestureHandlerThread()) { val thread = HandlerThread("BackPanelUiThread", Process.THREAD_PRIORITY_DISPLAY).apply { start() looper.setSlowLogThresholdMs( LONG_SLOW_DISPATCH_THRESHOLD, LONG_SLOW_DELIVERY_THRESHOLD ) } UiThreadContext( thread.looper, thread.threadHandler, thread.threadExecutor, thread.threadHandler.runWithScissors { Choreographer.getInstance() } ) } else { UiThreadContext( mainLooper, mainHandler, mainExecutor, mainHandler.runWithScissors { Choreographer.getInstance() } ) } } /** * Background Handler. * Loading
packages/SystemUI/src/com/android/systemui/util/concurrency/UiThreadContext.kt 0 → 100644 +51 −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.concurrency import android.os.Handler import android.os.Looper import android.view.Choreographer import com.android.systemui.util.Assert import java.util.concurrent.Executor import java.util.concurrent.atomic.AtomicReference private const val DEFAULT_TIMEOUT = 150L class UiThreadContext( val looper: Looper, val handler: Handler, val executor: Executor, val choreographer: Choreographer ) { fun isCurrentThread() { Assert.isCurrentThread(looper) } fun <T> runWithScissors(block: () -> T): T { return handler.runWithScissors(block) } fun runWithScissors(block: Runnable) { handler.runWithScissors(block, DEFAULT_TIMEOUT) } } fun <T> Handler.runWithScissors(block: () -> T): T { val returnedValue = AtomicReference<T>() runWithScissors({ returnedValue.set(block()) }, DEFAULT_TIMEOUT) return returnedValue.get()!! }