Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bbbb2d8f authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Separate thread for back panel" into main

parents c4a21251 a379689f
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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())) {
+9 −9
Original line number Diff line number Diff line
@@ -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() }
        }
    }

+64 −66
Original line number Diff line number Diff line
@@ -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);
        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;
@@ -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,
@@ -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;
@@ -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,
@@ -1386,7 +1384,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
                            mDesktopModeOptional,
                            mFalsingManager,
                            mBackGestureTfClassifierProviderProvider,
                    mLightBarControllerProvider);
                            mLightBarControllerProvider));
        }
    }

+40 −0
Original line number Diff line number Diff line
@@ -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.
     *
+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()!!
}