Merge "Add diag for inputflinger tests" into main
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index f012586..270bfbd 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -477,9 +477,14 @@
return NO_ERROR;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
+ const sp<Fence>& releaseFence) {
+#else
status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
EGLSyncKHR eglFence) {
+#endif
ATRACE_CALL();
ATRACE_BUFFER_INDEX(slot);
@@ -493,27 +498,6 @@
return BAD_VALUE;
}
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
- if (eglFence != EGL_NO_SYNC_KHR) {
- // Most platforms will be using native fences, so it's unlikely that we'll ever have to
- // process an eglFence. Ideally we can remove this code eventually. In the mean time, do our
- // best to wait for it so the buffer stays valid, otherwise return an error to the caller.
- //
- // EGL_SYNC_FLUSH_COMMANDS_BIT_KHR so that we don't wait forever on a fence that hasn't
- // shown up on the GPU yet.
- EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
- 1000000000);
- if (result == EGL_FALSE) {
- BQ_LOGE("releaseBuffer: error %#x waiting for fence", eglGetError());
- return UNKNOWN_ERROR;
- } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- BQ_LOGE("releaseBuffer: timeout waiting for fence");
- return UNKNOWN_ERROR;
- }
- eglDestroySyncKHR(eglDisplay, eglFence);
- }
-#endif
-
sp<IProducerListener> listener;
{ // Autolock scope
std::lock_guard<std::mutex> lock(mCore->mMutex);
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 504509d..3ad0e52 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -656,9 +656,13 @@
return OK;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t ConsumerBase::releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) {
+#else
status_t ConsumerBase::releaseBufferLocked(
int slot, const sp<GraphicBuffer> graphicBuffer,
EGLDisplay display, EGLSyncKHR eglFence) {
+#endif
if (mAbandoned) {
CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!");
return NO_INIT;
@@ -675,8 +679,12 @@
CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
slot, mSlots[slot].mFrameNumber);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber, mSlots[slot].mFence);
+#else
status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
display, eglFence, mSlots[slot].mFence);
+#endif
if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
freeBufferLocked(slot);
}
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 168129b..052b8ed 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -417,18 +417,18 @@
}
#endif
-status_t GLConsumer::releaseBufferLocked(int buf,
- sp<GraphicBuffer> graphicBuffer,
- EGLDisplay display, EGLSyncKHR eglFence) {
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t GLConsumer::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer,
+ EGLDisplay display, EGLSyncKHR eglFence) {
// release the buffer if it hasn't already been discarded by the
// BufferQueue. This can happen, for example, when the producer of this
// buffer has reallocated the original buffer slot after this buffer
// was acquired.
- status_t err = ConsumerBase::releaseBufferLocked(
- buf, graphicBuffer, display, eglFence);
+ status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer, display, eglFence);
mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
return err;
}
+#endif
status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
PendingRelease* pendingRelease)
@@ -490,9 +490,14 @@
// release old buffer
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (pendingRelease == nullptr) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t status =
+ releaseBufferLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer());
+#else
status_t status = releaseBufferLocked(
mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
+#endif
if (status < NO_ERROR) {
GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
strerror(-status), status);
@@ -501,10 +506,7 @@
}
} else {
pendingRelease->currentTexture = mCurrentTexture;
- pendingRelease->graphicBuffer =
- mCurrentTextureImage->graphicBuffer();
- pendingRelease->display = mEglDisplay;
- pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
+ pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
pendingRelease->isPending = true;
}
}
@@ -744,6 +746,11 @@
return err;
}
} else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ // Basically all clients are using native fence syncs. If they aren't, we lose nothing
+ // by waiting here, because the alternative can cause deadlocks (b/339705065).
+ glFinish();
+#else
EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
if (fence != EGL_NO_SYNC_KHR) {
// There is already a fence for the current slot. We need to
@@ -773,6 +780,7 @@
}
glFlush();
mEglSlots[mCurrentTexture].mEglFence = fence;
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
}
}
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index c1b6568..e133532 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -85,6 +85,12 @@
return callRemote<Signature>(Tag::ATTACH_BUFFER, slot, buffer);
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) override {
+ using Signature = status_t (IGraphicBufferConsumer::*)(int, uint64_t, const sp<Fence>&);
+ return callRemote<Signature>(Tag::RELEASE_BUFFER, buf, frameNumber, releaseFence);
+ }
+#else
status_t releaseBuffer(int buf, uint64_t frameNumber,
EGLDisplay display __attribute__((unused)),
EGLSyncKHR fence __attribute__((unused)),
@@ -92,6 +98,7 @@
using Signature = status_t (IGraphicBufferConsumer::*)(int, uint64_t, const sp<Fence>&);
return callRemote<Signature>(Tag::RELEASE_BUFFER, buf, frameNumber, releaseFence);
}
+#endif
status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) override {
using Signature = decltype(&IGraphicBufferConsumer::consumerConnect);
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index e00c44e..f99b54b 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -65,13 +65,14 @@
// any references to the just-released buffer that it might have, as if it
// had received a onBuffersReleased() call with a mask set for the released
// buffer.
- //
- // Note that the dependencies on EGL will be removed once we switch to using
- // the Android HW Sync HAL.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
+ const sp<Fence>& releaseFence) override;
+#else
virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
const sp<Fence>& releaseFence, EGLDisplay display,
EGLSyncKHR fence);
-
+#endif
// connect connects a consumer to the BufferQueue. Only one
// consumer may be connected, and when that consumer disconnects the
// BufferQueue is placed into the "abandoned" state, causing most
@@ -167,6 +168,7 @@
// dump our state in a String
status_t dumpState(const String8& prefix, String8* outResult) const override;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
// Functions required for backwards compatibility.
// These will be modified/renamed in IGraphicBufferConsumer and will be
// removed from this class at that time. See b/13306289.
@@ -176,6 +178,7 @@
const sp<Fence>& releaseFence) {
return releaseBuffer(buf, frameNumber, releaseFence, display, fence);
}
+#endif
virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
bool controlledByApp) {
diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index 5cd19c1..acb0006 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -245,10 +245,13 @@
// must take place when a buffer is released back to the BufferQueue. If
// it is overridden the derived class's implementation must call
// ConsumerBase::releaseBufferLocked.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer);
+#else
virtual status_t releaseBufferLocked(int slot,
const sp<GraphicBuffer> graphicBuffer,
EGLDisplay display = EGL_NO_DISPLAY, EGLSyncKHR eglFence = EGL_NO_SYNC_KHR);
-
+#endif
// returns true iff the slot still has the graphicBuffer in it.
bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer);
diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
index 30cbfa2..dbf707f 100644
--- a/libs/gui/include/gui/GLConsumer.h
+++ b/libs/gui/include/gui/GLConsumer.h
@@ -271,6 +271,7 @@
#endif
// releaseBufferLocked overrides the ConsumerBase method to update the
// mEglSlots array in addition to the ConsumerBase.
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer,
EGLDisplay display = EGL_NO_DISPLAY,
EGLSyncKHR eglFence = EGL_NO_SYNC_KHR) override;
@@ -279,16 +280,14 @@
const sp<GraphicBuffer> graphicBuffer, EGLSyncKHR eglFence) {
return releaseBufferLocked(slot, graphicBuffer, mEglDisplay, eglFence);
}
+#endif
struct PendingRelease {
- PendingRelease() : isPending(false), currentTexture(-1),
- graphicBuffer(), display(nullptr), fence(nullptr) {}
+ PendingRelease() : isPending(false), currentTexture(-1), graphicBuffer() {}
bool isPending;
int currentTexture;
sp<GraphicBuffer> graphicBuffer;
- EGLDisplay display;
- EGLSyncKHR fence;
};
// This releases the buffer in the slot referenced by mCurrentTexture,
@@ -468,16 +467,18 @@
// EGLSlot contains the information and object references that
// GLConsumer maintains about a BufferQueue buffer slot.
struct EglSlot {
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
-
+#endif
// mEglImage is the EGLImage created from mGraphicBuffer.
sp<EglImage> mEglImage;
-
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
// mFence is the EGL sync object that must signal before the buffer
// associated with this buffer slot may be dequeued. It is initialized
// to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
// on a compile-time option) set to a new sync object in updateTexImage.
EGLSyncKHR mEglFence;
+#endif
};
// mEglDisplay is the EGLDisplay with which this GLConsumer is currently
diff --git a/libs/gui/include/gui/IGraphicBufferConsumer.h b/libs/gui/include/gui/IGraphicBufferConsumer.h
index 56eb291..f6b3e89 100644
--- a/libs/gui/include/gui/IGraphicBufferConsumer.h
+++ b/libs/gui/include/gui/IGraphicBufferConsumer.h
@@ -139,12 +139,17 @@
// * the buffer slot was invalid
// * the fence was NULL
// * the buffer slot specified is not in the acquired state
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
+ const sp<Fence>& releaseFence) = 0;
+#else
virtual status_t releaseBuffer(int buf, uint64_t frameNumber, EGLDisplay display,
EGLSyncKHR fence, const sp<Fence>& releaseFence) = 0;
status_t releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) {
return releaseBuffer(buf, frameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence);
}
+#endif
// consumerConnect connects a consumer to the BufferQueue. Only one consumer may be connected,
// and when that consumer disconnects the BufferQueue is placed into the "abandoned" state,
diff --git a/libs/gui/include/gui/mock/GraphicBufferConsumer.h b/libs/gui/include/gui/mock/GraphicBufferConsumer.h
index 98f24c2..8dfd3cb 100644
--- a/libs/gui/include/gui/mock/GraphicBufferConsumer.h
+++ b/libs/gui/include/gui/mock/GraphicBufferConsumer.h
@@ -18,6 +18,7 @@
#include <gmock/gmock.h>
+#include <com_android_graphics_libgui_flags.h>
#include <gui/IGraphicBufferConsumer.h>
#include <utils/RefBase.h>
@@ -33,7 +34,11 @@
MOCK_METHOD3(acquireBuffer, status_t(BufferItem*, nsecs_t, uint64_t));
MOCK_METHOD1(detachBuffer, status_t(int));
MOCK_METHOD2(attachBuffer, status_t(int*, const sp<GraphicBuffer>&));
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ MOCK_METHOD3(releaseBuffer, status_t(int, uint64_t, const sp<Fence>&));
+#else
MOCK_METHOD5(releaseBuffer, status_t(int, uint64_t, EGLDisplay, EGLSyncKHR, const sp<Fence>&));
+#endif
MOCK_METHOD2(consumerConnect, status_t(const sp<IConsumerListener>&, bool));
MOCK_METHOD0(consumerDisconnect, status_t());
MOCK_METHOD1(getReleasedBuffers, status_t(uint64_t*));
diff --git a/libs/nativedisplay/include/surfacetexture/EGLConsumer.h b/libs/nativedisplay/include/surfacetexture/EGLConsumer.h
index 444722b..226a8a6 100644
--- a/libs/nativedisplay/include/surfacetexture/EGLConsumer.h
+++ b/libs/nativedisplay/include/surfacetexture/EGLConsumer.h
@@ -113,18 +113,11 @@
protected:
struct PendingRelease {
- PendingRelease()
- : isPending(false),
- currentTexture(-1),
- graphicBuffer(),
- display(nullptr),
- fence(nullptr) {}
+ PendingRelease() : isPending(false), currentTexture(-1), graphicBuffer() {}
bool isPending;
int currentTexture;
sp<GraphicBuffer> graphicBuffer;
- EGLDisplay display;
- EGLSyncKHR fence;
};
/**
@@ -250,13 +243,16 @@
* EGLConsumer maintains about a BufferQueue buffer slot.
*/
struct EglSlot {
- EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
+#endif
/**
* mEglImage is the EGLImage created from mGraphicBuffer.
*/
sp<EglImage> mEglImage;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
/**
* mFence is the EGL sync object that must signal before the buffer
* associated with this buffer slot may be dequeued. It is initialized
@@ -264,6 +260,7 @@
* on a compile-time option) set to a new sync object in updateTexImage.
*/
EGLSyncKHR mEglFence;
+#endif
};
/**
diff --git a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
index 006a785..253aa18 100644
--- a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
+++ b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
@@ -343,9 +343,13 @@
* releaseBufferLocked overrides the ConsumerBase method to update the
* mEglSlots array in addition to the ConsumerBase.
*/
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) override;
+#else
virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer,
EGLDisplay display = EGL_NO_DISPLAY,
EGLSyncKHR eglFence = EGL_NO_SYNC_KHR) override;
+#endif
/**
* freeBufferLocked frees up the given buffer slot. If the slot has been
diff --git a/libs/nativedisplay/surfacetexture/EGLConsumer.cpp b/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
index 3959fce..fad0f6c 100644
--- a/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
+++ b/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
@@ -221,7 +221,11 @@
}
void EGLConsumer::onReleaseBufferLocked(int buf) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ (void)buf;
+#else
mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
+#endif
}
status_t EGLConsumer::updateAndReleaseLocked(const BufferItem& item, PendingRelease* pendingRelease,
@@ -283,10 +287,15 @@
// release old buffer
if (st.mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (pendingRelease == nullptr) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t status = st.releaseBufferLocked(st.mCurrentTexture,
+ mCurrentTextureImage->graphicBuffer());
+#else
status_t status =
st.releaseBufferLocked(st.mCurrentTexture,
mCurrentTextureImage->graphicBuffer(), mEglDisplay,
mEglSlots[st.mCurrentTexture].mEglFence);
+#endif
if (status < NO_ERROR) {
EGC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
status);
@@ -296,8 +305,6 @@
} else {
pendingRelease->currentTexture = st.mCurrentTexture;
pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
- pendingRelease->display = mEglDisplay;
- pendingRelease->fence = mEglSlots[st.mCurrentTexture].mEglFence;
pendingRelease->isPending = true;
}
}
@@ -502,6 +509,11 @@
return err;
}
} else if (st.mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ // Basically all clients are using native fence syncs. If they aren't, we lose nothing
+ // by waiting here, because the alternative can cause deadlocks (b/339705065).
+ glFinish();
+#else
EGLSyncKHR fence = mEglSlots[st.mCurrentTexture].mEglFence;
if (fence != EGL_NO_SYNC_KHR) {
// There is already a fence for the current slot. We need to
@@ -531,6 +543,7 @@
}
glFlush();
mEglSlots[st.mCurrentTexture].mEglFence = fence;
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
}
}
diff --git a/libs/nativedisplay/surfacetexture/ImageConsumer.cpp b/libs/nativedisplay/surfacetexture/ImageConsumer.cpp
index 60e87b5..1ffd382 100644
--- a/libs/nativedisplay/surfacetexture/ImageConsumer.cpp
+++ b/libs/nativedisplay/surfacetexture/ImageConsumer.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
#include <gui/BufferQueue.h>
#include <surfacetexture/ImageConsumer.h>
#include <surfacetexture/SurfaceTexture.h>
@@ -95,10 +99,34 @@
}
// Finally release the old buffer.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ EGLSyncKHR previousFence = mImageSlots[st.mCurrentTexture].eglFence();
+ if (previousFence != EGL_NO_SYNC_KHR) {
+ // Most platforms will be using native fences, so it's unlikely that we'll ever have to
+ // process an eglFence. Ideally we can remove this code eventually. In the mean time, do
+ // our best to wait for it so the buffer stays valid, otherwise return an error to the
+ // caller.
+ //
+ // EGL_SYNC_FLUSH_COMMANDS_BIT_KHR so that we don't wait forever on a fence that hasn't
+ // shown up on the GPU yet.
+ EGLint result = eglClientWaitSyncKHR(display, previousFence,
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 1000000000);
+ if (result == EGL_FALSE) {
+ IMG_LOGE("dequeueBuffer: error %#x waiting for fence", eglGetError());
+ } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ IMG_LOGE("dequeueBuffer: timeout waiting for fence");
+ }
+ eglDestroySyncKHR(display, previousFence);
+ }
+
+ status_t status = st.releaseBufferLocked(st.mCurrentTexture,
+ st.mSlots[st.mCurrentTexture].mGraphicBuffer);
+#else
status_t status =
st.releaseBufferLocked(st.mCurrentTexture,
st.mSlots[st.mCurrentTexture].mGraphicBuffer, display,
mImageSlots[st.mCurrentTexture].eglFence());
+#endif
if (status < NO_ERROR) {
IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status);
err = status;
diff --git a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
index ce232cc..c0a1cc5 100644
--- a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
+++ b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
@@ -178,13 +178,21 @@
return NO_ERROR;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t SurfaceTexture::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer) {
+#else
status_t SurfaceTexture::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer,
EGLDisplay display, EGLSyncKHR eglFence) {
+#endif
// release the buffer if it hasn't already been discarded by the
// BufferQueue. This can happen, for example, when the producer of this
// buffer has reallocated the original buffer slot after this buffer
// was acquired.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer);
+#else
status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer, display, eglFence);
+#endif
// We could be releasing an EGL/Vulkan buffer, even if not currently
// attached to a GL context.
mImageConsumer.onReleaseBufferLocked(buf);
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
deleted file mode 100644
index 9039751..0000000
--- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "AndroidInputEventProtoConverter.h"
-
-#include <android-base/logging.h>
-#include <perfetto/trace/android/android_input_event.pbzero.h>
-
-namespace android::inputdispatcher::trace {
-
-namespace {
-
-using namespace ftl::flag_operators;
-
-// The trace config to use for maximal tracing.
-const impl::TraceConfig CONFIG_TRACE_ALL{
- .flags = impl::TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS |
- impl::TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH,
- .rules = {impl::TraceRule{.level = impl::TraceLevel::TRACE_LEVEL_COMPLETE,
- .matchAllPackages = {},
- .matchAnyPackages = {},
- .matchSecure{},
- .matchImeConnectionActive = {}}},
-};
-
-} // namespace
-
-void AndroidInputEventProtoConverter::toProtoMotionEvent(const TracedMotionEvent& event,
- proto::AndroidMotionEvent& outProto,
- bool isRedacted) {
- outProto.set_event_id(event.id);
- outProto.set_event_time_nanos(event.eventTime);
- outProto.set_down_time_nanos(event.downTime);
- outProto.set_source(event.source);
- outProto.set_action(event.action);
- outProto.set_device_id(event.deviceId);
- outProto.set_display_id(event.displayId.val());
- outProto.set_classification(static_cast<int32_t>(event.classification));
- outProto.set_flags(event.flags);
- outProto.set_policy_flags(event.policyFlags);
- outProto.set_button_state(event.buttonState);
- outProto.set_action_button(event.actionButton);
-
- if (!isRedacted) {
- outProto.set_cursor_position_x(event.xCursorPosition);
- outProto.set_cursor_position_y(event.yCursorPosition);
- outProto.set_meta_state(event.metaState);
- outProto.set_precision_x(event.xPrecision);
- outProto.set_precision_y(event.yPrecision);
- }
-
- for (uint32_t i = 0; i < event.pointerProperties.size(); i++) {
- auto* pointer = outProto.add_pointer();
-
- const auto& props = event.pointerProperties[i];
- pointer->set_pointer_id(props.id);
- pointer->set_tool_type(static_cast<int32_t>(props.toolType));
-
- const auto& coords = event.pointerCoords[i];
- auto bits = BitSet64(coords.bits);
- for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) {
- const auto axis = bits.clearFirstMarkedBit();
- auto axisEntry = pointer->add_axis_value();
- axisEntry->set_axis(axis);
-
- if (!isRedacted) {
- axisEntry->set_value(coords.values[axisIndex]);
- }
- }
- }
-}
-
-void AndroidInputEventProtoConverter::toProtoKeyEvent(const TracedKeyEvent& event,
- proto::AndroidKeyEvent& outProto,
- bool isRedacted) {
- outProto.set_event_id(event.id);
- outProto.set_event_time_nanos(event.eventTime);
- outProto.set_down_time_nanos(event.downTime);
- outProto.set_source(event.source);
- outProto.set_action(event.action);
- outProto.set_device_id(event.deviceId);
- outProto.set_display_id(event.displayId.val());
- outProto.set_repeat_count(event.repeatCount);
- outProto.set_flags(event.flags);
- outProto.set_policy_flags(event.policyFlags);
-
- if (!isRedacted) {
- outProto.set_key_code(event.keyCode);
- outProto.set_scan_code(event.scanCode);
- outProto.set_meta_state(event.metaState);
- }
-}
-
-void AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(
- const WindowDispatchArgs& args, proto::AndroidWindowInputDispatchEvent& outProto,
- bool isRedacted) {
- std::visit([&](auto entry) { outProto.set_event_id(entry.id); }, args.eventEntry);
- outProto.set_vsync_id(args.vsyncId);
- outProto.set_window_id(args.windowId);
- outProto.set_resolved_flags(args.resolvedFlags);
-
- if (isRedacted) {
- return;
- }
- if (auto* motion = std::get_if<TracedMotionEvent>(&args.eventEntry); motion != nullptr) {
- for (size_t i = 0; i < motion->pointerProperties.size(); i++) {
- auto* pointerProto = outProto.add_dispatched_pointer();
- pointerProto->set_pointer_id(motion->pointerProperties[i].id);
- const auto& coords = motion->pointerCoords[i];
- const auto rawXY =
- MotionEvent::calculateTransformedXY(motion->source, args.rawTransform,
- coords.getXYValue());
- if (coords.getXYValue() != rawXY) {
- // These values are only traced if they were modified by the raw transform
- // to save space. Trace consumers should be aware of this optimization.
- pointerProto->set_x_in_display(rawXY.x);
- pointerProto->set_y_in_display(rawXY.y);
- }
-
- const auto coordsInWindow =
- MotionEvent::calculateTransformedCoords(motion->source, motion->flags,
- args.transform, coords);
- auto bits = BitSet64(coords.bits);
- for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) {
- const uint32_t axis = bits.clearFirstMarkedBit();
- const float axisValueInWindow = coordsInWindow.values[axisIndex];
- // Only values that are modified by the window transform are traced.
- if (coords.values[axisIndex] != axisValueInWindow) {
- auto* axisEntry = pointerProto->add_axis_value_in_window();
- axisEntry->set_axis(axis);
- axisEntry->set_value(axisValueInWindow);
- }
- }
- }
- }
-}
-
-impl::TraceConfig AndroidInputEventProtoConverter::parseConfig(
- proto::AndroidInputEventConfig::Decoder& protoConfig) {
- if (protoConfig.has_mode() &&
- protoConfig.mode() == proto::AndroidInputEventConfig::TRACE_MODE_TRACE_ALL) {
- // User has requested the preset for maximal tracing
- return CONFIG_TRACE_ALL;
- }
-
- impl::TraceConfig config;
-
- // Parse trace flags
- if (protoConfig.has_trace_dispatcher_input_events() &&
- protoConfig.trace_dispatcher_input_events()) {
- config.flags |= impl::TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS;
- }
- if (protoConfig.has_trace_dispatcher_window_dispatch() &&
- protoConfig.trace_dispatcher_window_dispatch()) {
- config.flags |= impl::TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH;
- }
-
- // Parse trace rules
- auto rulesIt = protoConfig.rules();
- while (rulesIt) {
- proto::AndroidInputEventConfig::TraceRule::Decoder protoRule{rulesIt->as_bytes()};
- config.rules.emplace_back();
- auto& rule = config.rules.back();
-
- rule.level = protoRule.has_trace_level()
- ? static_cast<impl::TraceLevel>(protoRule.trace_level())
- : impl::TraceLevel::TRACE_LEVEL_NONE;
-
- if (protoRule.has_match_all_packages()) {
- auto pkgIt = protoRule.match_all_packages();
- while (pkgIt) {
- rule.matchAllPackages.emplace_back(pkgIt->as_std_string());
- pkgIt++;
- }
- }
-
- if (protoRule.has_match_any_packages()) {
- auto pkgIt = protoRule.match_any_packages();
- while (pkgIt) {
- rule.matchAnyPackages.emplace_back(pkgIt->as_std_string());
- pkgIt++;
- }
- }
-
- if (protoRule.has_match_secure()) {
- rule.matchSecure = protoRule.match_secure();
- }
-
- if (protoRule.has_match_ime_connection_active()) {
- rule.matchImeConnectionActive = protoRule.match_ime_connection_active();
- }
-
- rulesIt++;
- }
-
- return config;
-}
-
-} // namespace android::inputdispatcher::trace
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
index 887913f..eb33e2b 100644
--- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
+++ b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
@@ -26,20 +26,198 @@
namespace android::inputdispatcher::trace {
+namespace internal {
+
+using namespace ftl::flag_operators;
+
+// The trace config to use for maximal tracing.
+const impl::TraceConfig CONFIG_TRACE_ALL{
+ .flags = impl::TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS |
+ impl::TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH,
+ .rules = {impl::TraceRule{.level = impl::TraceLevel::TRACE_LEVEL_COMPLETE,
+ .matchAllPackages = {},
+ .matchAnyPackages = {},
+ .matchSecure{},
+ .matchImeConnectionActive = {}}},
+};
+
+} // namespace internal
+
/**
* Write traced events into Perfetto protos.
+ *
+ * This class is templated so that the logic can be tested while substituting the proto classes
+ * auto-generated by Perfetto's pbzero library with mock implementations.
*/
+template <typename ProtoMotion, typename ProtoKey, typename ProtoDispatch,
+ typename ProtoConfigDecoder>
class AndroidInputEventProtoConverter {
public:
- static void toProtoMotionEvent(const TracedMotionEvent& event,
- proto::AndroidMotionEvent& outProto, bool isRedacted);
- static void toProtoKeyEvent(const TracedKeyEvent& event, proto::AndroidKeyEvent& outProto,
- bool isRedacted);
- static void toProtoWindowDispatchEvent(const WindowDispatchArgs&,
- proto::AndroidWindowInputDispatchEvent& outProto,
- bool isRedacted);
+ static void toProtoMotionEvent(const TracedMotionEvent& event, ProtoMotion& outProto,
+ bool isRedacted) {
+ outProto.set_event_id(event.id);
+ outProto.set_event_time_nanos(event.eventTime);
+ outProto.set_down_time_nanos(event.downTime);
+ outProto.set_source(event.source);
+ outProto.set_action(event.action);
+ outProto.set_device_id(event.deviceId);
+ outProto.set_display_id(event.displayId.val());
+ outProto.set_classification(static_cast<int32_t>(event.classification));
+ outProto.set_flags(event.flags);
+ outProto.set_policy_flags(event.policyFlags);
+ outProto.set_button_state(event.buttonState);
+ outProto.set_action_button(event.actionButton);
- static impl::TraceConfig parseConfig(proto::AndroidInputEventConfig::Decoder& protoConfig);
+ if (!isRedacted) {
+ outProto.set_cursor_position_x(event.xCursorPosition);
+ outProto.set_cursor_position_y(event.yCursorPosition);
+ outProto.set_meta_state(event.metaState);
+ outProto.set_precision_x(event.xPrecision);
+ outProto.set_precision_y(event.yPrecision);
+ }
+
+ for (uint32_t i = 0; i < event.pointerProperties.size(); i++) {
+ auto* pointer = outProto.add_pointer();
+
+ const auto& props = event.pointerProperties[i];
+ pointer->set_pointer_id(props.id);
+ pointer->set_tool_type(static_cast<int32_t>(props.toolType));
+
+ const auto& coords = event.pointerCoords[i];
+ auto bits = BitSet64(coords.bits);
+ for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) {
+ const auto axis = bits.clearFirstMarkedBit();
+ auto axisEntry = pointer->add_axis_value();
+ axisEntry->set_axis(axis);
+
+ if (!isRedacted) {
+ axisEntry->set_value(coords.values[axisIndex]);
+ }
+ }
+ }
+ }
+
+ static void toProtoKeyEvent(const TracedKeyEvent& event, ProtoKey& outProto, bool isRedacted) {
+ outProto.set_event_id(event.id);
+ outProto.set_event_time_nanos(event.eventTime);
+ outProto.set_down_time_nanos(event.downTime);
+ outProto.set_source(event.source);
+ outProto.set_action(event.action);
+ outProto.set_device_id(event.deviceId);
+ outProto.set_display_id(event.displayId.val());
+ outProto.set_repeat_count(event.repeatCount);
+ outProto.set_flags(event.flags);
+ outProto.set_policy_flags(event.policyFlags);
+
+ if (!isRedacted) {
+ outProto.set_key_code(event.keyCode);
+ outProto.set_scan_code(event.scanCode);
+ outProto.set_meta_state(event.metaState);
+ }
+ }
+
+ static void toProtoWindowDispatchEvent(const WindowDispatchArgs& args, ProtoDispatch& outProto,
+ bool isRedacted) {
+ std::visit([&](auto entry) { outProto.set_event_id(entry.id); }, args.eventEntry);
+ outProto.set_vsync_id(args.vsyncId);
+ outProto.set_window_id(args.windowId);
+ outProto.set_resolved_flags(args.resolvedFlags);
+
+ if (isRedacted) {
+ return;
+ }
+ if (auto* motion = std::get_if<TracedMotionEvent>(&args.eventEntry); motion != nullptr) {
+ for (size_t i = 0; i < motion->pointerProperties.size(); i++) {
+ auto* pointerProto = outProto.add_dispatched_pointer();
+ pointerProto->set_pointer_id(motion->pointerProperties[i].id);
+ const auto& coords = motion->pointerCoords[i];
+ const auto rawXY =
+ MotionEvent::calculateTransformedXY(motion->source, args.rawTransform,
+ coords.getXYValue());
+ if (coords.getXYValue() != rawXY) {
+ // These values are only traced if they were modified by the raw transform
+ // to save space. Trace consumers should be aware of this optimization.
+ pointerProto->set_x_in_display(rawXY.x);
+ pointerProto->set_y_in_display(rawXY.y);
+ }
+
+ const auto coordsInWindow =
+ MotionEvent::calculateTransformedCoords(motion->source, motion->flags,
+ args.transform, coords);
+ auto bits = BitSet64(coords.bits);
+ for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) {
+ const uint32_t axis = bits.clearFirstMarkedBit();
+ const float axisValueInWindow = coordsInWindow.values[axisIndex];
+ // Only values that are modified by the window transform are traced.
+ if (coords.values[axisIndex] != axisValueInWindow) {
+ auto* axisEntry = pointerProto->add_axis_value_in_window();
+ axisEntry->set_axis(axis);
+ axisEntry->set_value(axisValueInWindow);
+ }
+ }
+ }
+ }
+ }
+
+ static impl::TraceConfig parseConfig(ProtoConfigDecoder& protoConfig) {
+ if (protoConfig.has_mode() &&
+ protoConfig.mode() == proto::AndroidInputEventConfig::TRACE_MODE_TRACE_ALL) {
+ // User has requested the preset for maximal tracing
+ return internal::CONFIG_TRACE_ALL;
+ }
+
+ impl::TraceConfig config;
+
+ // Parse trace flags
+ if (protoConfig.has_trace_dispatcher_input_events() &&
+ protoConfig.trace_dispatcher_input_events()) {
+ config.flags |= impl::TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS;
+ }
+ if (protoConfig.has_trace_dispatcher_window_dispatch() &&
+ protoConfig.trace_dispatcher_window_dispatch()) {
+ config.flags |= impl::TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH;
+ }
+
+ // Parse trace rules
+ auto rulesIt = protoConfig.rules();
+ while (rulesIt) {
+ proto::AndroidInputEventConfig::TraceRule::Decoder protoRule{rulesIt->as_bytes()};
+ config.rules.emplace_back();
+ auto& rule = config.rules.back();
+
+ rule.level = protoRule.has_trace_level()
+ ? static_cast<impl::TraceLevel>(protoRule.trace_level())
+ : impl::TraceLevel::TRACE_LEVEL_NONE;
+
+ if (protoRule.has_match_all_packages()) {
+ auto pkgIt = protoRule.match_all_packages();
+ while (pkgIt) {
+ rule.matchAllPackages.emplace_back(pkgIt->as_std_string());
+ pkgIt++;
+ }
+ }
+
+ if (protoRule.has_match_any_packages()) {
+ auto pkgIt = protoRule.match_any_packages();
+ while (pkgIt) {
+ rule.matchAnyPackages.emplace_back(pkgIt->as_std_string());
+ pkgIt++;
+ }
+ }
+
+ if (protoRule.has_match_secure()) {
+ rule.matchSecure = protoRule.match_secure();
+ }
+
+ if (protoRule.has_match_ime_connection_active()) {
+ rule.matchImeConnectionActive = protoRule.match_ime_connection_active();
+ }
+
+ rulesIt++;
+ }
+
+ return config;
+ }
};
} // namespace android::inputdispatcher::trace
diff --git a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
index 761d619..823f8a5 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
+++ b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
@@ -70,7 +70,7 @@
uint32_t policyFlags;
int32_t deviceId;
uint32_t source;
- ui::LogicalDisplayId displayId;
+ ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
int32_t action;
int32_t actionButton;
int32_t flags;
diff --git a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
index 77b5c2e..ebcd9c9 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
+++ b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
@@ -34,6 +34,11 @@
constexpr auto INPUT_EVENT_TRACE_DATA_SOURCE_NAME = "android.input.inputevent";
+using ProtoConverter =
+ AndroidInputEventProtoConverter<proto::AndroidMotionEvent, proto::AndroidKeyEvent,
+ proto::AndroidWindowInputDispatchEvent,
+ proto::AndroidInputEventConfig::Decoder>;
+
bool isPermanentlyAllowed(gui::Uid uid) {
switch (uid.val()) {
case AID_SYSTEM:
@@ -85,7 +90,7 @@
const auto rawConfig = args.config->android_input_event_config_raw();
auto protoConfig = perfetto::protos::pbzero::AndroidInputEventConfig::Decoder{rawConfig};
- mConfig = AndroidInputEventProtoConverter::parseConfig(protoConfig);
+ mConfig = ProtoConverter::parseConfig(protoConfig);
}
void PerfettoBackend::InputEventDataSource::OnStart(const InputEventDataSource::StartArgs&) {
@@ -238,7 +243,7 @@
auto* inputEvent = winscopeExtensions->set_android_input_event();
auto* dispatchMotion = isRedacted ? inputEvent->set_dispatcher_motion_event_redacted()
: inputEvent->set_dispatcher_motion_event();
- AndroidInputEventProtoConverter::toProtoMotionEvent(event, *dispatchMotion, isRedacted);
+ ProtoConverter::toProtoMotionEvent(event, *dispatchMotion, isRedacted);
});
}
@@ -266,7 +271,7 @@
auto* inputEvent = winscopeExtensions->set_android_input_event();
auto* dispatchKey = isRedacted ? inputEvent->set_dispatcher_key_event_redacted()
: inputEvent->set_dispatcher_key_event();
- AndroidInputEventProtoConverter::toProtoKeyEvent(event, *dispatchKey, isRedacted);
+ ProtoConverter::toProtoKeyEvent(event, *dispatchKey, isRedacted);
});
}
@@ -295,8 +300,7 @@
auto* dispatchEvent = isRedacted
? inputEvent->set_dispatcher_window_dispatch_event_redacted()
: inputEvent->set_dispatcher_window_dispatch_event();
- AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(dispatchArgs, *dispatchEvent,
- isRedacted);
+ ProtoConverter::toProtoWindowDispatchEvent(dispatchArgs, *dispatchEvent, isRedacted);
});
}
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 5b88588..18d47f6 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -48,6 +48,7 @@
],
srcs: [
":inputdispatcher_common_test_sources",
+ "AndroidInputEventProtoConverter_test.cpp",
"AnrTracker_test.cpp",
"CapturedTouchpadEventConverter_test.cpp",
"CursorInputMapper_test.cpp",
diff --git a/services/inputflinger/tests/AndroidInputEventProtoConverter_test.cpp b/services/inputflinger/tests/AndroidInputEventProtoConverter_test.cpp
new file mode 100644
index 0000000..414da66
--- /dev/null
+++ b/services/inputflinger/tests/AndroidInputEventProtoConverter_test.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2025 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.
+ */
+
+#include "../dispatcher/trace/AndroidInputEventProtoConverter.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace android::inputdispatcher::trace {
+
+namespace {
+
+using testing::Return, testing::_;
+
+class MockProtoAxisValue {
+public:
+ MOCK_METHOD(void, set_axis, (int32_t));
+ MOCK_METHOD(void, set_value, (float));
+};
+
+class MockProtoPointer {
+public:
+ MOCK_METHOD(void, set_pointer_id, (uint32_t));
+ MOCK_METHOD(void, set_tool_type, (int32_t));
+ MOCK_METHOD(MockProtoAxisValue*, add_axis_value, ());
+};
+
+class MockProtoMotion {
+public:
+ MOCK_METHOD(void, set_event_id, (uint32_t));
+ MOCK_METHOD(void, set_event_time_nanos, (int64_t));
+ MOCK_METHOD(void, set_down_time_nanos, (int64_t));
+ MOCK_METHOD(void, set_source, (uint32_t));
+ MOCK_METHOD(void, set_action, (int32_t));
+ MOCK_METHOD(void, set_device_id, (uint32_t));
+ MOCK_METHOD(void, set_display_id, (uint32_t));
+ MOCK_METHOD(void, set_classification, (int32_t));
+ MOCK_METHOD(void, set_flags, (uint32_t));
+ MOCK_METHOD(void, set_policy_flags, (uint32_t));
+ MOCK_METHOD(void, set_button_state, (uint32_t));
+ MOCK_METHOD(void, set_action_button, (uint32_t));
+ MOCK_METHOD(void, set_cursor_position_x, (float));
+ MOCK_METHOD(void, set_cursor_position_y, (float));
+ MOCK_METHOD(void, set_meta_state, (uint32_t));
+ MOCK_METHOD(void, set_precision_x, (float));
+ MOCK_METHOD(void, set_precision_y, (float));
+ MOCK_METHOD(MockProtoPointer*, add_pointer, ());
+};
+
+using TestProtoConverter = AndroidInputEventProtoConverter<MockProtoMotion, proto::AndroidKeyEvent,
+ proto::AndroidWindowInputDispatchEvent,
+ proto::AndroidInputEventConfig::Decoder>;
+
+TEST(AndroidInputEventProtoConverterTest, ToProtoMotionEvent) {
+ TracedMotionEvent event{};
+ event.id = 1;
+ event.eventTime = 2;
+ event.downTime = 3;
+ event.source = AINPUT_SOURCE_MOUSE;
+ event.action = AMOTION_EVENT_ACTION_BUTTON_PRESS;
+ event.deviceId = 4;
+ event.displayId = ui::LogicalDisplayId(5);
+ event.classification = MotionClassification::PINCH;
+ event.flags = 6;
+ event.policyFlags = 7;
+ event.buttonState = 8;
+ event.actionButton = 9;
+ event.xCursorPosition = 10.0f;
+ event.yCursorPosition = 11.0f;
+ event.metaState = 12;
+ event.xPrecision = 13.0f;
+ event.yPrecision = 14.0f;
+ event.pointerProperties.emplace_back(PointerProperties{
+ .id = 15,
+ .toolType = ToolType::MOUSE,
+ });
+ event.pointerProperties.emplace_back(PointerProperties{
+ .id = 16,
+ .toolType = ToolType::FINGER,
+ });
+ event.pointerCoords.emplace_back();
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 17.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 18.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 19.0f);
+ event.pointerCoords.emplace_back();
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 20.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 21.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 22.0f);
+
+ testing::StrictMock<MockProtoMotion> proto;
+ testing::StrictMock<MockProtoPointer> pointer1;
+ testing::StrictMock<MockProtoPointer> pointer2;
+ testing::StrictMock<MockProtoAxisValue> axisValue1;
+ testing::StrictMock<MockProtoAxisValue> axisValue2;
+ testing::StrictMock<MockProtoAxisValue> axisValue3;
+ testing::StrictMock<MockProtoAxisValue> axisValue4;
+ testing::StrictMock<MockProtoAxisValue> axisValue5;
+ testing::StrictMock<MockProtoAxisValue> axisValue6;
+
+ EXPECT_CALL(proto, set_event_id(1));
+ EXPECT_CALL(proto, set_event_time_nanos(2));
+ EXPECT_CALL(proto, set_down_time_nanos(3));
+ EXPECT_CALL(proto, set_source(AINPUT_SOURCE_MOUSE));
+ EXPECT_CALL(proto, set_action(AMOTION_EVENT_ACTION_BUTTON_PRESS));
+ EXPECT_CALL(proto, set_device_id(4));
+ EXPECT_CALL(proto, set_display_id(5));
+ EXPECT_CALL(proto, set_classification(AMOTION_EVENT_CLASSIFICATION_PINCH));
+ EXPECT_CALL(proto, set_flags(6));
+ EXPECT_CALL(proto, set_policy_flags(7));
+ EXPECT_CALL(proto, set_button_state(8));
+ EXPECT_CALL(proto, set_action_button(9));
+ EXPECT_CALL(proto, set_cursor_position_x(10.0f));
+ EXPECT_CALL(proto, set_cursor_position_y(11.0f));
+ EXPECT_CALL(proto, set_meta_state(12));
+ EXPECT_CALL(proto, set_precision_x(13.0f));
+ EXPECT_CALL(proto, set_precision_y(14.0f));
+
+ EXPECT_CALL(proto, add_pointer()).WillOnce(Return(&pointer1)).WillOnce(Return(&pointer2));
+
+ EXPECT_CALL(pointer1, set_pointer_id(15));
+ EXPECT_CALL(pointer1, set_tool_type(AMOTION_EVENT_TOOL_TYPE_MOUSE));
+ EXPECT_CALL(pointer1, add_axis_value())
+ .WillOnce(Return(&axisValue1))
+ .WillOnce(Return(&axisValue2))
+ .WillOnce(Return(&axisValue3));
+ EXPECT_CALL(axisValue1, set_axis(AMOTION_EVENT_AXIS_X));
+ EXPECT_CALL(axisValue1, set_value(17.0f));
+ EXPECT_CALL(axisValue2, set_axis(AMOTION_EVENT_AXIS_Y));
+ EXPECT_CALL(axisValue2, set_value(18.0f));
+ EXPECT_CALL(axisValue3, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
+ EXPECT_CALL(axisValue3, set_value(19.0f));
+
+ EXPECT_CALL(pointer2, set_pointer_id(16));
+ EXPECT_CALL(pointer2, set_tool_type(AMOTION_EVENT_TOOL_TYPE_FINGER));
+ EXPECT_CALL(pointer2, add_axis_value())
+ .WillOnce(Return(&axisValue4))
+ .WillOnce(Return(&axisValue5))
+ .WillOnce(Return(&axisValue6));
+ EXPECT_CALL(axisValue4, set_axis(AMOTION_EVENT_AXIS_X));
+ EXPECT_CALL(axisValue4, set_value(20.0f));
+ EXPECT_CALL(axisValue5, set_axis(AMOTION_EVENT_AXIS_Y));
+ EXPECT_CALL(axisValue5, set_value(21.0f));
+ EXPECT_CALL(axisValue6, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
+ EXPECT_CALL(axisValue6, set_value(22.0f));
+
+ TestProtoConverter::toProtoMotionEvent(event, proto, /*isRedacted=*/false);
+}
+
+TEST(AndroidInputEventProtoConverterTest, ToProtoMotionEvent_Redacted) {
+ TracedMotionEvent event{};
+ event.id = 1;
+ event.eventTime = 2;
+ event.downTime = 3;
+ event.source = AINPUT_SOURCE_MOUSE;
+ event.action = AMOTION_EVENT_ACTION_BUTTON_PRESS;
+ event.deviceId = 4;
+ event.displayId = ui::LogicalDisplayId(5);
+ event.classification = MotionClassification::PINCH;
+ event.flags = 6;
+ event.policyFlags = 7;
+ event.buttonState = 8;
+ event.actionButton = 9;
+ event.xCursorPosition = 10.0f;
+ event.yCursorPosition = 11.0f;
+ event.metaState = 12;
+ event.xPrecision = 13.0f;
+ event.yPrecision = 14.0f;
+ event.pointerProperties.emplace_back(PointerProperties{
+ .id = 15,
+ .toolType = ToolType::MOUSE,
+ });
+ event.pointerProperties.emplace_back(PointerProperties{
+ .id = 16,
+ .toolType = ToolType::FINGER,
+ });
+ event.pointerCoords.emplace_back();
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 17.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 18.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 19.0f);
+ event.pointerCoords.emplace_back();
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 20.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 21.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 22.0f);
+
+ testing::StrictMock<MockProtoMotion> proto;
+ testing::StrictMock<MockProtoPointer> pointer1;
+ testing::StrictMock<MockProtoPointer> pointer2;
+ testing::StrictMock<MockProtoAxisValue> axisValue1;
+ testing::StrictMock<MockProtoAxisValue> axisValue2;
+ testing::StrictMock<MockProtoAxisValue> axisValue3;
+ testing::StrictMock<MockProtoAxisValue> axisValue4;
+ testing::StrictMock<MockProtoAxisValue> axisValue5;
+ testing::StrictMock<MockProtoAxisValue> axisValue6;
+
+ EXPECT_CALL(proto, set_event_id(1));
+ EXPECT_CALL(proto, set_event_time_nanos(2));
+ EXPECT_CALL(proto, set_down_time_nanos(3));
+ EXPECT_CALL(proto, set_source(AINPUT_SOURCE_MOUSE));
+ EXPECT_CALL(proto, set_action(AMOTION_EVENT_ACTION_BUTTON_PRESS));
+ EXPECT_CALL(proto, set_device_id(4));
+ EXPECT_CALL(proto, set_display_id(5));
+ EXPECT_CALL(proto, set_classification(AMOTION_EVENT_CLASSIFICATION_PINCH));
+ EXPECT_CALL(proto, set_flags(6));
+ EXPECT_CALL(proto, set_policy_flags(7));
+ EXPECT_CALL(proto, set_button_state(8));
+ EXPECT_CALL(proto, set_action_button(9));
+
+ EXPECT_CALL(proto, add_pointer()).WillOnce(Return(&pointer1)).WillOnce(Return(&pointer2));
+
+ EXPECT_CALL(pointer1, set_pointer_id(15));
+ EXPECT_CALL(pointer1, set_tool_type(AMOTION_EVENT_TOOL_TYPE_MOUSE));
+ EXPECT_CALL(pointer1, add_axis_value())
+ .WillOnce(Return(&axisValue1))
+ .WillOnce(Return(&axisValue2))
+ .WillOnce(Return(&axisValue3));
+ EXPECT_CALL(axisValue1, set_axis(AMOTION_EVENT_AXIS_X));
+ EXPECT_CALL(axisValue2, set_axis(AMOTION_EVENT_AXIS_Y));
+ EXPECT_CALL(axisValue3, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
+
+ EXPECT_CALL(pointer2, set_pointer_id(16));
+ EXPECT_CALL(pointer2, set_tool_type(AMOTION_EVENT_TOOL_TYPE_FINGER));
+ EXPECT_CALL(pointer2, add_axis_value())
+ .WillOnce(Return(&axisValue4))
+ .WillOnce(Return(&axisValue5))
+ .WillOnce(Return(&axisValue6));
+ EXPECT_CALL(axisValue4, set_axis(AMOTION_EVENT_AXIS_X));
+ EXPECT_CALL(axisValue5, set_axis(AMOTION_EVENT_AXIS_Y));
+ EXPECT_CALL(axisValue6, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
+
+ // Redacted fields
+ EXPECT_CALL(proto, set_meta_state(_)).Times(0);
+ EXPECT_CALL(proto, set_cursor_position_x(_)).Times(0);
+ EXPECT_CALL(proto, set_cursor_position_y(_)).Times(0);
+ EXPECT_CALL(proto, set_precision_x(_)).Times(0);
+ EXPECT_CALL(proto, set_precision_y(_)).Times(0);
+ EXPECT_CALL(axisValue1, set_value(_)).Times(0);
+ EXPECT_CALL(axisValue2, set_value(_)).Times(0);
+ EXPECT_CALL(axisValue3, set_value(_)).Times(0);
+ EXPECT_CALL(axisValue4, set_value(_)).Times(0);
+ EXPECT_CALL(axisValue5, set_value(_)).Times(0);
+ EXPECT_CALL(axisValue6, set_value(_)).Times(0);
+
+ TestProtoConverter::toProtoMotionEvent(event, proto, /*isRedacted=*/true);
+}
+
+} // namespace
+
+} // namespace android::inputdispatcher::trace
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
index 67b1e8c..5a14f4b 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
@@ -31,6 +31,30 @@
} // namespace
+DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
+ ui::Rotation orientation, bool isActive, const std::string& uniqueId,
+ std::optional<uint8_t> physicalPort, ViewportType type) {
+ const bool isRotated = orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270;
+ DisplayViewport v;
+ v.displayId = displayId;
+ v.orientation = orientation;
+ v.logicalLeft = 0;
+ v.logicalTop = 0;
+ v.logicalRight = isRotated ? height : width;
+ v.logicalBottom = isRotated ? width : height;
+ v.physicalLeft = 0;
+ v.physicalTop = 0;
+ v.physicalRight = isRotated ? height : width;
+ v.physicalBottom = isRotated ? width : height;
+ v.deviceWidth = isRotated ? height : width;
+ v.deviceHeight = isRotated ? width : height;
+ v.isActive = isActive;
+ v.uniqueId = uniqueId;
+ v.physicalPort = physicalPort;
+ v.type = type;
+ return v;
+};
+
void FakeInputReaderPolicy::assertInputDevicesChanged() {
waitForInputDevices(
[](bool devicesChanged) {
@@ -115,33 +139,6 @@
mConfig.setDisplayViewports(mViewports);
}
-void FakeInputReaderPolicy::addDisplayViewport(ui::LogicalDisplayId displayId, int32_t width,
- int32_t height, ui::Rotation orientation,
- bool isActive, const std::string& uniqueId,
- std::optional<uint8_t> physicalPort,
- ViewportType type) {
- const bool isRotated = orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270;
- DisplayViewport v;
- v.displayId = displayId;
- v.orientation = orientation;
- v.logicalLeft = 0;
- v.logicalTop = 0;
- v.logicalRight = isRotated ? height : width;
- v.logicalBottom = isRotated ? width : height;
- v.physicalLeft = 0;
- v.physicalTop = 0;
- v.physicalRight = isRotated ? height : width;
- v.physicalBottom = isRotated ? width : height;
- v.deviceWidth = isRotated ? height : width;
- v.deviceHeight = isRotated ? width : height;
- v.isActive = isActive;
- v.uniqueId = uniqueId;
- v.physicalPort = physicalPort;
- v.type = type;
-
- addDisplayViewport(v);
-}
-
bool FakeInputReaderPolicy::updateViewport(const DisplayViewport& viewport) {
size_t count = mViewports.size();
for (size_t i = 0; i < count; i++) {
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.h b/services/inputflinger/tests/FakeInputReaderPolicy.h
index 42c9567..9dce31a 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.h
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.h
@@ -31,6 +31,10 @@
namespace android {
+DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
+ ui::Rotation orientation, bool isActive, const std::string& uniqueId,
+ std::optional<uint8_t> physicalPort, ViewportType type);
+
class FakeInputReaderPolicy : public InputReaderPolicyInterface {
protected:
virtual ~FakeInputReaderPolicy() {}
@@ -50,9 +54,6 @@
std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const;
std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t displayPort) const;
void addDisplayViewport(DisplayViewport viewport);
- void addDisplayViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
- ui::Rotation orientation, bool isActive, const std::string& uniqueId,
- std::optional<uint8_t> physicalPort, ViewportType type);
bool updateViewport(const DisplayViewport& viewport);
void addExcludedDeviceName(const std::string& deviceName);
void addInputPortAssociation(const std::string& inputPort, uint8_t displayPort);
diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp
index 77f42f2..652a658 100644
--- a/services/inputflinger/tests/InputMapperTest.cpp
+++ b/services/inputflinger/tests/InputMapperTest.cpp
@@ -186,8 +186,10 @@
const std::string& uniqueId,
std::optional<uint8_t> physicalPort,
ViewportType viewportType) {
- mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /* isActive= */ true,
- uniqueId, physicalPort, viewportType);
+ DisplayViewport viewport =
+ createViewport(displayId, width, height, orientation, /* isActive= */ true, uniqueId,
+ physicalPort, viewportType);
+ mFakePolicy->addDisplayViewport(viewport);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
}
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 50cbedf..a8e4736 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -385,30 +385,29 @@
static const std::string uniqueId = "local:0";
// We didn't add any viewports yet, so there shouldn't be any.
- std::optional<DisplayViewport> internalViewport =
- mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_FALSE(internalViewport);
+ ASSERT_FALSE(mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL));
// Add an internal viewport, then clear it
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, uniqueId, NO_PORT, ViewportType::INTERNAL);
-
+ DisplayViewport internalViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(internalViewport);
// Check matching by uniqueId
- internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
- ASSERT_TRUE(internalViewport);
- ASSERT_EQ(ViewportType::INTERNAL, internalViewport->type);
+ std::optional<DisplayViewport> receivedInternalViewport =
+ mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
+ ASSERT_TRUE(receivedInternalViewport.has_value());
+ ASSERT_EQ(internalViewport, *receivedInternalViewport);
// Check matching by viewport type
- internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_TRUE(internalViewport);
- ASSERT_EQ(uniqueId, internalViewport->uniqueId);
+ receivedInternalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
+ ASSERT_TRUE(receivedInternalViewport.has_value());
+ ASSERT_EQ(internalViewport, *receivedInternalViewport);
mFakePolicy->clearViewports();
+
// Make sure nothing is found after clear
- internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
- ASSERT_FALSE(internalViewport);
- internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_FALSE(internalViewport);
+ ASSERT_FALSE(mFakePolicy->getDisplayViewportByUniqueId(uniqueId));
+ ASSERT_FALSE(mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL));
}
TEST_F(InputReaderPolicyTest, Viewports_GetByType) {
@@ -420,49 +419,49 @@
constexpr ui::LogicalDisplayId virtualDisplayId2 = ui::LogicalDisplayId{3};
// Add an internal viewport
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, internalUniqueId, NO_PORT,
- ViewportType::INTERNAL);
+ DisplayViewport internalViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, internalUniqueId, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(internalViewport);
// Add an external viewport
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, externalUniqueId, NO_PORT,
- ViewportType::EXTERNAL);
+ DisplayViewport externalViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, externalUniqueId, NO_PORT, ViewportType::EXTERNAL);
+ mFakePolicy->addDisplayViewport(externalViewport);
// Add an virtual viewport
- mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, virtualUniqueId1, NO_PORT,
- ViewportType::VIRTUAL);
+ DisplayViewport virtualViewport1 =
+ createViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, virtualUniqueId1, NO_PORT, ViewportType::VIRTUAL);
+ mFakePolicy->addDisplayViewport(virtualViewport1);
// Add another virtual viewport
- mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, virtualUniqueId2, NO_PORT,
- ViewportType::VIRTUAL);
+ DisplayViewport virtualViewport2 =
+ createViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, virtualUniqueId2, NO_PORT, ViewportType::VIRTUAL);
+ mFakePolicy->addDisplayViewport(virtualViewport2);
// Check matching by type for internal
- std::optional<DisplayViewport> internalViewport =
+ std::optional<DisplayViewport> receivedInternalViewport =
mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_TRUE(internalViewport);
- ASSERT_EQ(internalUniqueId, internalViewport->uniqueId);
+ ASSERT_TRUE(receivedInternalViewport.has_value());
+ ASSERT_EQ(internalViewport, *receivedInternalViewport);
// Check matching by type for external
- std::optional<DisplayViewport> externalViewport =
+ std::optional<DisplayViewport> receivedExternalViewport =
mFakePolicy->getDisplayViewportByType(ViewportType::EXTERNAL);
- ASSERT_TRUE(externalViewport);
- ASSERT_EQ(externalUniqueId, externalViewport->uniqueId);
+ ASSERT_TRUE(receivedExternalViewport.has_value());
+ ASSERT_EQ(externalViewport, *receivedExternalViewport);
// Check matching by uniqueId for virtual viewport #1
- std::optional<DisplayViewport> virtualViewport1 =
+ std::optional<DisplayViewport> receivedVirtualViewport1 =
mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId1);
- ASSERT_TRUE(virtualViewport1);
- ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport1->type);
- ASSERT_EQ(virtualUniqueId1, virtualViewport1->uniqueId);
- ASSERT_EQ(virtualDisplayId1, virtualViewport1->displayId);
+ ASSERT_TRUE(receivedVirtualViewport1.has_value());
+ ASSERT_EQ(virtualViewport1, *receivedVirtualViewport1);
// Check matching by uniqueId for virtual viewport #2
- std::optional<DisplayViewport> virtualViewport2 =
+ std::optional<DisplayViewport> receivedVirtualViewport2 =
mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId2);
- ASSERT_TRUE(virtualViewport2);
- ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport2->type);
- ASSERT_EQ(virtualUniqueId2, virtualViewport2->uniqueId);
- ASSERT_EQ(virtualDisplayId2, virtualViewport2->displayId);
+ ASSERT_TRUE(receivedVirtualViewport2.has_value());
+ ASSERT_EQ(virtualViewport2, *receivedVirtualViewport2);
}
@@ -482,24 +481,26 @@
for (const ViewportType& type : types) {
mFakePolicy->clearViewports();
// Add a viewport
- mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, uniqueId1, NO_PORT, type);
+ DisplayViewport viewport1 =
+ createViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId1, NO_PORT, type);
+ mFakePolicy->addDisplayViewport(viewport1);
// Add another viewport
- mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, uniqueId2, NO_PORT, type);
+ DisplayViewport viewport2 =
+ createViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId2, NO_PORT, type);
+ mFakePolicy->addDisplayViewport(viewport2);
// Check that correct display viewport was returned by comparing the display IDs.
- std::optional<DisplayViewport> viewport1 =
+ std::optional<DisplayViewport> receivedViewport1 =
mFakePolicy->getDisplayViewportByUniqueId(uniqueId1);
- ASSERT_TRUE(viewport1);
- ASSERT_EQ(displayId1, viewport1->displayId);
- ASSERT_EQ(type, viewport1->type);
+ ASSERT_TRUE(receivedViewport1.has_value());
+ ASSERT_EQ(viewport1, *receivedViewport1);
- std::optional<DisplayViewport> viewport2 =
+ std::optional<DisplayViewport> receivedViewport2 =
mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
- ASSERT_TRUE(viewport2);
- ASSERT_EQ(displayId2, viewport2->displayId);
- ASSERT_EQ(type, viewport2->type);
+ ASSERT_TRUE(receivedViewport2.has_value());
+ ASSERT_EQ(viewport2, *receivedViewport2);
// When there are multiple viewports of the same kind, and uniqueId is not specified
// in the call to getDisplayViewport, then that situation is not supported.
@@ -525,32 +526,27 @@
// Add the default display first and ensure it gets returned.
mFakePolicy->clearViewports();
- mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
- ViewportType::INTERNAL);
- mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
- ViewportType::INTERNAL);
-
- std::optional<DisplayViewport> viewport =
+ DisplayViewport viewport1 = createViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH,
+ DISPLAY_HEIGHT, ui::ROTATION_0, /*isActive=*/true,
+ uniqueId1, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport1);
+ DisplayViewport viewport2 =
+ createViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId2, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport2);
+ std::optional<DisplayViewport> receivedViewport =
mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_TRUE(viewport);
- ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
- ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
+ ASSERT_TRUE(receivedViewport.has_value());
+ ASSERT_EQ(viewport1, *receivedViewport);
// Add the default display second to make sure order doesn't matter.
mFakePolicy->clearViewports();
- mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
- ViewportType::INTERNAL);
- mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
- ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport2);
+ mFakePolicy->addDisplayViewport(viewport1);
- viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_TRUE(viewport);
- ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
- ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
+ receivedViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
+ ASSERT_TRUE(receivedViewport.has_value());
+ ASSERT_EQ(viewport1, *receivedViewport);
}
/**
@@ -568,28 +564,27 @@
mFakePolicy->clearViewports();
// Add a viewport that's associated with some display port that's not of interest.
- mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, uniqueId1, hdmi3, type);
+ DisplayViewport viewport1 =
+ createViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId1, hdmi3, type);
+ mFakePolicy->addDisplayViewport(viewport1);
// Add another viewport, connected to HDMI1 port
- mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, uniqueId2, hdmi1, type);
-
+ DisplayViewport viewport2 =
+ createViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId2, hdmi1, type);
+ mFakePolicy->addDisplayViewport(viewport2);
// Check that correct display viewport was returned by comparing the display ports.
std::optional<DisplayViewport> hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1);
- ASSERT_TRUE(hdmi1Viewport);
- ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
- ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
+ ASSERT_TRUE(hdmi1Viewport.has_value());
+ ASSERT_EQ(viewport2, *hdmi1Viewport);
// Check that we can still get the same viewport using the uniqueId
hdmi1Viewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
- ASSERT_TRUE(hdmi1Viewport);
- ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
- ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
- ASSERT_EQ(type, hdmi1Viewport->type);
+ ASSERT_TRUE(hdmi1Viewport.has_value());
+ ASSERT_EQ(viewport2, *hdmi1Viewport);
// Check that we cannot find a port with "HDMI2", because we never added one
- std::optional<DisplayViewport> hdmi2Viewport = mFakePolicy->getDisplayViewportByPort(hdmi2);
- ASSERT_FALSE(hdmi2Viewport);
+ ASSERT_FALSE(mFakePolicy->getDisplayViewportByPort(hdmi2));
}
// --- InputReaderTest ---
@@ -1046,11 +1041,14 @@
// Add default and second display.
mFakePolicy->clearViewports();
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
- mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, "local:1", hdmi1,
- ViewportType::EXTERNAL);
+ DisplayViewport internalViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(internalViewport);
+ DisplayViewport externalViewport =
+ createViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, "local:1", hdmi1, ViewportType::EXTERNAL);
+ mFakePolicy->addDisplayViewport(externalViewport);
mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
mReader->loopOnce();
@@ -1653,7 +1651,7 @@
mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto info = waitForDevice(mDevice->getName());
- ASSERT_TRUE(info);
+ ASSERT_TRUE(info.has_value());
mDeviceInfo = *info;
}
@@ -1661,8 +1659,10 @@
ui::Rotation orientation, const std::string& uniqueId,
std::optional<uint8_t> physicalPort,
ViewportType viewportType) {
- mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /*isActive=*/true,
- uniqueId, physicalPort, viewportType);
+ DisplayViewport viewport =
+ createViewport(displayId, width, height, orientation, /*isActive=*/true, uniqueId,
+ physicalPort, viewportType);
+ mFakePolicy->addDisplayViewport(viewport);
mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
}
@@ -1721,7 +1721,7 @@
ViewportType::INTERNAL);
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto info = waitForDevice(mDevice->getName());
- ASSERT_TRUE(info);
+ ASSERT_TRUE(info.has_value());
mDeviceInfo = *info;
}
};
@@ -2053,7 +2053,7 @@
auto externalStylus = createUinputDevice<UinputExternalStylus>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto stylusInfo = waitForDevice(externalStylus->getName());
- ASSERT_TRUE(stylusInfo);
+ ASSERT_TRUE(stylusInfo.has_value());
// Move
mDevice->sendMove(centerPoint + Point(2, 2));
@@ -2122,7 +2122,7 @@
mStylus = mStylusDeviceLifecycleTracker.get();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto info = waitForDevice(mStylus->getName());
- ASSERT_TRUE(info);
+ ASSERT_TRUE(info.has_value());
mStylusInfo = *info;
}
@@ -2395,7 +2395,7 @@
// Connecting an external stylus changes the source of the touchscreen.
const auto deviceInfo = waitForDevice(mDevice->getName());
- ASSERT_TRUE(deviceInfo);
+ ASSERT_TRUE(deviceInfo.has_value());
ASSERT_TRUE(isFromSource(deviceInfo->getSources(), STYLUS_FUSION_SOURCE));
}
@@ -2408,7 +2408,7 @@
createUinputDevice<UinputExternalStylusWithPressure>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto stylusInfo = waitForDevice(stylus->getName());
- ASSERT_TRUE(stylusInfo);
+ ASSERT_TRUE(stylusInfo.has_value());
ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
@@ -2453,7 +2453,7 @@
createUinputDevice<UinputExternalStylusWithPressure>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto stylusInfo = waitForDevice(stylus->getName());
- ASSERT_TRUE(stylusInfo);
+ ASSERT_TRUE(stylusInfo.has_value());
ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
@@ -2880,9 +2880,10 @@
ASSERT_FALSE(mDevice->isEnabled());
// Prepare displays.
- mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, UNIQUE_ID, hdmi,
- ViewportType::INTERNAL);
+ DisplayViewport viewport =
+ createViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, UNIQUE_ID, hdmi, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport);
unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::Change::DISPLAY_INFO);
ASSERT_TRUE(mDevice->isEnabled());
@@ -2917,9 +2918,12 @@
ASSERT_FALSE(mDevice->isEnabled());
// Device should be enabled when a display is found.
- mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
- NO_PORT, ViewportType::INTERNAL);
+
+ DisplayViewport secondViewport =
+ createViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /* isActive= */ true, DISPLAY_UNIQUE_ID, NO_PORT,
+ ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(secondViewport);
unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::Change::DISPLAY_INFO);
ASSERT_TRUE(mDevice->isEnabled());
@@ -2945,9 +2949,12 @@
/*changes=*/{});
mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
- mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
- NO_PORT, ViewportType::INTERNAL);
+
+ DisplayViewport secondViewport =
+ createViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /* isActive= */ true, DISPLAY_UNIQUE_ID, NO_PORT,
+ ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(secondViewport);
const auto initialGeneration = mDevice->getGeneration();
unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::Change::DISPLAY_INFO);
@@ -7594,8 +7601,10 @@
TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
addConfigurationProperty("touch.deviceType", "touchScreen");
// Don't set touch.enableForInactiveViewport to verify the default behavior.
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ DisplayViewport viewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
@@ -7614,8 +7623,10 @@
TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
addConfigurationProperty("touch.deviceType", "touchScreen");
addConfigurationProperty("touch.enableForInactiveViewport", "1");
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ DisplayViewport viewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
@@ -7636,8 +7647,10 @@
TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
addConfigurationProperty("touch.deviceType", "touchScreen");
addConfigurationProperty("touch.enableForInactiveViewport", "0");
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ DisplayViewport viewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport);
std::optional<DisplayViewport> optionalDisplayViewport =
mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
ASSERT_TRUE(optionalDisplayViewport.has_value());
@@ -7692,12 +7705,10 @@
TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_TouchesNotAborted) {
addConfigurationProperty("touch.deviceType", "touchScreen");
addConfigurationProperty("touch.enableForInactiveViewport", "1");
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
- std::optional<DisplayViewport> optionalDisplayViewport =
- mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
- ASSERT_TRUE(optionalDisplayViewport.has_value());
- DisplayViewport displayViewport = *optionalDisplayViewport;
+ DisplayViewport displayViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(displayViewport);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
diff --git a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
index 0ea22d4..b7cb348 100644
--- a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
+++ b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
@@ -109,9 +109,10 @@
mockSlotValues({});
mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID);
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, "local:0", NO_PORT,
- ViewportType::INTERNAL);
+ DisplayViewport internalViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(internalViewport);
mMapper = createInputMapper<MultiTouchInputMapper>(*mDeviceContext,
mFakePolicy->getReaderConfiguration());
}
diff --git a/services/inputflinger/tests/TouchpadInputMapper_test.cpp b/services/inputflinger/tests/TouchpadInputMapper_test.cpp
index 0789114..5f5aa63 100644
--- a/services/inputflinger/tests/TouchpadInputMapper_test.cpp
+++ b/services/inputflinger/tests/TouchpadInputMapper_test.cpp
@@ -124,9 +124,10 @@
*/
TEST_F(TouchpadInputMapperTest, HoverAndLeftButtonPress) {
mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID);
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
-
+ DisplayViewport viewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport);
std::list<NotifyArgs> args;
args += mMapper->reconfigure(systemTime(SYSTEM_TIME_MONOTONIC), mReaderConfiguration,