2/ Migrate some common shell classes to use executors

- Remove Handler usage in some (non-feature specific) shell code
(Note: The shell main thread will still be the sysui main thread)
- Add explicit executor for display organizer

Bug: 161979899
Test: atest WMShellUnitTests
Change-Id: I9a354f742167b907c32537eb022e22c0d5bfb97a
This commit is contained in:
Winson Chung
2020-11-11 13:43:54 -08:00
parent 0a398edf5a
commit 68d5d7cdfe
30 changed files with 557 additions and 340 deletions

View File

@@ -16,113 +16,32 @@
package com.android.wm.shell; package com.android.wm.shell;
import android.util.Slog;
import com.android.wm.shell.apppairs.AppPairs; import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip; import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.TimeUnit;
/** /**
* An entry point into the shell for dumping shell internal state and running adb commands. * An entry point into the shell for dumping shell internal state and running adb commands.
* *
* Use with {@code adb shell dumpsys activity service SystemUIService WMShell ...}. * Use with {@code adb shell dumpsys activity service SystemUIService WMShell ...}.
*/ */
public final class ShellCommandHandler { public interface ShellCommandHandler {
/**
* Dumps the shell state.
*/
void dump(PrintWriter pw);
private final Optional<LegacySplitScreen> mLegacySplitScreenOptional; /**
private final Optional<Pip> mPipOptional; * Handles a shell command.
private final Optional<OneHanded> mOneHandedOptional; */
private final Optional<HideDisplayCutout> mHideDisplayCutout; boolean handleCommand(final String[] args, PrintWriter pw);
private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<AppPairs> mAppPairsOptional;
public ShellCommandHandler(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,
Optional<AppPairs> appPairsOptional) {
mShellTaskOrganizer = shellTaskOrganizer;
mLegacySplitScreenOptional = legacySplitScreenOptional;
mPipOptional = pipOptional;
mOneHandedOptional = oneHandedOptional;
mHideDisplayCutout = hideDisplayCutout;
mAppPairsOptional = appPairsOptional;
}
/** Dumps WM Shell internal state. */
@ExternalThread
public void dump(PrintWriter pw) {
mShellTaskOrganizer.dump(pw, "");
pw.println();
pw.println();
mPipOptional.ifPresent(pip -> pip.dump(pw));
mLegacySplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw));
mOneHandedOptional.ifPresent(oneHanded -> oneHanded.dump(pw));
mHideDisplayCutout.ifPresent(hideDisplayCutout -> hideDisplayCutout.dump(pw));
pw.println();
pw.println();
mAppPairsOptional.ifPresent(appPairs -> appPairs.dump(pw, ""));
}
/** Returns {@code true} if command was found and executed. */
@ExternalThread
public boolean handleCommand(String[] args, PrintWriter pw) {
if (args.length < 2) {
// Argument at position 0 is "WMShell".
return false;
}
switch (args[1]) {
case "pair":
return runPair(args, pw);
case "unpair":
return runUnpair(args, pw);
case "help":
return runHelp(pw);
default:
return false;
}
}
private boolean runPair(String[] args, PrintWriter pw) {
if (args.length < 4) {
// First two arguments are "WMShell" and command name.
pw.println("Error: two task ids should be provided as arguments");
return false;
}
final int taskId1 = new Integer(args[2]);
final int taskId2 = new Integer(args[3]);
mAppPairsOptional.ifPresent(appPairs -> appPairs.pair(taskId1, taskId2));
return true;
}
private boolean runUnpair(String[] args, PrintWriter pw) {
if (args.length < 3) {
// First two arguments are "WMShell" and command name.
pw.println("Error: task id should be provided as an argument");
return false;
}
final int taskId = new Integer(args[2]);
mAppPairsOptional.ifPresent(appPairs -> appPairs.unpair(taskId));
return true;
}
private boolean runHelp(PrintWriter pw) {
pw.println("Window Manager Shell commands:");
pw.println(" help");
pw.println(" Print this help text.");
pw.println(" <no arguments provided>");
pw.println(" Dump Window Manager Shell internal state");
pw.println(" pair <taskId1> <taskId2>");
pw.println(" unpair <taskId>");
pw.println(" Pairs/unpairs tasks with given ids.");
return true;
}
} }

View File

@@ -0,0 +1,171 @@
/*
* Copyright (C) 2019 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.wm.shell;
import android.util.Slog;
import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.io.PrintWriter;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
/**
* An entry point into the shell for dumping shell internal state and running adb commands.
*
* Use with {@code adb shell dumpsys activity service SystemUIService WMShell ...}.
*/
public final class ShellCommandHandlerImpl {
private static final String TAG = ShellCommandHandlerImpl.class.getSimpleName();
private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
private final Optional<Pip> mPipOptional;
private final Optional<OneHanded> mOneHandedOptional;
private final Optional<HideDisplayCutout> mHideDisplayCutout;
private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<AppPairs> mAppPairsOptional;
private final ShellExecutor mMainExecutor;
private final HandlerImpl mImpl = new HandlerImpl();
public static ShellCommandHandler create(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,
Optional<AppPairs> appPairsOptional,
ShellExecutor mainExecutor) {
return new ShellCommandHandlerImpl(shellTaskOrganizer, legacySplitScreenOptional,
pipOptional, oneHandedOptional, hideDisplayCutout, appPairsOptional,
mainExecutor).mImpl;
}
private ShellCommandHandlerImpl(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,
Optional<AppPairs> appPairsOptional,
ShellExecutor mainExecutor) {
mShellTaskOrganizer = shellTaskOrganizer;
mLegacySplitScreenOptional = legacySplitScreenOptional;
mPipOptional = pipOptional;
mOneHandedOptional = oneHandedOptional;
mHideDisplayCutout = hideDisplayCutout;
mAppPairsOptional = appPairsOptional;
mMainExecutor = mainExecutor;
}
/** Dumps WM Shell internal state. */
private void dump(PrintWriter pw) {
mShellTaskOrganizer.dump(pw, "");
pw.println();
pw.println();
mPipOptional.ifPresent(pip -> pip.dump(pw));
mLegacySplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw));
mOneHandedOptional.ifPresent(oneHanded -> oneHanded.dump(pw));
mHideDisplayCutout.ifPresent(hideDisplayCutout -> hideDisplayCutout.dump(pw));
pw.println();
pw.println();
mAppPairsOptional.ifPresent(appPairs -> appPairs.dump(pw, ""));
}
/** Returns {@code true} if command was found and executed. */
private boolean handleCommand(final String[] args, PrintWriter pw) {
if (args.length < 2) {
// Argument at position 0 is "WMShell".
return false;
}
switch (args[1]) {
case "pair":
return runPair(args, pw);
case "unpair":
return runUnpair(args, pw);
case "help":
return runHelp(pw);
default:
return false;
}
}
private boolean runPair(String[] args, PrintWriter pw) {
if (args.length < 4) {
// First two arguments are "WMShell" and command name.
pw.println("Error: two task ids should be provided as arguments");
return false;
}
final int taskId1 = new Integer(args[2]);
final int taskId2 = new Integer(args[3]);
mAppPairsOptional.ifPresent(appPairs -> appPairs.pair(taskId1, taskId2));
return true;
}
private boolean runUnpair(String[] args, PrintWriter pw) {
if (args.length < 3) {
// First two arguments are "WMShell" and command name.
pw.println("Error: task id should be provided as an argument");
return false;
}
final int taskId = new Integer(args[2]);
mAppPairsOptional.ifPresent(appPairs -> appPairs.unpair(taskId));
return true;
}
private boolean runHelp(PrintWriter pw) {
pw.println("Window Manager Shell commands:");
pw.println(" help");
pw.println(" Print this help text.");
pw.println(" <no arguments provided>");
pw.println(" Dump Window Manager Shell internal state");
pw.println(" pair <taskId1> <taskId2>");
pw.println(" unpair <taskId>");
pw.println(" Pairs/unpairs tasks with given ids.");
return true;
}
private class HandlerImpl implements ShellCommandHandler {
@Override
public void dump(PrintWriter pw) {
try {
mMainExecutor.executeBlocking(() -> ShellCommandHandlerImpl.this.dump(pw));
} catch (InterruptedException e) {
throw new RuntimeException("Failed to dump the Shell in 2s", e);
}
}
@Override
public boolean handleCommand(String[] args, PrintWriter pw) {
try {
boolean[] result = new boolean[1];
mMainExecutor.executeBlocking(() -> {
result[0] = ShellCommandHandlerImpl.this.handleCommand(args, pw);
});
return result[0];
} catch (InterruptedException e) {
throw new RuntimeException("Failed to handle Shell command in 2s", e);
}
}
}
}

View File

