diff options
| author | 2024-05-31 08:57:07 +0000 | |
|---|---|---|
| committer | 2024-05-31 08:57:07 +0000 | |
| commit | bbbb2d8ff62fc6e0d573613d64a2ef8806961bf5 (patch) | |
| tree | 46d8a822443cc77bbe94fada84a550a6f508d128 | |
| parent | c4a2125180170bd11ea812cdcb464d77f0053e44 (diff) | |
| parent | a379689f66bcc431645ec7c87bbd35eb2f42732f (diff) | |
Merge "Separate thread for back panel" into main
5 files changed, 179 insertions, 75 deletions
diff --git a/packages/SystemUI/customization/src/com/android/systemui/util/Assert.java b/packages/SystemUI/customization/src/com/android/systemui/util/Assert.java index 165e9728b9d7..de9baa59b2b7 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/util/Assert.java +++ b/packages/SystemUI/customization/src/com/android/systemui/util/Assert.java @@ -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())) { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt index b208434c3218..18358a79cbca 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt @@ -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 @@ -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 { @@ -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, @@ -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() } } } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index d0f8412c85b2..2dc09e5ab478 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -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; @@ -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; @@ -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; @@ -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; @@ -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); @@ -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(); @@ -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, @@ -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; @@ -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(); } @@ -564,13 +558,15 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mIsAttached = true; mOverviewProxyService.addCallback(mQuickSwitchListener); mSysUiState.addCallback(mSysUiStateCallback); - mInputManager.registerInputDeviceListener(mInputDeviceListener, mMainHandler); - int [] inputDevices = mInputManager.getInputDeviceIds(); + 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()); } /** @@ -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"); @@ -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( @@ -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(); @@ -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; @@ -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. @@ -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)); }); @@ -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; @@ -1327,29 +1327,27 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack @Inject public Factory(OverviewProxyService overviewProxyService, - SysUiState sysUiState, - PluginManager pluginManager, - @Main Executor executor, - @Main Handler handler, - @Background Executor backgroundExecutor, - UserTracker userTracker, - NavigationModeController navigationModeController, - BackPanelController.Factory backPanelControllerFactory, - ViewConfiguration viewConfiguration, - WindowManager windowManager, - IWindowManager windowManagerService, - InputManager inputManager, - Optional<Pip> pipOptional, - Optional<DesktopMode> desktopModeOptional, - FalsingManager falsingManager, - Provider<BackGestureTfClassifierProvider> - backGestureTfClassifierProviderProvider, - Provider<LightBarController> lightBarControllerProvider) { + SysUiState sysUiState, + PluginManager pluginManager, + @BackPanelUiThread UiThreadContext uiThreadContext, + @Background Executor backgroundExecutor, + UserTracker userTracker, + NavigationModeController navigationModeController, + BackPanelController.Factory backPanelControllerFactory, + ViewConfiguration viewConfiguration, + WindowManager windowManager, + IWindowManager windowManagerService, + InputManager inputManager, + Optional<Pip> pipOptional, + Optional<DesktopMode> desktopModeOptional, + FalsingManager falsingManager, + Provider<BackGestureTfClassifierProvider> + backGestureTfClassifierProviderProvider, + Provider<LightBarController> lightBarControllerProvider) { mOverviewProxyService = overviewProxyService; mSysUiState = sysUiState; mPluginManager = pluginManager; - mExecutor = executor; - mHandler = handler; + mUiThreadContext = uiThreadContext; mBackgroundExecutor = backgroundExecutor; mUserTracker = userTracker; mNavigationModeController = navigationModeController; @@ -1367,26 +1365,26 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack /** Construct a {@link EdgeBackGestureHandler}. */ public EdgeBackGestureHandler create(Context context) { - return new EdgeBackGestureHandler( - context, - mOverviewProxyService, - mSysUiState, - mPluginManager, - mExecutor, - mHandler, - mBackgroundExecutor, - mUserTracker, - mNavigationModeController, - mBackPanelControllerFactory, - mViewConfiguration, - mWindowManager, - mWindowManagerService, - mInputManager, - mPipOptional, - mDesktopModeOptional, - mFalsingManager, - mBackGestureTfClassifierProviderProvider, - mLightBarControllerProvider); + return mUiThreadContext.runWithScissors( + () -> new EdgeBackGestureHandler( + context, + mOverviewProxyService, + mSysUiState, + mPluginManager, + mUiThreadContext, + mBackgroundExecutor, + mUserTracker, + mNavigationModeController, + mBackPanelControllerFactory, + mViewConfiguration, + mWindowManager, + mWindowManagerService, + mInputManager, + mPipOptional, + mDesktopModeOptional, + mFalsingManager, + mBackGestureTfClassifierProviderProvider, + mLightBarControllerProvider)); } } diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.kt b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.kt index 83e3428bb95f..a7abb6b5f1d3 100644 --- a/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.kt +++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.kt @@ -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 @@ -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 @@ -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. * diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/UiThreadContext.kt b/packages/SystemUI/src/com/android/systemui/util/concurrency/UiThreadContext.kt new file mode 100644 index 000000000000..8c8c686dddcc --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/UiThreadContext.kt @@ -0,0 +1,51 @@ +/* + * 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()!! +} |