Merge "SpriteController: Reparent pointer surfaces under DisplayContent"

This commit is contained in:
TreeHugger Robot
2021-11-15 12:17:46 +00:00
committed by Android (Google) Code Review
6 changed files with 63 additions and 12 deletions

View File

@@ -27,10 +27,12 @@ namespace android {
// --- SpriteController ---
SpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) :
mLooper(looper), mOverlayLayer(overlayLayer) {
SpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer,
ParentSurfaceProvider parentSurfaceProvider)
: mLooper(looper),
mOverlayLayer(overlayLayer),
mParentSurfaceProvider(std::move(parentSurfaceProvider)) {
mHandler = new WeakMessageHandler(this);
mLocked.transactionNestingCount = 0;
mLocked.deferredSpriteUpdate = false;
}
@@ -168,8 +170,7 @@ void SpriteController::doUpdateSprites() {
// If surface is a new one, we have to set right layer stack.
if (update.surfaceChanged || update.state.dirty & DIRTY_DISPLAY_ID) {
t.setLayerStack(update.state.surfaceControl,
ui::LayerStack::fromValue(update.state.displayId));
t.reparent(update.state.surfaceControl, mParentSurfaceProvider(update.state.displayId));
needApplyTransaction = true;
}
}

View File

@@ -114,7 +114,8 @@ protected:
virtual ~SpriteController();
public:
SpriteController(const sp<Looper>& looper, int32_t overlayLayer);
using ParentSurfaceProvider = std::function<sp<SurfaceControl>(int /*displayId*/)>;
SpriteController(const sp<Looper>& looper, int32_t overlayLayer, ParentSurfaceProvider parent);
/* Creates a new sprite, initially invisible. */
virtual sp<Sprite> createSprite();
@@ -245,6 +246,7 @@ private:
sp<Looper> mLooper;
const int32_t mOverlayLayer;
sp<WeakMessageHandler> mHandler;
ParentSurfaceProvider mParentSurfaceProvider;
sp<SurfaceComposerClient> mSurfaceComposerClient;

View File

@@ -26,7 +26,8 @@ namespace android {
class MockSpriteController : public SpriteController {
public:
MockSpriteController(sp<Looper> looper) : SpriteController(looper, 0) {}
MockSpriteController(sp<Looper> looper)
: SpriteController(looper, 0, [](int) { return nullptr; }) {}
~MockSpriteController() {}
MOCK_METHOD(sp<Sprite>, createSprite, (), (override));

View File

@@ -98,6 +98,7 @@ import android.view.InputMonitor;
import android.view.KeyEvent;
import android.view.PointerIcon;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.VerifiedInputEvent;
import android.view.ViewConfiguration;
import android.widget.Toast;
@@ -2906,6 +2907,15 @@ public class InputManagerService extends IInputManager.Stub
return PointerIcon.getDefaultIcon(getContextForPointerIcon(displayId));
}
// Native callback.
private long getParentSurfaceForPointers(int displayId) {
final SurfaceControl sc = mWindowManagerCallbacks.getParentSurfaceForPointers(displayId);
if (sc == null) {
return 0;
}
return sc.mNativeObject;
}
@NonNull
private Context getContextForPointerIcon(int displayId) {
if (mPointerIconDisplayContext != null
@@ -3105,6 +3115,12 @@ public class InputManagerService extends IInputManager.Stub
* Called when the drag over window has changed.
*/
void notifyDropWindow(IBinder token, float x, float y);
/**
* Get the {@link SurfaceControl} that should be the parent for the surfaces created for
* pointers such as the mouse cursor and touch spots for the given display.
*/
SurfaceControl getParentSurfaceForPointers(int displayId);
}
/**

View File

@@ -29,6 +29,7 @@ import android.os.IBinder;
import android.util.Slog;
import android.view.InputApplicationHandle;
import android.view.KeyEvent;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.WindowManagerPolicyConstants;
@@ -234,6 +235,19 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
mService.mDragDropController::reportDropWindow, token, x, y));
}
@Override
public SurfaceControl getParentSurfaceForPointers(int displayId) {
synchronized (mService.mGlobalLock) {
final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
if (dc == null) {
Slog.e(TAG, "Failed to get parent surface for pointers on display " + displayId
+ " - DisplayContent not found.");
return null;
}
return dc.getOverlayLayer();
}
}
/** Waits until the built-in input devices have been configured. */
public boolean waitForInputDevicesReady(long timeoutMillis) {
synchronized (mInputDevicesReadyMonitor) {

View File

@@ -128,6 +128,7 @@ static struct {
jmethodID getTouchCalibrationForInputDevice;
jmethodID getContextForDisplay;
jmethodID notifyDropWindow;
jmethodID getParentSurfaceForPointers;
} gServiceClassInfo;
static struct {
@@ -389,7 +390,7 @@ private:
void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
void ensureSpriteControllerLocked();
int32_t getPointerDisplayId();
void updatePointerDisplayLocked();
sp<SurfaceControl> getParentSurfaceForPointers(int displayId);
static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
static inline JNIEnv* jniEnv() {
@@ -668,6 +669,18 @@ int32_t NativeInputManager::getPointerDisplayId() {
return pointerDisplayId;
}
sp<SurfaceControl> NativeInputManager::getParentSurfaceForPointers(int displayId) {
JNIEnv* env = jniEnv();
jlong nativeSurfaceControlPtr =
env->CallLongMethod(mServiceObj, gServiceClassInfo.getParentSurfaceForPointers,
displayId);
if (checkAndClearExceptionFromCallback(env, "getParentSurfaceForPointers")) {
return nullptr;
}
return reinterpret_cast<SurfaceControl*>(nativeSurfaceControlPtr);
}
void NativeInputManager::ensureSpriteControllerLocked() REQUIRES(mLock) {
if (mLocked.spriteController == nullptr) {
JNIEnv* env = jniEnv();
@@ -675,7 +688,9 @@ void NativeInputManager::ensureSpriteControllerLocked() REQUIRES(mLock) {
if (checkAndClearExceptionFromCallback(env, "getPointerLayer")) {
layer = -1;
}
mLocked.spriteController = new SpriteController(mLooper, layer);
mLocked.spriteController = new SpriteController(mLooper, layer, [this](int displayId) {
return getParentSurfaceForPointers(displayId);
});
}
}
@@ -2500,9 +2515,11 @@ int register_android_server_InputManager(JNIEnv* env) {
"getTouchCalibrationForInputDevice",
"(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;");
GET_METHOD_ID(gServiceClassInfo.getContextForDisplay, clazz,
"getContextForDisplay",
"(I)Landroid/content/Context;")
GET_METHOD_ID(gServiceClassInfo.getContextForDisplay, clazz, "getContextForDisplay",
"(I)Landroid/content/Context;");
GET_METHOD_ID(gServiceClassInfo.getParentSurfaceForPointers, clazz,
"getParentSurfaceForPointers", "(I)J");
// InputDevice