@@ -16,61 +16,15 @@
package com.android.wm.shell; package com.android.wm.shell;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.Optional;
/** /**
* An entry point into the shell for initializing shell internal state. * An entry point into the shell for initializing shell internal state.
*/ */
public class ShellInit {
private final DisplayImeController mDisplayImeController;
private final DragAndDropController mDragAndDropController;
private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
private final Optional<AppPairs> mAppPairsOptional;
private final FullscreenTaskListener mFullscreenTaskListener;
private final Transitions mTransitions;
public ShellInit(DisplayImeController displayImeController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions) {
mDisplayImeController = displayImeController;
mDragAndDropController = dragAndDropController;
mShellTaskOrganizer = shellTaskOrganizer;
mLegacySplitScreenOptional = legacySplitScreenOptional;
mAppPairsOptional = appPairsOptional;
mFullscreenTaskListener = fullscreenTaskListener;
mTransitions = transitions;
}
@ExternalThread @ExternalThread
public void init() { public interface ShellInit {
// Start listening for display changes /**
mDisplayImeController.startMonitorDisplays(); * Initializes the shell state.
*/
mShellTaskOrganizer.addListenerForType( void init();
mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
// Register the shell organizer
mShellTaskOrganizer.registerOrganizer();
mAppPairsOptional.ifPresent(AppPairs::onOrganizerRegistered);
// Bind the splitscreen impl to the drag drop controller
mDragAndDropController.setSplitScreenController(mLegacySplitScreenOptional);
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
mTransitions.register(mShellTaskOrganizer);
}
}
} }

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2019 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.wm.shell;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
/**
* The entry point implementation into the shell for initializing shell internal state.
*/
public class ShellInitImpl {
private static final String TAG = ShellInitImpl.class.getSimpleName();
private final DisplayImeController mDisplayImeController;
private final DragAndDropController mDragAndDropController;
private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
private final Optional<AppPairs> mAppPairsOptional;
private final FullscreenTaskListener mFullscreenTaskListener;
private final ShellExecutor mMainExecutor;
private final InitImpl mImpl = new InitImpl();
public static ShellInit create(DisplayImeController displayImeController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener,
ShellExecutor mainExecutor) {
return new ShellInitImpl(displayImeController,
dragAndDropController,
shellTaskOrganizer,
legacySplitScreenOptional,
appPairsOptional,
fullscreenTaskListener,
mainExecutor).mImpl;
}
private ShellInitImpl(DisplayImeController displayImeController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener,
ShellExecutor mainExecutor) {
mDisplayImeController = displayImeController;
mDragAndDropController = dragAndDropController;
mShellTaskOrganizer = shellTaskOrganizer;
mLegacySplitScreenOptional = legacySplitScreenOptional;
mAppPairsOptional = appPairsOptional;
mFullscreenTaskListener = fullscreenTaskListener;
mMainExecutor = mainExecutor;
}
private void init() {
// Start listening for display changes
mDisplayImeController.startMonitorDisplays();
mShellTaskOrganizer.addListenerForType(
mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
// Register the shell organizer
mShellTaskOrganizer.registerOrganizer();
mAppPairsOptional.ifPresent(AppPairs::onOrganizerRegistered);
// Bind the splitscreen impl to the drag drop controller
mDragAndDropController.initialize(mLegacySplitScreenOptional);
}
@ExternalThread
private class InitImpl implements ShellInit {
@Override
public void init() {
try {
mMainExecutor.executeBlocking(() -> ShellInitImpl.this.init());
} catch (InterruptedException e) {
throw new RuntimeException("Failed to initialize the Shell in 2s", e);
}
}
}
}

View File

@@ -37,8 +37,8 @@ public class WindowManagerShellWrapper {
*/ */
private final PinnedStackListenerForwarder mPinnedStackListenerForwarder; private final PinnedStackListenerForwarder mPinnedStackListenerForwarder;
public WindowManagerShellWrapper(ShellExecutor shellMainExecutor) { public WindowManagerShellWrapper(ShellExecutor mainExecutor) {
mPinnedStackListenerForwarder = new PinnedStackListenerForwarder(shellMainExecutor); mPinnedStackListenerForwarder = new PinnedStackListenerForwarder(mainExecutor);
} }
/** /**

View File

@@ -45,7 +45,6 @@ import android.graphics.PixelFormat;
import android.graphics.PointF; import android.graphics.PointF;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.os.UserHandle; import android.os.UserHandle;
@@ -68,6 +67,7 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.WindowManagerShellWrapper; import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.pip.PinnedStackListenerForwarder; import com.android.wm.shell.pip.PinnedStackListenerForwarder;
import java.io.FileDescriptor; import java.io.FileDescriptor;
@@ -106,7 +106,6 @@ public class BubbleController implements Bubbles {
private final FloatingContentCoordinator mFloatingContentCoordinator; private final FloatingContentCoordinator mFloatingContentCoordinator;
private final BubbleDataRepository mDataRepository; private final BubbleDataRepository mDataRepository;
private BubbleLogger mLogger; private BubbleLogger mLogger;
private final Handler mMainHandler;
private BubbleData mBubbleData; private BubbleData mBubbleData;
private View mBubbleScrim; private View mBubbleScrim;
@Nullable private BubbleStackView mStackView; @Nullable private BubbleStackView mStackView;
@@ -138,7 +137,7 @@ public class BubbleController implements Bubbles {
private WindowManager mWindowManager; private WindowManager mWindowManager;
// Used to post to main UI thread // Used to post to main UI thread
private Handler mHandler = new Handler(); private final ShellExecutor mMainExecutor;
/** LayoutParams used to add the BubbleStackView to the window manager. */ /** LayoutParams used to add the BubbleStackView to the window manager. */
private WindowManager.LayoutParams mWmLayoutParams; private WindowManager.LayoutParams mWmLayoutParams;
@@ -186,15 +185,15 @@ public class BubbleController implements Bubbles {
WindowManagerShellWrapper windowManagerShellWrapper, WindowManagerShellWrapper windowManagerShellWrapper,
LauncherApps launcherApps, LauncherApps launcherApps,
UiEventLogger uiEventLogger, UiEventLogger uiEventLogger,
Handler mainHandler, ShellTaskOrganizer organizer,
ShellTaskOrganizer organizer) { ShellExecutor mainExecutor) {
BubbleLogger logger = new BubbleLogger(uiEventLogger); BubbleLogger logger = new BubbleLogger(uiEventLogger);
BubblePositioner positioner = new BubblePositioner(context, windowManager); BubblePositioner positioner = new BubblePositioner(context, windowManager);
BubbleData data = new BubbleData(context, logger, positioner); BubbleData data = new BubbleData(context, logger, positioner);
return new BubbleController(context, data, synchronizer, floatingContentCoordinator, return new BubbleController(context, data, synchronizer, floatingContentCoordinator,
new BubbleDataRepository(context, launcherApps), new BubbleDataRepository(context, launcherApps),
statusBarService, windowManager, windowManagerShellWrapper, launcherApps, statusBarService, windowManager, windowManagerShellWrapper, launcherApps,
logger, mainHandler, organizer, positioner); logger, organizer, positioner, mainExecutor);
} }
/** /**
@@ -211,14 +210,14 @@ public class BubbleController implements Bubbles {
WindowManagerShellWrapper windowManagerShellWrapper, WindowManagerShellWrapper windowManagerShellWrapper,
LauncherApps launcherApps, LauncherApps launcherApps,
BubbleLogger bubbleLogger, BubbleLogger bubbleLogger,
Handler mainHandler,
ShellTaskOrganizer organizer, ShellTaskOrganizer organizer,
BubblePositioner positioner) { BubblePositioner positioner,
ShellExecutor mainExecutor) {
mContext = context; mContext = context;
mFloatingContentCoordinator = floatingContentCoordinator; mFloatingContentCoordinator = floatingContentCoordinator;
mDataRepository = dataRepository; mDataRepository = dataRepository;
mLogger = bubbleLogger; mLogger = bubbleLogger;
mMainHandler = mainHandler; mMainExecutor = mainExecutor;
mBubblePositioner = positioner; mBubblePositioner = positioner;
mBubbleData = data; mBubbleData = data;
@@ -241,7 +240,7 @@ public class BubbleController implements Bubbles {
bubble.setPendingIntentCanceled(); bubble.setPendingIntentCanceled();
return; return;
} }
mHandler.post(() -> removeBubble(bubble.getKey(), DISMISS_INVALID_INTENT)); mMainExecutor.execute(() -> removeBubble(bubble.getKey(), DISMISS_INVALID_INTENT));
}); });
try { try {

View File

@@ -16,7 +16,6 @@
package com.android.wm.shell.common; package com.android.wm.shell.common;
import android.os.Handler;
import android.os.RemoteException; import android.os.RemoteException;
import android.view.IDisplayWindowRotationCallback; import android.view.IDisplayWindowRotationCallback;
import android.view.IDisplayWindowRotationController; import android.view.IDisplayWindowRotationController;
@@ -37,7 +36,7 @@ import java.util.ArrayList;
*/ */
public class DisplayChangeController { public class DisplayChangeController {
private final Handler mHandler; private final ShellExecutor mMainExecutor;
private final IWindowManager mWmService; private final IWindowManager mWmService;
private final IDisplayWindowRotationController mControllerImpl; private final IDisplayWindowRotationController mControllerImpl;
@@ -45,8 +44,8 @@ public class DisplayChangeController {
new ArrayList<>(); new ArrayList<>();
private final ArrayList<OnDisplayChangingListener> mTmpListeners = new ArrayList<>(); private final ArrayList<OnDisplayChangingListener> mTmpListeners = new ArrayList<>();
public DisplayChangeController(Handler mainHandler, IWindowManager wmService) { public DisplayChangeController(IWindowManager wmService, ShellExecutor mainExecutor) {
mHandler = mainHandler; mMainExecutor = mainExecutor;
mWmService = wmService; mWmService = wmService;
mControllerImpl = new DisplayWindowRotationControllerImpl(); mControllerImpl = new DisplayWindowRotationControllerImpl();
try { try {
@@ -97,7 +96,7 @@ public class DisplayChangeController {
@Override @Override
public void onRotateDisplay(int displayId, final int fromRotation, public void onRotateDisplay(int displayId, final int fromRotation,
final int toRotation, IDisplayWindowRotationCallback callback) { final int toRotation, IDisplayWindowRotationCallback callback) {
mHandler.post(() -> { mMainExecutor.execute(() -> {
DisplayChangeController.this.onRotateDisplay(displayId, fromRotation, toRotation, DisplayChangeController.this.onRotateDisplay(displayId, fromRotation, toRotation,
callback); callback);
}); });

View File

@@ -20,7 +20,6 @@ import android.annotation.Nullable;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.RemoteException; import android.os.RemoteException;
import android.util.Slog; import android.util.Slog;
import android.util.SparseArray; import android.util.SparseArray;
@@ -44,7 +43,7 @@ import java.util.ArrayList;
public class DisplayController { public class DisplayController {
private static final String TAG = "DisplayController"; private static final String TAG = "DisplayController";
private final Handler mHandler; private final ShellExecutor mMainExecutor;
private final Context mContext; private final Context mContext;
private final IWindowManager mWmService; private final IWindowManager mWmService;
private final DisplayChangeController mChangeController; private final DisplayChangeController mChangeController;
@@ -61,12 +60,12 @@ public class DisplayController {
return displayManager.getDisplay(displayId); return displayManager.getDisplay(displayId);
} }
public DisplayController(Context context, Handler handler, public DisplayController(Context context, IWindowManager wmService,
IWindowManager wmService) { ShellExecutor mainExecutor) {
mHandler = handler; mMainExecutor = mainExecutor;
mContext = context; mContext = context;
mWmService = wmService; mWmService = wmService;
mChangeController = new DisplayChangeController(mHandler, mWmService); mChangeController = new DisplayChangeController(mWmService, mainExecutor);
mDisplayContainerListener = new DisplayWindowListenerImpl(); mDisplayContainerListener = new DisplayWindowListenerImpl();
try { try {
mWmService.registerDisplayWindowListener(mDisplayContainerListener); mWmService.registerDisplayWindowListener(mDisplayContainerListener);
@@ -229,35 +228,35 @@ public class DisplayController {
private class DisplayWindowListenerImpl extends IDisplayWindowListener.Stub { private class DisplayWindowListenerImpl extends IDisplayWindowListener.Stub {
@Override @Override
public void onDisplayAdded(int displayId) { public void onDisplayAdded(int displayId) {
mHandler.post(() -> { mMainExecutor.execute(() -> {
DisplayController.this.onDisplayAdded(displayId); DisplayController.this.onDisplayAdded(displayId);
}); });
} }
@Override @Override
public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
mHandler.post(() -> { mMainExecutor.execute(() -> {
DisplayController.this.onDisplayConfigurationChanged(displayId, newConfig); DisplayController.this.onDisplayConfigurationChanged(displayId, newConfig);
}); });
} }
@Override @Override
public void onDisplayRemoved(int displayId) { public void onDisplayRemoved(int displayId) {
mHandler.post(() -> { mMainExecutor.execute(() -> {
DisplayController.this.onDisplayRemoved(displayId); DisplayController.this.onDisplayRemoved(displayId);
}); });
} }
@Override @Override
public void onFixedRotationStarted(int displayId, int newRotation) { public void onFixedRotationStarted(int displayId, int newRotation) {
mHandler.post(() -> { mMainExecutor.execute(() -> {
DisplayController.this.onFixedRotationStarted(displayId, newRotation); DisplayController.this.onFixedRotationStarted(displayId, newRotation);
}); });
} }
@Override @Override
public void onFixedRotationFinished(int displayId) { public void onFixedRotationFinished(int displayId) {
mHandler.post(() -> { mMainExecutor.execute(() -> {
DisplayController.this.onFixedRotationFinished(displayId); DisplayController.this.onFixedRotationFinished(displayId);
}); });
} }

View File

@@ -40,10 +40,12 @@ import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator; import android.view.animation.PathInterpolator;
import androidx.annotation.BinderThread; import androidx.annotation.BinderThread;
import androidx.annotation.VisibleForTesting;
import com.android.internal.view.IInputMethodManager; import com.android.internal.view.IInputMethodManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
/** /**
@@ -64,7 +66,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
private static final int FLOATING_IME_BOTTOM_INSET = -80; private static final int FLOATING_IME_BOTTOM_INSET = -80;
protected final IWindowManager mWmService; protected final IWindowManager mWmService;
protected final Executor mExecutor; protected final Executor mMainExecutor;
private final TransactionPool mTransactionPool; private final TransactionPool mTransactionPool;
private final DisplayController mDisplayController; private final DisplayController mDisplayController;
private final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>(); private final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>();
@@ -73,10 +75,10 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
public DisplayImeController(IWindowManager wmService, DisplayController displayController, public DisplayImeController(IWindowManager wmService, DisplayController displayController,
Executor mainExecutor, TransactionPool transactionPool) { Executor mainExecutor, TransactionPool transactionPool) {
mExecutor = mainExecutor;
mWmService = wmService; mWmService = wmService;
mTransactionPool = transactionPool;
mDisplayController = displayController; mDisplayController = displayController;
mMainExecutor = mainExecutor;
mTransactionPool = transactionPool;
} }
/** Starts monitor displays changes and set insets controller for each displays. */ /** Starts monitor displays changes and set insets controller for each displays. */
@@ -90,11 +92,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
// WM will defer IME inset handling to it in multi-window scenarious. // WM will defer IME inset handling to it in multi-window scenarious.
PerDisplay pd = new PerDisplay(displayId, PerDisplay pd = new PerDisplay(displayId,
mDisplayController.getDisplayLayout(displayId).rotation()); mDisplayController.getDisplayLayout(displayId).rotation());
try { pd.register();
mWmService.setDisplayWindowInsetsController(displayId, pd);
} catch (RemoteException e) {
Slog.w(TAG, "Unable to set insets controller on display " + displayId);
}
mImePerDisplay.put(displayId, pd); mImePerDisplay.put(displayId, pd);
} }
@@ -182,9 +180,11 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
} }
/** An implementation of {@link IDisplayWindowInsetsController} for a given display id. */ /** An implementation of {@link IDisplayWindowInsetsController} for a given display id. */
public class PerDisplay extends IDisplayWindowInsetsController.Stub { public class PerDisplay {
final int mDisplayId; final int mDisplayId;
final InsetsState mInsetsState = new InsetsState(); final InsetsState mInsetsState = new InsetsState();
protected final DisplayWindowInsetsControllerImpl mInsetsControllerImpl =
new DisplayWindowInsetsControllerImpl();
InsetsSourceControl mImeSourceControl = null; InsetsSourceControl mImeSourceControl = null;
int mAnimationDirection = DIRECTION_NONE; int mAnimationDirection = DIRECTION_NONE;
ValueAnimator mAnimation = null; ValueAnimator mAnimation = null;
@@ -198,10 +198,16 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
mRotation = initialRotation; mRotation = initialRotation;
} }
@BinderThread public void register() {
@Override try {
public void insetsChanged(InsetsState insetsState) { mWmService.setDisplayWindowInsetsController(mDisplayId, mInsetsControllerImpl);
mExecutor.execute(() -> { } catch (RemoteException e) {
Slog.w(TAG, "Unable to set insets controller on display " + mDisplayId);
}
}
protected void insetsChanged(InsetsState insetsState) {
mMainExecutor.execute(() -> {
if (mInsetsState.equals(insetsState)) { if (mInsetsState.equals(insetsState)) {
return; return;
} }
@@ -220,9 +226,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}); });
} }
@BinderThread @VisibleForTesting
@Override protected void insetsControlChanged(InsetsState insetsState,
public void insetsControlChanged(InsetsState insetsState,
InsetsSourceControl[] activeControls) { InsetsSourceControl[] activeControls) {
insetsChanged(insetsState); insetsChanged(insetsState);
if (activeControls != null) { if (activeControls != null) {
@@ -231,7 +236,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
continue; continue;
} }
if (activeControl.getType() == InsetsState.ITYPE_IME) { if (activeControl.getType() == InsetsState.ITYPE_IME) {
mExecutor.execute(() -> { mMainExecutor.execute(() -> {
final Point lastSurfacePosition = mImeSourceControl != null final Point lastSurfacePosition = mImeSourceControl != null
? mImeSourceControl.getSurfacePosition() : null; ? mImeSourceControl.getSurfacePosition() : null;
final boolean positionChanged = final boolean positionChanged =
@@ -271,30 +276,25 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
} }
} }
@BinderThread protected void showInsets(int types, boolean fromIme) {
@Override
public void showInsets(int types, boolean fromIme) {
if ((types & WindowInsets.Type.ime()) == 0) { if ((types & WindowInsets.Type.ime()) == 0) {
return; return;
} }
if (DEBUG) Slog.d(TAG, "Got showInsets for ime"); if (DEBUG) Slog.d(TAG, "Got showInsets for ime");
mExecutor.execute(() -> startAnimation(true /* show */, false /* forceRestart */)); mMainExecutor.execute(() -> startAnimation(true /* show */, false /* forceRestart */));
} }
@BinderThread
@Override protected void hideInsets(int types, boolean fromIme) {
public void hideInsets(int types, boolean fromIme) {
if ((types & WindowInsets.Type.ime()) == 0) { if ((types & WindowInsets.Type.ime()) == 0) {
return; return;
} }
if (DEBUG) Slog.d(TAG, "Got hideInsets for ime"); if (DEBUG) Slog.d(TAG, "Got hideInsets for ime");
mExecutor.execute(() -> startAnimation(false /* show */, false /* forceRestart */)); mMainExecutor.execute(() -> startAnimation(false /* show */, false /* forceRestart */));
} }
@BinderThread
@Override
public void topFocusedWindowChanged(String packageName) { public void topFocusedWindowChanged(String packageName) {
// no-op // Do nothing
} }
/** /**
@@ -457,6 +457,47 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
setVisibleDirectly(true /* visible */); setVisibleDirectly(true /* visible */);
} }
} }
@VisibleForTesting
@BinderThread
public class DisplayWindowInsetsControllerImpl
extends IDisplayWindowInsetsController.Stub {
@Override
public void topFocusedWindowChanged(String packageName) throws RemoteException {
mMainExecutor.execute(() -> {
PerDisplay.this.topFocusedWindowChanged(packageName);
});
}
@Override
public void insetsChanged(InsetsState insetsState) throws RemoteException {
mMainExecutor.execute(() -> {
PerDisplay.this.insetsChanged(insetsState);
});
}
@Override
public void insetsControlChanged(InsetsState insetsState,
InsetsSourceControl[] activeControls) throws RemoteException {
mMainExecutor.execute(() -> {
PerDisplay.this.insetsControlChanged(insetsState, activeControls);
});
}
@Override
public void showInsets(int types, boolean fromIme) throws RemoteException {
mMainExecutor.execute(() -> {
PerDisplay.this.showInsets(types, fromIme);
});
}
@Override
public void hideInsets(int types, boolean fromIme) throws RemoteException {
mMainExecutor.execute(() -> {
PerDisplay.this.hideInsets(types, fromIme);
});
}
}
} }
void removeImeSurface() { void removeImeSurface() {

View File

@@ -50,6 +50,16 @@ public interface ShellExecutor extends Executor {
latch.await(waitTimeout, waitTimeUnit); latch.await(waitTimeout, waitTimeUnit);
} }
/**
* Convenience method to execute the blocking call with a default timeout.
*
* @throws InterruptedException if runnable does not return in the time specified by
* {@param waitTimeout}
*/
default void executeBlocking(Runnable runnable) throws InterruptedException {
executeBlocking(runnable, 2, TimeUnit.SECONDS);
}
/** /**
* See {@link android.os.Handler#postDelayed(Runnable, long)}. * See {@link android.os.Handler#postDelayed(Runnable, long)}.
*/ */

View File

@@ -16,16 +16,14 @@
package com.android.wm.shell.common; package com.android.wm.shell.common;
import android.annotation.BinderThread;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.os.Handler;
import android.util.Slog; import android.util.Slog;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import android.window.WindowContainerTransaction; import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransactionCallback; import android.window.WindowContainerTransactionCallback;
import android.window.WindowOrganizer; import android.window.WindowOrganizer;
import androidx.annotation.BinderThread;
import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.common.annotations.ShellMainThread;
import java.util.ArrayList; import java.util.ArrayList;
@@ -41,7 +39,7 @@ public final class SyncTransactionQueue {
private static final int REPLY_TIMEOUT = 5300; private static final int REPLY_TIMEOUT = 5300;
private final TransactionPool mTransactionPool; private final TransactionPool mTransactionPool;
private final Handler mHandler; private final ShellExecutor mMainExecutor;
// Sync Transactions currently don't support nesting or interleaving properly, so // Sync Transactions currently don't support nesting or interleaving properly, so
// queue up transactions to run them serially. // queue up transactions to run them serially.
@@ -59,9 +57,9 @@ public final class SyncTransactionQueue {
} }
}; };
public SyncTransactionQueue(TransactionPool pool, Handler handler) { public SyncTransactionQueue(TransactionPool pool, ShellExecutor mainExecutor) {
mTransactionPool = pool; mTransactionPool = pool;
mHandler = handler; mMainExecutor = mainExecutor;
} }
/** /**
@@ -152,14 +150,14 @@ public final class SyncTransactionQueue {
if (DEBUG) Slog.d(TAG, "Sending sync transaction: " + mWCT); if (DEBUG) Slog.d(TAG, "Sending sync transaction: " + mWCT);
mId = new WindowOrganizer().applySyncTransaction(mWCT, this); mId = new WindowOrganizer().applySyncTransaction(mWCT, this);
if (DEBUG) Slog.d(TAG, " Sent sync transaction. Got id=" + mId); if (DEBUG) Slog.d(TAG, " Sent sync transaction. Got id=" + mId);
mHandler.postDelayed(mOnReplyTimeout, REPLY_TIMEOUT); mMainExecutor.executeDelayed(mOnReplyTimeout, REPLY_TIMEOUT);
} }
@BinderThread @BinderThread
@Override @Override
public void onTransactionReady(int id, public void onTransactionReady(int id,
@NonNull SurfaceControl.Transaction t) { @NonNull SurfaceControl.Transaction t) {
mHandler.post(() -> { mMainExecutor.execute(() -> {
synchronized (mQueue) { synchronized (mQueue) {
if (mId != id) { if (mId != id) {
Slog.e(TAG, "Got an unexpected onTransactionReady. Expected " Slog.e(TAG, "Got an unexpected onTransactionReady. Expected "
@@ -167,7 +165,7 @@ public final class SyncTransactionQueue {
return; return;
} }
mInFlight = null; mInFlight = null;
mHandler.removeCallbacks(mOnReplyTimeout); mMainExecutor.removeCallbacks(mOnReplyTimeout);
if (DEBUG) Slog.d(TAG, "onTransactionReady id=" + mId); if (DEBUG) Slog.d(TAG, "onTransactionReady id=" + mId);
mQueue.remove(this); mQueue.remove(this);
onTransactionReceived(t); onTransactionReceived(t);

View File

@@ -71,11 +71,11 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler.
private final IActivityTaskManager mActivityTaskManager; private final IActivityTaskManager mActivityTaskManager;
// NOTE: In this case we do want to use a handler since we rely on the message system to // NOTE: In this case we do want to use a handler since we rely on the message system to
// efficiently dedupe sequential calls // efficiently dedupe sequential calls
private Handler mHandler; private Handler mMainHandler;
public TaskStackListenerImpl(Handler handler) { public TaskStackListenerImpl(Handler mainHandler) {
mActivityTaskManager = ActivityTaskManager.getService(); mActivityTaskManager = ActivityTaskManager.getService();
mHandler = new Handler(handler.getLooper(), this); mMainHandler = new Handler(mainHandler.getLooper(), this);
} }
@VisibleForTesting @VisibleForTesting
@@ -84,8 +84,8 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler.
} }
@VisibleForTesting @VisibleForTesting
void setHandler(Handler handler) { void setHandler(Handler mainHandler) {
mHandler = handler; mMainHandler = mainHandler;
} }
public void addListener(TaskStackListenerCallback listener) { public void addListener(TaskStackListenerCallback listener) {
@@ -124,13 +124,13 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler.
@Override @Override
public void onRecentTaskListUpdated() { public void onRecentTaskListUpdated() {
mHandler.obtainMessage(ON_TASK_LIST_UPDATED).sendToTarget(); mMainHandler.obtainMessage(ON_TASK_LIST_UPDATED).sendToTarget();
} }
@Override @Override
public void onRecentTaskListFrozenChanged(boolean frozen) { public void onRecentTaskListFrozenChanged(boolean frozen) {
mHandler.obtainMessage(ON_TASK_LIST_FROZEN_UNFROZEN, frozen ? 1 : 0, 0 /* unused */) mMainHandler.obtainMessage(ON_TASK_LIST_FROZEN_UNFROZEN, frozen ? 1 : 0,
.sendToTarget(); 0 /* unused */).sendToTarget();
} }
@Override @Override
@@ -147,48 +147,50 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler.
} }
mTmpListeners.clear(); mTmpListeners.clear();
mHandler.removeMessages(ON_TASK_STACK_CHANGED); mMainHandler.removeMessages(ON_TASK_STACK_CHANGED);
mHandler.sendEmptyMessage(ON_TASK_STACK_CHANGED); mMainHandler.sendEmptyMessage(ON_TASK_STACK_CHANGED);
} }
@Override @Override
public void onTaskProfileLocked(int taskId, int userId) { public void onTaskProfileLocked(int taskId, int userId) {
mHandler.obtainMessage(ON_TASK_PROFILE_LOCKED, taskId, userId).sendToTarget(); mMainHandler.obtainMessage(ON_TASK_PROFILE_LOCKED, taskId, userId).sendToTarget();
} }
@Override @Override
public void onTaskDisplayChanged(int taskId, int newDisplayId) { public void onTaskDisplayChanged(int taskId, int newDisplayId) {
mHandler.obtainMessage(ON_TASK_DISPLAY_CHANGED, taskId, newDisplayId).sendToTarget(); mMainHandler.obtainMessage(ON_TASK_DISPLAY_CHANGED, taskId,
newDisplayId).sendToTarget();
} }
@Override @Override
public void onTaskCreated(int taskId, ComponentName componentName) { public void onTaskCreated(int taskId, ComponentName componentName) {
mHandler.obtainMessage(ON_TASK_CREATED, taskId, 0, componentName).sendToTarget(); mMainHandler.obtainMessage(ON_TASK_CREATED, taskId, 0, componentName).sendToTarget();
} }
@Override @Override
public void onTaskRemoved(int taskId) { public void onTaskRemoved(int taskId) {
mHandler.obtainMessage(ON_TASK_REMOVED, taskId, 0).sendToTarget(); mMainHandler.obtainMessage(ON_TASK_REMOVED, taskId, 0).sendToTarget();
} }
@Override @Override
public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) { public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
mHandler.obtainMessage(ON_TASK_MOVED_TO_FRONT, taskInfo).sendToTarget(); mMainHandler.obtainMessage(ON_TASK_MOVED_TO_FRONT, taskInfo).sendToTarget();
} }
@Override @Override
public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo) { public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo) {
mHandler.obtainMessage(ON_TASK_DESCRIPTION_CHANGED, taskInfo).sendToTarget(); mMainHandler.obtainMessage(ON_TASK_DESCRIPTION_CHANGED, taskInfo).sendToTarget();
} }
@Override @Override
public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
mHandler.obtainMessage(ON_TASK_SNAPSHOT_CHANGED, taskId, 0, snapshot).sendToTarget(); mMainHandler.obtainMessage(ON_TASK_SNAPSHOT_CHANGED, taskId, 0, snapshot)
.sendToTarget();
} }
@Override @Override
public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) { public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
mHandler.obtainMessage(ON_BACK_PRESSED_ON_TASK_ROOT, taskInfo).sendToTarget(); mMainHandler.obtainMessage(ON_BACK_PRESSED_ON_TASK_ROOT, taskInfo).sendToTarget();
} }
@Override @Override
@@ -198,44 +200,44 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler.
args.argi1 = userId; args.argi1 = userId;
args.argi2 = taskId; args.argi2 = taskId;
args.argi3 = stackId; args.argi3 = stackId;
mHandler.removeMessages(ON_ACTIVITY_PINNED); mMainHandler.removeMessages(ON_ACTIVITY_PINNED);
mHandler.obtainMessage(ON_ACTIVITY_PINNED, args).sendToTarget(); mMainHandler.obtainMessage(ON_ACTIVITY_PINNED, args).sendToTarget();
} }
@Override @Override
public void onActivityUnpinned() { public void onActivityUnpinned() {
mHandler.removeMessages(ON_ACTIVITY_UNPINNED); mMainHandler.removeMessages(ON_ACTIVITY_UNPINNED);
mHandler.sendEmptyMessage(ON_ACTIVITY_UNPINNED); mMainHandler.sendEmptyMessage(ON_ACTIVITY_UNPINNED);
} }
@Override @Override
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, boolean homeTaskVisible, public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
boolean clearedTask, boolean wasVisible) { boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
final SomeArgs args = SomeArgs.obtain(); final SomeArgs args = SomeArgs.obtain();
args.arg1 = task; args.arg1 = task;
args.argi1 = homeTaskVisible ? 1 : 0; args.argi1 = homeTaskVisible ? 1 : 0;
args.argi2 = clearedTask ? 1 : 0; args.argi2 = clearedTask ? 1 : 0;
args.argi3 = wasVisible ? 1 : 0; args.argi3 = wasVisible ? 1 : 0;
mHandler.removeMessages(ON_ACTIVITY_RESTART_ATTEMPT); mMainHandler.removeMessages(ON_ACTIVITY_RESTART_ATTEMPT);
mHandler.obtainMessage(ON_ACTIVITY_RESTART_ATTEMPT, args).sendToTarget(); mMainHandler.obtainMessage(ON_ACTIVITY_RESTART_ATTEMPT, args).sendToTarget();
} }
@Override @Override
public void onActivityForcedResizable(String packageName, int taskId, int reason) { public void onActivityForcedResizable(String packageName, int taskId, int reason) {
mHandler.obtainMessage(ON_ACTIVITY_FORCED_RESIZABLE, taskId, reason, packageName) mMainHandler.obtainMessage(ON_ACTIVITY_FORCED_RESIZABLE, taskId, reason, packageName)
.sendToTarget(); .sendToTarget();
} }
@Override @Override
public void onActivityDismissingDockedStack() { public void onActivityDismissingDockedStack() {
mHandler.sendEmptyMessage(ON_ACTIVITY_DISMISSING_DOCKED_STACK); mMainHandler.sendEmptyMessage(ON_ACTIVITY_DISMISSING_DOCKED_STACK);
} }
@Override @Override
public void onActivityLaunchOnSecondaryDisplayFailed( public void onActivityLaunchOnSecondaryDisplayFailed(
ActivityManager.RunningTaskInfo taskInfo, ActivityManager.RunningTaskInfo taskInfo,
int requestedDisplayId) { int requestedDisplayId) {
mHandler.obtainMessage(ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED, mMainHandler.obtainMessage(ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED,
requestedDisplayId, requestedDisplayId,
0 /* unused */, 0 /* unused */,
taskInfo).sendToTarget(); taskInfo).sendToTarget();
@@ -245,25 +247,25 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler.
public void onActivityLaunchOnSecondaryDisplayRerouted( public void onActivityLaunchOnSecondaryDisplayRerouted(
ActivityManager.RunningTaskInfo taskInfo, ActivityManager.RunningTaskInfo taskInfo,
int requestedDisplayId) { int requestedDisplayId) {
mHandler.obtainMessage(ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED, mMainHandler.obtainMessage(ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED,
requestedDisplayId, 0 /* unused */, taskInfo).sendToTarget(); requestedDisplayId, 0 /* unused */, taskInfo).sendToTarget();
} }
@Override @Override
public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) {
mHandler.obtainMessage(ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE, taskId, mMainHandler.obtainMessage(ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE, taskId,
requestedOrientation).sendToTarget(); requestedOrientation).sendToTarget();
} }
@Override @Override
public void onActivityRotation(int displayId) { public void onActivityRotation(int displayId) {
mHandler.obtainMessage(ON_ACTIVITY_ROTATION, displayId, 0 /* unused */) mMainHandler.obtainMessage(ON_ACTIVITY_ROTATION, displayId, 0 /* unused */)
.sendToTarget(); .sendToTarget();
} }
@Override @Override
public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) { public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) {
mHandler.obtainMessage(ON_SIZE_COMPAT_MODE_ACTIVITY_CHANGED, displayId, mMainHandler.obtainMessage(ON_SIZE_COMPAT_MODE_ACTIVITY_CHANGED, displayId,
0 /* unused */, 0 /* unused */,
activityToken).sendToTarget(); activityToken).sendToTarget();
} }

