Merge "Move wm component initialization to shell main thread"

This commit is contained in:
TreeHugger Robot
2022-02-17 07:26:37 +00:00
committed by Android (Google) Code Review
4 changed files with 81 additions and 19 deletions

View File

@@ -168,8 +168,8 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static DragAndDrop provideDragAndDrop(DragAndDropController dragAndDropController) {
return dragAndDropController.asDragAndDrop();
static Optional<DragAndDrop> provideDragAndDrop(DragAndDropController dragAndDropController) {
return Optional.of(dragAndDropController.asDragAndDrop());
}
@WMSingleton
@@ -184,8 +184,8 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static CompatUI provideCompatUI(CompatUIController compatUIController) {
return compatUIController.asCompatUI();
static Optional<CompatUI> provideCompatUI(CompatUIController compatUIController) {
return Optional.of(compatUIController.asCompatUI());
}
@WMSingleton

View File

@@ -27,7 +27,10 @@ import android.os.HandlerThread;
import android.os.Looper;
import android.os.Trace;
import androidx.annotation.Nullable;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.wm.shell.R;
import com.android.wm.shell.common.HandlerExecutor;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
@@ -35,7 +38,6 @@ import com.android.wm.shell.common.annotations.ExternalMainThread;
import com.android.wm.shell.common.annotations.ShellAnimationThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
import com.android.wm.shell.R;
import dagger.Module;
import dagger.Provides;
@@ -53,7 +55,7 @@ public abstract class WMShellConcurrencyModule {
/**
* Returns whether to enable a separate shell thread for the shell features.
*/
private static boolean enableShellMainThread(Context context) {
public static boolean enableShellMainThread(Context context) {
return context.getResources().getBoolean(R.bool.config_enableShellMainThread);
}
@@ -84,24 +86,42 @@ public abstract class WMShellConcurrencyModule {
return new HandlerExecutor(sysuiMainHandler);
}
/**
* Creates a shell main thread to be injected into the shell components. This does not provide
* the {@param HandleThread}, but is used to create the thread prior to initializing the
* WM component, and is explicitly bound.
*
* See {@link com.android.systemui.SystemUIFactory#init(Context, boolean)}.
*/
public static HandlerThread createShellMainThread() {
HandlerThread mainThread = new HandlerThread("wmshell.main", THREAD_PRIORITY_DISPLAY);
return mainThread;
}
/**
* Shell main-thread Handler, don't use this unless really necessary (ie. need to dedupe
* multiple types of messages, etc.)
*
* @param mainThread If non-null, this thread is expected to be started already
*/
@WMSingleton
@Provides
@ShellMainThread
public static Handler provideShellMainHandler(Context context,
@Nullable @ShellMainThread HandlerThread mainThread,
@ExternalMainThread Handler sysuiMainHandler) {
if (enableShellMainThread(context)) {
HandlerThread mainThread = new HandlerThread("wmshell.main", THREAD_PRIORITY_DISPLAY);
mainThread.start();
if (Build.IS_DEBUGGABLE) {
mainThread.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
mainThread.getLooper().setSlowLogThresholdMs(MSGQ_SLOW_DISPATCH_THRESHOLD_MS,
MSGQ_SLOW_DELIVERY_THRESHOLD_MS);
}
return Handler.createAsync(mainThread.getLooper());
if (mainThread == null) {
// If this thread wasn't pre-emptively started, then create and start it
mainThread = createShellMainThread();
mainThread.start();
}
if (Build.IS_DEBUGGABLE) {
mainThread.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
mainThread.getLooper().setSlowLogThresholdMs(MSGQ_SLOW_DISPATCH_THRESHOLD_MS,
MSGQ_SLOW_DELIVERY_THRESHOLD_MS);
}
return Handler.createAsync(mainThread.getLooper());
}
return sysuiMainHandler;
}

View File

@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -28,6 +29,7 @@ import com.android.systemui.dagger.DaggerGlobalRootComponent;
import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dagger.WMComponent;
import com.android.wm.shell.dagger.WMShellConcurrencyModule;
import com.android.systemui.navigationbar.gestural.BackGestureTfClassifierProvider;
import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
import com.android.wm.shell.transition.ShellTransitions;
@@ -96,8 +98,9 @@ public class SystemUIFactory {
&& android.os.Process.myUserHandle().isSystem()
&& ActivityThread.currentProcessName().equals(ActivityThread.currentPackageName());
mRootComponent = buildGlobalRootComponent(context);
// Stand up WMComponent
mWMComponent = mRootComponent.getWMComponentBuilder().build();
setupWmComponent(context);
if (mInitializeComponents) {
// Only initialize when not starting from tests since this currently initializes some
// components that shouldn't be run in the test environment
@@ -124,8 +127,8 @@ public class SystemUIFactory {
.setDisplayAreaHelper(mWMComponent.getDisplayAreaHelper())
.setTaskSurfaceHelper(mWMComponent.getTaskSurfaceHelper())
.setRecentTasks(mWMComponent.getRecentTasks())
.setCompatUI(Optional.of(mWMComponent.getCompatUI()))
.setDragAndDrop(Optional.of(mWMComponent.getDragAndDrop()))
.setCompatUI(mWMComponent.getCompatUI())
.setDragAndDrop(mWMComponent.getDragAndDrop())
.setBackAnimation(mWMComponent.getBackAnimation());
} else {
// TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option
@@ -160,6 +163,36 @@ public class SystemUIFactory {
dependency.start();
}
/**
* Sets up {@link #mWMComponent}. On devices where the Shell runs on its own main thread,
* this will pre-create the thread to ensure that the components are constructed on the
* same thread, to reduce the likelihood of side effects from running the constructors on
* a different thread than the rest of the class logic.
*/
private void setupWmComponent(Context context) {
WMComponent.Builder wmBuilder = mRootComponent.getWMComponentBuilder();
if (!mInitializeComponents || !WMShellConcurrencyModule.enableShellMainThread(context)) {
// If running under tests or shell thread is not enabled, we don't need anything special
mWMComponent = wmBuilder.build();
return;
}
// If the shell main thread is enabled, initialize the component on that thread
HandlerThread shellThread = WMShellConcurrencyModule.createShellMainThread();
shellThread.start();
// Use an async handler since we don't care about synchronization
Handler shellHandler = Handler.createAsync(shellThread.getLooper());
boolean built = shellHandler.runWithScissors(() -> {
wmBuilder.setShellMainThread(shellThread);
mWMComponent = wmBuilder.build();
}, 5000);
if (!built) {
Log.w(TAG, "Failed to initialize WMComponent");
throw new RuntimeException();
}
}
/**
* Prepares the SysUIComponent builder before it is built.
* @param sysUIBuilder the builder provided by the root component's getSysUIComponent() method

View File

@@ -17,6 +17,9 @@
package com.android.systemui.dagger;
import android.content.Context;
import android.os.HandlerThread;
import androidx.annotation.Nullable;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.tv.TvWMComponent;
@@ -26,6 +29,7 @@ import com.android.wm.shell.TaskViewFactory;
import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.compatui.CompatUI;
import com.android.wm.shell.dagger.TvWMShellModule;
import com.android.wm.shell.dagger.WMShellModule;
@@ -44,6 +48,7 @@ import com.android.wm.shell.transition.ShellTransitions;
import java.util.Optional;
import dagger.BindsInstance;
import dagger.Subcomponent;
/**
@@ -64,6 +69,10 @@ public interface WMComponent {
*/
@Subcomponent.Builder
interface Builder {
@BindsInstance
Builder setShellMainThread(@Nullable @ShellMainThread HandlerThread t);
WMComponent build();
}
@@ -120,10 +129,10 @@ public interface WMComponent {
Optional<RecentTasks> getRecentTasks();
@WMSingleton
CompatUI getCompatUI();
Optional<CompatUI> getCompatUI();
@WMSingleton
DragAndDrop getDragAndDrop();
Optional<DragAndDrop> getDragAndDrop();
@WMSingleton
Optional<BackAnimation> getBackAnimation();