View File

@@ -74,11 +74,11 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
public DragAndDropController(Context context, DisplayController displayController) { public DragAndDropController(Context context, DisplayController displayController) {
mContext = context; mContext = context;
mDisplayController = displayController; mDisplayController = displayController;
mDisplayController.addDisplayWindowListener(this);
} }
public void setSplitScreenController(Optional<LegacySplitScreen> splitscreen) { public void initialize(Optional<LegacySplitScreen> splitscreen) {
mLegacySplitScreen = splitscreen.orElse(null); mLegacySplitScreen = splitscreen.orElse(null);
mDisplayController.addDisplayWindowListener(this);
} }
@Override @Override

View File

@@ -25,6 +25,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -37,12 +38,15 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
private final Context mContext; private final Context mContext;
private final HideDisplayCutoutOrganizer mOrganizer; private final HideDisplayCutoutOrganizer mOrganizer;
private final ShellExecutor mMainExecutor;
@VisibleForTesting @VisibleForTesting
boolean mEnabled; boolean mEnabled;
HideDisplayCutoutController(Context context, HideDisplayCutoutOrganizer organizer) { HideDisplayCutoutController(Context context, HideDisplayCutoutOrganizer organizer,
ShellExecutor mainExecutor) {
mContext = context; mContext = context;
mOrganizer = organizer; mOrganizer = organizer;
mMainExecutor = mainExecutor;
updateStatus(); updateStatus();
} }
@@ -52,7 +56,7 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
*/ */
@Nullable @Nullable
public static HideDisplayCutoutController create( public static HideDisplayCutoutController create(
Context context, DisplayController displayController, Executor executor) { Context context, DisplayController displayController, ShellExecutor mainExecutor) {
// The SystemProperty is set for devices that support this feature and is used to control // The SystemProperty is set for devices that support this feature and is used to control
// whether to create the HideDisplayCutout instance. // whether to create the HideDisplayCutout instance.
// It's defined in the device.mk (e.g. device/google/crosshatch/device.mk). // It's defined in the device.mk (e.g. device/google/crosshatch/device.mk).
@@ -61,8 +65,8 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
} }
HideDisplayCutoutOrganizer organizer = HideDisplayCutoutOrganizer organizer =
new HideDisplayCutoutOrganizer(context, displayController, executor); new HideDisplayCutoutOrganizer(context, displayController, mainExecutor);
return new HideDisplayCutoutController(context, organizer); return new HideDisplayCutoutController(context, organizer, mainExecutor);
} }
@VisibleForTesting @VisibleForTesting

View File

@@ -42,6 +42,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.R; import com.android.internal.R;
import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.List; import java.util.List;
@@ -90,8 +91,8 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer {
}; };
HideDisplayCutoutOrganizer(Context context, DisplayController displayController, HideDisplayCutoutOrganizer(Context context, DisplayController displayController,
Executor executor) { ShellExecutor mainExecutor) {
super(executor); super(mainExecutor);
mContext = context; mContext = context;
mDisplayController = displayController; mDisplayController = displayController;
} }

View File

@@ -24,7 +24,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Handler;
import android.util.Slog; import android.util.Slog;
import android.view.Choreographer; import android.view.Choreographer;
import android.view.SurfaceControl; import android.view.SurfaceControl;
@@ -33,6 +32,7 @@ import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction; import android.window.WindowContainerTransaction;
import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.TransactionPool;
class DividerImeController implements DisplayImeController.ImePositionProcessor { class DividerImeController implements DisplayImeController.ImePositionProcessor {
@@ -43,7 +43,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
private final LegacySplitScreenTaskListener mSplits; private final LegacySplitScreenTaskListener mSplits;
private final TransactionPool mTransactionPool; private final TransactionPool mTransactionPool;
private final Handler mHandler; private final ShellExecutor mMainExecutor;
private final TaskOrganizer mTaskOrganizer; private final TaskOrganizer mTaskOrganizer;
/** /**
@@ -94,10 +94,10 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
private boolean mAdjustedWhileHidden = false; private boolean mAdjustedWhileHidden = false;
DividerImeController(LegacySplitScreenTaskListener splits, TransactionPool pool, DividerImeController(LegacySplitScreenTaskListener splits, TransactionPool pool,
Handler handler, TaskOrganizer taskOrganizer) { ShellExecutor mainExecutor, TaskOrganizer taskOrganizer) {
mSplits = splits; mSplits = splits;
mTransactionPool = pool; mTransactionPool = pool;
mHandler = handler; mMainExecutor = mainExecutor;
mTaskOrganizer = taskOrganizer; mTaskOrganizer = taskOrganizer;
} }
@@ -377,7 +377,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
/** Completely aborts/resets adjustment state */ /** Completely aborts/resets adjustment state */
public void pause(int displayId) { public void pause(int displayId) {
if (DEBUG) Slog.d(TAG, "ime pause posting " + dumpState()); if (DEBUG) Slog.d(TAG, "ime pause posting " + dumpState());
mHandler.post(() -> { mMainExecutor.execute(() -> {
if (DEBUG) Slog.d(TAG, "ime pause run posted " + dumpState()); if (DEBUG) Slog.d(TAG, "ime pause run posted " + dumpState());
if (mPaused) { if (mPaused) {
return; return;
@@ -396,7 +396,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
public void resume(int displayId) { public void resume(int displayId) {
if (DEBUG) Slog.d(TAG, "ime resume posting " + dumpState()); if (DEBUG) Slog.d(TAG, "ime resume posting " + dumpState());
mHandler.post(() -> { mMainExecutor.execute(() -> {
if (DEBUG) Slog.d(TAG, "ime resume run posted " + dumpState()); if (DEBUG) Slog.d(TAG, "ime resume run posted " + dumpState());
if (!mPaused) { if (!mPaused) {
return; return;

View File

@@ -22,12 +22,12 @@ import static com.android.wm.shell.legacysplitscreen.ForcedResizableInfoActivity
import android.app.ActivityOptions; import android.app.ActivityOptions;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Handler;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.ArraySet; import android.util.ArraySet;
import android.widget.Toast; import android.widget.Toast;
import com.android.wm.shell.R; import com.android.wm.shell.R;
import com.android.wm.shell.common.ShellExecutor;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -40,7 +40,7 @@ final class ForcedResizableInfoActivityController implements DividerView.Divider
private static final int TIMEOUT = 1000; private static final int TIMEOUT = 1000;
private final Context mContext; private final Context mContext;
private final Handler mHandler = new Handler(); private final ShellExecutor mMainExecutor;
private final ArraySet<PendingTaskRecord> mPendingTasks = new ArraySet<>(); private final ArraySet<PendingTaskRecord> mPendingTasks = new ArraySet<>();
private final ArraySet<String> mPackagesShownInSession = new ArraySet<>(); private final ArraySet<String> mPackagesShownInSession = new ArraySet<>();
private boolean mDividerDragging; private boolean mDividerDragging;
@@ -69,15 +69,17 @@ final class ForcedResizableInfoActivityController implements DividerView.Divider
} }
ForcedResizableInfoActivityController(Context context, ForcedResizableInfoActivityController(Context context,
LegacySplitScreenController splitScreenController) { LegacySplitScreenController splitScreenController,
ShellExecutor mainExecutor) {
mContext = context; mContext = context;
mMainExecutor = mainExecutor;
splitScreenController.registerInSplitScreenListener(mDockedStackExistsListener); splitScreenController.registerInSplitScreenListener(mDockedStackExistsListener);
} }
@Override @Override
public void onDraggingStart() { public void onDraggingStart() {
mDividerDragging = true; mDividerDragging = true;
mHandler.removeCallbacks(mTimeoutRunnable); mMainExecutor.removeCallbacks(mTimeoutRunnable);
} }
@Override @Override
@@ -111,7 +113,7 @@ final class ForcedResizableInfoActivityController implements DividerView.Divider
} }
private void showPending() { private void showPending() {
mHandler.removeCallbacks(mTimeoutRunnable); mMainExecutor.removeCallbacks(mTimeoutRunnable);
for (int i = mPendingTasks.size() - 1; i >= 0; i--) { for (int i = mPendingTasks.size() - 1; i >= 0; i--) {
PendingTaskRecord pendingRecord = mPendingTasks.valueAt(i); PendingTaskRecord pendingRecord = mPendingTasks.valueAt(i);
Intent intent = new Intent(mContext, ForcedResizableInfoActivity.class); Intent intent = new Intent(mContext, ForcedResizableInfoActivity.class);
@@ -127,8 +129,8 @@ final class ForcedResizableInfoActivityController implements DividerView.Divider
} }
private void postTimeout() { private void postTimeout() {
mHandler.removeCallbacks(mTimeoutRunnable); mMainExecutor.removeCallbacks(mTimeoutRunnable);
mHandler.postDelayed(mTimeoutRunnable, TIMEOUT); mMainExecutor.executeDelayed(mTimeoutRunnable, TIMEOUT);
} }
private boolean debounce(String packageName) { private boolean debounce(String packageName) {

View File

@@ -30,7 +30,6 @@ import android.app.ActivityTaskManager;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException; import android.os.RemoteException;
import android.provider.Settings; import android.provider.Settings;
import android.util.Slog; import android.util.Slog;
@@ -49,6 +48,7 @@ import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TaskStackListenerCallback; import com.android.wm.shell.common.TaskStackListenerCallback;
@@ -80,7 +80,7 @@ public class LegacySplitScreenController implements LegacySplitScreen,
private final DividerImeController mImePositionProcessor; private final DividerImeController mImePositionProcessor;
private final DividerState mDividerState = new DividerState(); private final DividerState mDividerState = new DividerState();
private final ForcedResizableInfoActivityController mForcedResizableController; private final ForcedResizableInfoActivityController mForcedResizableController;
private final Handler mHandler; private final ShellExecutor mMainExecutor;
private final LegacySplitScreenTaskListener mSplits; private final LegacySplitScreenTaskListener mSplits;
private final SystemWindows mSystemWindows; private final SystemWindows mSystemWindows;
final TransactionPool mTransactionPool; final TransactionPool mTransactionPool;
@@ -112,21 +112,23 @@ public class LegacySplitScreenController implements LegacySplitScreen,
public LegacySplitScreenController(Context context, public LegacySplitScreenController(Context context,
DisplayController displayController, SystemWindows systemWindows, DisplayController displayController, SystemWindows systemWindows,
DisplayImeController imeController, Handler handler, TransactionPool transactionPool, DisplayImeController imeController, TransactionPool transactionPool,
ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue, ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
TaskStackListenerImpl taskStackListener, Transitions transitions) { TaskStackListenerImpl taskStackListener, Transitions transitions,
ShellExecutor mainExecutor) {
mContext = context; mContext = context;
mDisplayController = displayController; mDisplayController = displayController;
mSystemWindows = systemWindows; mSystemWindows = systemWindows;
mImeController = imeController; mImeController = imeController;
mHandler = handler; mMainExecutor = mainExecutor;
mForcedResizableController = new ForcedResizableInfoActivityController(context, this); mForcedResizableController = new ForcedResizableInfoActivityController(context, this,
mainExecutor);
mTransactionPool = transactionPool; mTransactionPool = transactionPool;
mWindowManagerProxy = new WindowManagerProxy(syncQueue, shellTaskOrganizer); mWindowManagerProxy = new WindowManagerProxy(syncQueue, shellTaskOrganizer);
mTaskOrganizer = shellTaskOrganizer; mTaskOrganizer = shellTaskOrganizer;
mSplits = new LegacySplitScreenTaskListener(this, shellTaskOrganizer, transitions, mSplits = new LegacySplitScreenTaskListener(this, shellTaskOrganizer, transitions,
syncQueue); syncQueue);
mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler, mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mMainExecutor,
shellTaskOrganizer); shellTaskOrganizer);
mRotationController = mRotationController =
(display, fromRotation, toRotation, wct) -> { (display, fromRotation, toRotation, wct) -> {
@@ -271,11 +273,6 @@ public class LegacySplitScreenController implements LegacySplitScreen,
} }
} }
/** Posts task to handler dealing with divider. */
void post(Runnable task) {
mHandler.post(task);
}
@Override @Override
public DividerView getDividerView() { public DividerView getDividerView() {
return mView; return mView;
@@ -345,7 +342,7 @@ public class LegacySplitScreenController implements LegacySplitScreen,
} }
void onTaskVanished() { void onTaskVanished() {
mHandler.post(this::removeDivider); removeDivider();
} }
private void updateVisibility(final boolean visible) { private void updateVisibility(final boolean visible) {
@@ -379,7 +376,7 @@ public class LegacySplitScreenController implements LegacySplitScreen,
@Override @Override
public void setMinimized(final boolean minimized) { public void setMinimized(final boolean minimized) {
if (DEBUG) Slog.d(TAG, "posting ext setMinimized " + minimized + " vis:" + mVisible); if (DEBUG) Slog.d(TAG, "posting ext setMinimized " + minimized + " vis:" + mVisible);
mHandler.post(() -> { mMainExecutor.execute(() -> {
if (DEBUG) Slog.d(TAG, "run posted ext setMinimized " + minimized + " vis:" + mVisible); if (DEBUG) Slog.d(TAG, "run posted ext setMinimized " + minimized + " vis:" + mVisible);
if (!mVisible) { if (!mVisible) {
return; return;

View File

@@ -204,7 +204,7 @@ class LegacySplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
return; return;
} }
mSplitScreenController.post(() -> handleTaskInfoChanged(taskInfo)); handleTaskInfoChanged(taskInfo);
} }
} }

View File

@@ -38,11 +38,11 @@ import java.util.ArrayList;
public class PinnedStackListenerForwarder { public class PinnedStackListenerForwarder {
private final IPinnedStackListener mListenerImpl = new PinnedStackListenerImpl(); private final IPinnedStackListener mListenerImpl = new PinnedStackListenerImpl();
private final ShellExecutor mShellMainExecutor; private final ShellExecutor mMainExecutor;
private final ArrayList<PinnedStackListener> mListeners = new ArrayList<>(); private final ArrayList<PinnedStackListener> mListeners = new ArrayList<>();
public PinnedStackListenerForwarder(ShellExecutor shellMainExecutor) { public PinnedStackListenerForwarder(ShellExecutor mainExecutor) {
mShellMainExecutor = shellMainExecutor; mMainExecutor = mainExecutor;
} }
/** Adds a listener to receive updates from the WindowManagerService. */ /** Adds a listener to receive updates from the WindowManagerService. */
@@ -94,35 +94,35 @@ public class PinnedStackListenerForwarder {
private class PinnedStackListenerImpl extends IPinnedStackListener.Stub { private class PinnedStackListenerImpl extends IPinnedStackListener.Stub {
@Override @Override
public void onMovementBoundsChanged(boolean fromImeAdjustment) { public void onMovementBoundsChanged(boolean fromImeAdjustment) {
mShellMainExecutor.execute(() -> { mMainExecutor.execute(() -> {
PinnedStackListenerForwarder.this.onMovementBoundsChanged(fromImeAdjustment); PinnedStackListenerForwarder.this.onMovementBoundsChanged(fromImeAdjustment);
}); });
} }
@Override @Override
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
mShellMainExecutor.execute(() -> { mMainExecutor.execute(() -> {
PinnedStackListenerForwarder.this.onImeVisibilityChanged(imeVisible, imeHeight); PinnedStackListenerForwarder.this.onImeVisibilityChanged(imeVisible, imeHeight);
}); });
} }
@Override @Override
public void onActionsChanged(ParceledListSlice<RemoteAction> actions) { public void onActionsChanged(ParceledListSlice<RemoteAction> actions) {
mShellMainExecutor.execute(() -> { mMainExecutor.execute(() -> {
PinnedStackListenerForwarder.this.onActionsChanged(actions); PinnedStackListenerForwarder.this.onActionsChanged(actions);
}); });
} }
@Override @Override
public void onActivityHidden(ComponentName componentName) { public void onActivityHidden(ComponentName componentName) {
mShellMainExecutor.execute(() -> { mMainExecutor.execute(() -> {
PinnedStackListenerForwarder.this.onActivityHidden(componentName); PinnedStackListenerForwarder.this.onActivityHidden(componentName);
}); });
} }
@Override @Override
public void onAspectRatioChanged(float aspectRatio) { public void onAspectRatioChanged(float aspectRatio) {
mShellMainExecutor.execute(() -> { mMainExecutor.execute(() -> {
PinnedStackListenerForwarder.this.onAspectRatioChanged(aspectRatio); PinnedStackListenerForwarder.this.onAspectRatioChanged(aspectRatio);
}); });
} }

View File

@@ -155,7 +155,7 @@ public class PipTouchHandler {
PipTaskOrganizer pipTaskOrganizer, PipTaskOrganizer pipTaskOrganizer,
FloatingContentCoordinator floatingContentCoordinator, FloatingContentCoordinator floatingContentCoordinator,
PipUiEventLogger pipUiEventLogger, PipUiEventLogger pipUiEventLogger,
ShellExecutor shellMainExecutor) { ShellExecutor mainExecutor) {
// Initialize the Pip input consumer // Initialize the Pip input consumer
mContext = context; mContext = context;
mAccessibilityManager = context.getSystemService(AccessibilityManager.class); mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
@@ -186,7 +186,7 @@ public class PipTouchHandler {
mFloatingContentCoordinator = floatingContentCoordinator; mFloatingContentCoordinator = floatingContentCoordinator;
mConnection = new PipAccessibilityInteractionConnection(mContext, pipBoundsState, mConnection = new PipAccessibilityInteractionConnection(mContext, pipBoundsState,
mMotionHelper, pipTaskOrganizer, mPipBoundsAlgorithm.getSnapAlgorithm(), mMotionHelper, pipTaskOrganizer, mPipBoundsAlgorithm.getSnapAlgorithm(),
this::onAccessibilityShowMenu, this::updateMovementBounds, shellMainExecutor); this::onAccessibilityShowMenu, this::updateMovementBounds, mainExecutor);
mPipUiEventLogger = pipUiEventLogger; mPipUiEventLogger = pipUiEventLogger;

View File

@@ -27,6 +27,8 @@ import android.testing.TestableLooper;
import androidx.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.wm.shell.common.ShellExecutor;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -44,12 +46,14 @@ public class HideDisplayCutoutControllerTest {
private HideDisplayCutoutController mHideDisplayCutoutController; private HideDisplayCutoutController mHideDisplayCutoutController;
@Mock @Mock
private HideDisplayCutoutOrganizer mMockDisplayAreaOrganizer; private HideDisplayCutoutOrganizer mMockDisplayAreaOrganizer;
@Mock
private ShellExecutor mMockMainExecutor;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mHideDisplayCutoutController = new HideDisplayCutoutController( mHideDisplayCutoutController = new HideDisplayCutoutController(
mContext, mMockDisplayAreaOrganizer); mContext, mMockDisplayAreaOrganizer, mMockMainExecutor);
} }
@Test @Test

View File

@@ -50,6 +50,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.R; import com.android.internal.R;
import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -72,6 +73,9 @@ public class HideDisplayCutoutOrganizerTest {
private DisplayController mMockDisplayController; private DisplayController mMockDisplayController;
private HideDisplayCutoutOrganizer mOrganizer; private HideDisplayCutoutOrganizer mOrganizer;
@Mock
private ShellExecutor mMockMainExecutor;
private DisplayAreaInfo mDisplayAreaInfo; private DisplayAreaInfo mDisplayAreaInfo;
private SurfaceControl mLeash; private SurfaceControl mLeash;
@@ -93,7 +97,7 @@ public class HideDisplayCutoutOrganizerTest {
when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay); when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
HideDisplayCutoutOrganizer organizer = new HideDisplayCutoutOrganizer( HideDisplayCutoutOrganizer organizer = new HideDisplayCutoutOrganizer(
mContext, mMockDisplayController, Runnable::run); mContext, mMockDisplayController, mMockMainExecutor);
mOrganizer = Mockito.spy(organizer); mOrganizer = Mockito.spy(organizer);
doNothing().when(mOrganizer).unregisterOrganizer(); doNothing().when(mOrganizer).unregisterOrganizer();
doNothing().when(mOrganizer).applyBoundsAndOffsets(any(), any(), any(), any()); doNothing().when(mOrganizer).applyBoundsAndOffsets(any(), any(), any(), any());

View File

@@ -73,7 +73,7 @@ public class PipTouchHandlerTest extends ShellTestCase {
private PipUiEventLogger mPipUiEventLogger; private PipUiEventLogger mPipUiEventLogger;
@Mock @Mock
private ShellExecutor mShellMainExecutor; private ShellExecutor mMainExecutor;
private PipBoundsState mPipBoundsState; private PipBoundsState mPipBoundsState;
private PipBoundsAlgorithm mPipBoundsAlgorithm; private PipBoundsAlgorithm mPipBoundsAlgorithm;
@@ -98,7 +98,7 @@ public class PipTouchHandlerTest extends ShellTestCase {
mPipSnapAlgorithm = new PipSnapAlgorithm(); mPipSnapAlgorithm = new PipSnapAlgorithm();
mPipTouchHandler = new PipTouchHandler(mContext, mPhonePipMenuController, mPipTouchHandler = new PipTouchHandler(mContext, mPhonePipMenuController,
mPipBoundsAlgorithm, mPipBoundsState, mPipTaskOrganizer, mPipBoundsAlgorithm, mPipBoundsState, mPipTaskOrganizer,
mFloatingContentCoordinator, mPipUiEventLogger, mShellMainExecutor); mFloatingContentCoordinator, mPipUiEventLogger, mMainExecutor);
mMotionHelper = Mockito.spy(mPipTouchHandler.getMotionHelper()); mMotionHelper = Mockito.spy(mPipTouchHandler.getMotionHelper());
mPipResizeGestureHandler = Mockito.spy(mPipTouchHandler.getPipResizeGestureHandler()); mPipResizeGestureHandler = Mockito.spy(mPipTouchHandler.getPipResizeGestureHandler());
mPipTouchHandler.setPipMotionHelper(mMotionHelper); mPipTouchHandler.setPipMotionHelper(mMotionHelper);

View File

@@ -17,24 +17,22 @@
package com.android.systemui.wmshell; package com.android.systemui.wmshell;
import android.content.Context; import android.content.Context;
import android.os.Handler;
import android.view.IWindowManager; import android.view.IWindowManager;
import com.android.systemui.dagger.WMSingleton; import com.android.systemui.dagger.WMSingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.Transitions; import com.android.wm.shell.Transitions;
import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import java.util.concurrent.Executor;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
@@ -47,9 +45,9 @@ public class TvWMShellModule {
@WMSingleton @WMSingleton
@Provides @Provides
static DisplayImeController provideDisplayImeController(IWindowManager wmService, static DisplayImeController provideDisplayImeController(IWindowManager wmService,
DisplayController displayController, @Main Executor mainExecutor, DisplayController displayController, @ShellMainThread ShellExecutor shellMainExecutor,
TransactionPool transactionPool) { TransactionPool transactionPool) {
return new DisplayImeController(wmService, displayController, mainExecutor, return new DisplayImeController(wmService, displayController, shellMainExecutor,
transactionPool); transactionPool);
} }
@@ -57,12 +55,12 @@ public class TvWMShellModule {
@Provides @Provides
static LegacySplitScreen provideSplitScreen(Context context, static LegacySplitScreen provideSplitScreen(Context context,
DisplayController displayController, SystemWindows systemWindows, DisplayController displayController, SystemWindows systemWindows,
DisplayImeController displayImeController, @Main Handler handler, DisplayImeController displayImeController, TransactionPool transactionPool,
TransactionPool transactionPool, ShellTaskOrganizer shellTaskOrganizer, ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
SyncTransactionQueue syncQueue, TaskStackListenerImpl taskStackListener, TaskStackListenerImpl taskStackListener, Transitions transitions,
Transitions transitions) { @ShellMainThread ShellExecutor mainExecutor) {
return new LegacySplitScreenController(context, displayController, systemWindows, return new LegacySplitScreenController(context, displayController, systemWindows,
displayImeController, handler, transactionPool, shellTaskOrganizer, syncQueue, displayImeController, transactionPool, shellTaskOrganizer, syncQueue,
taskStackListener, transitions); taskStackListener, transitions, mainExecutor);
} }
} }

View File

@@ -36,7 +36,9 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.wm.shell.FullscreenTaskListener; import com.android.wm.shell.FullscreenTaskListener;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellCommandHandler; import com.android.wm.shell.ShellCommandHandler;
import com.android.wm.shell.ShellCommandHandlerImpl;
import com.android.wm.shell.ShellInit; import com.android.wm.shell.ShellInit;
import com.android.wm.shell.ShellInitImpl;
import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.Transitions; import com.android.wm.shell.Transitions;
import com.android.wm.shell.WindowManagerShellWrapper; import com.android.wm.shell.WindowManagerShellWrapper;
@@ -158,7 +160,7 @@ public abstract class WMShellBaseModule {
// Choreographer.getSfInstance() which returns a thread-local Choreographer instance // Choreographer.getSfInstance() which returns a thread-local Choreographer instance
// that uses the SF vsync // that uses the SF vsync
handler.setProvider(new SfVsyncFrameCallbackProvider()); handler.setProvider(new SfVsyncFrameCallbackProvider());
}, 1, TimeUnit.SECONDS); });
return handler; return handler;
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new RuntimeException("Failed to initialize SfVsync animation handler in 1s", e); throw new RuntimeException("Failed to initialize SfVsync animation handler in 1s", e);
@@ -173,14 +175,14 @@ public abstract class WMShellBaseModule {
Optional<LegacySplitScreen> legacySplitScreenOptional, Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<AppPairs> appPairsOptional, Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener, FullscreenTaskListener fullscreenTaskListener,
Transitions transitions) { @ShellMainThread ShellExecutor shellMainExecutor) {
return new ShellInit(displayImeController, return ShellInitImpl.create(displayImeController,
dragAndDropController, dragAndDropController,
shellTaskOrganizer, shellTaskOrganizer,
legacySplitScreenOptional, legacySplitScreenOptional,
appPairsOptional, appPairsOptional,
fullscreenTaskListener, fullscreenTaskListener,
transitions); shellMainExecutor);
} }
/** /**
@@ -195,9 +197,11 @@ public abstract class WMShellBaseModule {
Optional<Pip> pipOptional, Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional, Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout, Optional<HideDisplayCutout> hideDisplayCutout,
Optional<AppPairs> appPairsOptional) { Optional<AppPairs> appPairsOptional,
return Optional.of(new ShellCommandHandler(shellTaskOrganizer, legacySplitScreenOptional, @ShellMainThread ShellExecutor shellMainExecutor) {
pipOptional, oneHandedOptional, hideDisplayCutout, appPairsOptional)); return Optional.of(ShellCommandHandlerImpl.create(shellTaskOrganizer,
legacySplitScreenOptional, pipOptional, oneHandedOptional, hideDisplayCutout,
appPairsOptional, shellMainExecutor));
} }
@WMSingleton @WMSingleton
@@ -208,9 +212,9 @@ public abstract class WMShellBaseModule {
@WMSingleton @WMSingleton
@Provides @Provides
static DisplayController provideDisplayController(Context context, @Main Handler handler, static DisplayController provideDisplayController(Context context,
IWindowManager wmService) { IWindowManager wmService, @ShellMainThread ShellExecutor shellMainExecutor) {
return new DisplayController(context, handler, wmService); return new DisplayController(context, wmService, shellMainExecutor);
} }
@WMSingleton @WMSingleton
@@ -269,9 +273,9 @@ public abstract class WMShellBaseModule {
@WMSingleton @WMSingleton
@Provides @Provides
static SyncTransactionQueue provideSyncTransactionQueue(@Main Handler handler, static SyncTransactionQueue provideSyncTransactionQueue(TransactionPool pool,
TransactionPool pool) { @ShellMainThread ShellExecutor shellMainExecutor) {
return new SyncTransactionQueue(pool, handler); return new SyncTransactionQueue(pool, shellMainExecutor);
} }
@WMSingleton @WMSingleton
@@ -288,10 +292,12 @@ public abstract class WMShellBaseModule {
return new RootTaskDisplayAreaOrganizer(mainExecutor, context); return new RootTaskDisplayAreaOrganizer(mainExecutor, context);
} }
// We currently dedupe multiple messages, so we use the shell main handler directly
@WMSingleton @WMSingleton
@Provides @Provides
static TaskStackListenerImpl providerTaskStackListenerImpl(@Main Handler handler) { static TaskStackListenerImpl providerTaskStackListenerImpl(
return new TaskStackListenerImpl(handler); @ShellMainThread Handler shellMainHandler) {
return new TaskStackListenerImpl(shellMainHandler);
} }
@BindsOptionalOf @BindsOptionalOf
@@ -309,11 +315,12 @@ public abstract class WMShellBaseModule {
WindowManagerShellWrapper windowManagerShellWrapper, WindowManagerShellWrapper windowManagerShellWrapper,
LauncherApps launcherApps, LauncherApps launcherApps,
UiEventLogger uiEventLogger, UiEventLogger uiEventLogger,
@Main Handler mainHandler, ShellTaskOrganizer organizer,
ShellTaskOrganizer organizer) { @ShellMainThread ShellExecutor shellMainExecutor) {
return Optional.of(BubbleController.create(context, null /* synchronizer */, return Optional.of(BubbleController.create(context, null /* synchronizer */,
floatingContentCoordinator, statusBarService, windowManager, floatingContentCoordinator, statusBarService, windowManager,
windowManagerShellWrapper, launcherApps, uiEventLogger, mainHandler, organizer)); windowManagerShellWrapper, launcherApps, uiEventLogger, organizer,
shellMainExecutor));
} }
@WMSingleton @WMSingleton

View File

@@ -65,9 +65,9 @@ public class WMShellModule {
@WMSingleton @WMSingleton
@Provides @Provides
static DisplayImeController provideDisplayImeController(IWindowManager wmService, static DisplayImeController provideDisplayImeController(IWindowManager wmService,
DisplayController displayController, @Main Executor mainExecutor, DisplayController displayController, @ShellMainThread ShellExecutor shellMainExecutor,
TransactionPool transactionPool) { TransactionPool transactionPool) {
return new DisplayImeController(wmService, displayController, mainExecutor, return new DisplayImeController(wmService, displayController, shellMainExecutor,
transactionPool); transactionPool);
} }
@@ -75,13 +75,13 @@ public class WMShellModule {
@Provides @Provides
static LegacySplitScreen provideLegacySplitScreen(Context context, static LegacySplitScreen provideLegacySplitScreen(Context context,
DisplayController displayController, SystemWindows systemWindows, DisplayController displayController, SystemWindows systemWindows,
DisplayImeController displayImeController, @Main Handler handler, DisplayImeController displayImeController, TransactionPool transactionPool,
TransactionPool transactionPool, ShellTaskOrganizer shellTaskOrganizer, ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
SyncTransactionQueue syncQueue, TaskStackListenerImpl taskStackListener, TaskStackListenerImpl taskStackListener, Transitions transitions,
Transitions transitions) { @ShellMainThread ShellExecutor mainExecutor) {
return new LegacySplitScreenController(context, displayController, systemWindows, return new LegacySplitScreenController(context, displayController, systemWindows,
displayImeController, handler, transactionPool, shellTaskOrganizer, syncQueue, displayImeController, transactionPool, shellTaskOrganizer, syncQueue,
taskStackListener, transitions); taskStackListener, transitions, mainExecutor);
} }
@WMSingleton @WMSingleton

View File

@@ -100,6 +100,7 @@ import com.android.wm.shell.bubbles.BubbleOverflow;
import com.android.wm.shell.bubbles.BubbleStackView; import com.android.wm.shell.bubbles.BubbleStackView;
import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@@ -278,9 +279,9 @@ public class BubblesTest extends SysuiTestCase {
mWindowManagerShellWrapper, mWindowManagerShellWrapper,
mLauncherApps, mLauncherApps,
mBubbleLogger, mBubbleLogger,
mock(Handler.class),
mock(ShellTaskOrganizer.class), mock(ShellTaskOrganizer.class),
mPositioner); mPositioner,
mock(ShellExecutor.class));
mBubbleController.setExpandListener(mBubbleExpandListener); mBubbleController.setExpandListener(mBubbleExpandListener);
mBubblesManager = new BubblesManager( mBubblesManager = new BubblesManager(

View File

@@ -93,6 +93,7 @@ import com.android.wm.shell.bubbles.BubbleOverflow;
import com.android.wm.shell.bubbles.BubbleStackView; import com.android.wm.shell.bubbles.BubbleStackView;
import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
@@ -246,9 +247,9 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
mWindowManagerShellWrapper, mWindowManagerShellWrapper,
mLauncherApps, mLauncherApps,
mBubbleLogger, mBubbleLogger,
mock(Handler.class),
mock(ShellTaskOrganizer.class), mock(ShellTaskOrganizer.class),
mPositioner); mPositioner,
mock(ShellExecutor.class));
mBubbleController.setExpandListener(mBubbleExpandListener); mBubbleController.setExpandListener(mBubbleExpandListener);
mBubblesManager = new BubblesManager( mBubblesManager = new BubblesManager(

View File

@@ -30,6 +30,7 @@ import com.android.wm.shell.bubbles.BubbleDataRepository;
import com.android.wm.shell.bubbles.BubbleLogger; import com.android.wm.shell.bubbles.BubbleLogger;
import com.android.wm.shell.bubbles.BubblePositioner; import com.android.wm.shell.bubbles.BubblePositioner;
import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
/** /**
* Testable BubbleController subclass that immediately synchronizes surfaces. * Testable BubbleController subclass that immediately synchronizes surfaces.
@@ -46,12 +47,12 @@ public class TestableBubbleController extends BubbleController {
WindowManagerShellWrapper windowManagerShellWrapper, WindowManagerShellWrapper windowManagerShellWrapper,
LauncherApps launcherApps, LauncherApps launcherApps,
BubbleLogger bubbleLogger, BubbleLogger bubbleLogger,
Handler mainHandler,
ShellTaskOrganizer shellTaskOrganizer, ShellTaskOrganizer shellTaskOrganizer,
BubblePositioner positioner) { BubblePositioner positioner,
ShellExecutor shellMainExecutor) {
super(context, data, Runnable::run, floatingContentCoordinator, dataRepository, super(context, data, Runnable::run, floatingContentCoordinator, dataRepository,
statusBarService, windowManager, windowManagerShellWrapper, launcherApps, statusBarService, windowManager, windowManagerShellWrapper, launcherApps,
bubbleLogger, mainHandler, shellTaskOrganizer, positioner); bubbleLogger, shellTaskOrganizer, positioner, shellMainExecutor);
setInflateSynchronously(true); setInflateSynchronously(true);
} }
} }