Merge "Better logs for "Unable to generate SkImage/SkSurface"" into udc-dev
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 92b1677..f1d8c72 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -540,6 +540,7 @@
# Run atrace with the categories written in a file
service boottrace /system/bin/atrace --async_start -f /data/misc/boottrace/categories
+ user root
disabled
oneshot
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 043a7f1..8ca927e 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2206,6 +2206,16 @@
continue;
}
+ // Skip cached processes.
+ if (IsCached(pid)) {
+ // For consistency, the header and footer to this message match those
+ // dumped by debuggerd in the success case.
+ dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
+ dprintf(fd, "Dump skipped for cached process.\n");
+ dprintf(fd, "---- end %d ----", pid);
+ continue;
+ }
+
const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
std::string exe;
if (!android::base::Readlink(link_name, &exe)) {
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index a80da4e..d0030dd 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -8,6 +8,7 @@
socket dumpstate stream 0660 shell log
disabled
oneshot
+ user root
# dumpstatez generates a zipped bugreport but also uses a socket to print the file location once
# it is finished.
@@ -16,9 +17,11 @@
class main
disabled
oneshot
+ user root
# bugreportd starts dumpstate binder service and makes it wait for a listener to connect.
service bugreportd /system/bin/dumpstate -w
class main
disabled
oneshot
+ user root
diff --git a/cmds/installd/installd.rc b/cmds/installd/installd.rc
index 5b08c77..525f0c8 100644
--- a/cmds/installd/installd.rc
+++ b/cmds/installd/installd.rc
@@ -1,6 +1,7 @@
service installd /system/bin/installd
class main
+ user root
capabilities CHOWN DAC_OVERRIDE DAC_READ_SEARCH FOWNER FSETID KILL SETGID SETUID SYS_ADMIN
on early-boot
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index cc8ac0a..63f3821 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -700,6 +700,11 @@
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't linkToDeath.");
}
+ // make sure all callbacks have been told about a consistent state - b/278038751
+ if (serviceIt->second.hasClients) {
+ cb->onClients(service, true);
+ }
+
mNameToClientCallback[name].push_back(cb);
return Status::ok();
diff --git a/include/input/Input.h b/include/input/Input.h
index a033535..1e810b4 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -210,7 +210,20 @@
*/
float transformAngle(const ui::Transform& transform, float angleRadians);
-const char* inputEventTypeToString(int32_t type);
+/**
+ * The type of the InputEvent.
+ * This should have 1:1 correspondence with the values of anonymous enum defined in input.h.
+ */
+enum class InputEventType {
+ KEY = AINPUT_EVENT_TYPE_KEY,
+ MOTION = AINPUT_EVENT_TYPE_MOTION,
+ FOCUS = AINPUT_EVENT_TYPE_FOCUS,
+ CAPTURE = AINPUT_EVENT_TYPE_CAPTURE,
+ DRAG = AINPUT_EVENT_TYPE_DRAG,
+ TOUCH_MODE = AINPUT_EVENT_TYPE_TOUCH_MODE,
+ ftl_first = KEY,
+ ftl_last = TOUCH_MODE,
+};
std::string inputEventSourceToString(int32_t source);
@@ -482,7 +495,7 @@
public:
virtual ~InputEvent() { }
- virtual int32_t getType() const = 0;
+ virtual InputEventType getType() const = 0;
inline int32_t getId() const { return mId; }
@@ -513,6 +526,8 @@
std::array<uint8_t, 32> mHmac;
};
+std::ostream& operator<<(std::ostream& out, const InputEvent& event);
+
/*
* Key events.
*/
@@ -520,7 +535,7 @@
public:
virtual ~KeyEvent() { }
- virtual int32_t getType() const { return AINPUT_EVENT_TYPE_KEY; }
+ virtual InputEventType getType() const { return InputEventType::KEY; }
inline int32_t getAction() const { return mAction; }
@@ -571,7 +586,7 @@
public:
virtual ~MotionEvent() { }
- virtual int32_t getType() const { return AINPUT_EVENT_TYPE_MOTION; }
+ virtual InputEventType getType() const { return InputEventType::MOTION; }
inline int32_t getAction() const { return mAction; }
@@ -899,7 +914,7 @@
public:
virtual ~FocusEvent() {}
- virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_FOCUS; }
+ virtual InputEventType getType() const override { return InputEventType::FOCUS; }
inline bool getHasFocus() const { return mHasFocus; }
@@ -918,7 +933,7 @@
public:
virtual ~CaptureEvent() {}
- virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_CAPTURE; }
+ virtual InputEventType getType() const override { return InputEventType::CAPTURE; }
inline bool getPointerCaptureEnabled() const { return mPointerCaptureEnabled; }
@@ -937,7 +952,7 @@
public:
virtual ~DragEvent() {}
- virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_DRAG; }
+ virtual InputEventType getType() const override { return InputEventType::DRAG; }
inline bool isExiting() const { return mIsExiting; }
@@ -961,7 +976,7 @@
public:
virtual ~TouchModeEvent() {}
- virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_TOUCH_MODE; }
+ virtual InputEventType getType() const override { return InputEventType::TOUCH_MODE; }
inline bool isInTouchMode() const { return mIsInTouchMode; }
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index c67310e..9423041 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -227,7 +227,7 @@
status_t parseMapKey();
status_t parseKey();
status_t parseKeyProperty();
- status_t finishKey(Key* key);
+ status_t finishKey(Key& key);
status_t parseModifier(const std::string& token, int32_t* outMetaState);
status_t parseCharacterLiteral(char16_t* outCharacter);
};
@@ -243,7 +243,7 @@
KeyCharacterMap(const std::string& filename);
- bool getKey(int32_t keyCode, const Key** outKey) const;
+ const Key* getKey(int32_t keyCode) const;
const Behavior* getKeyBehavior(int32_t keyCode, int32_t metaState) const;
static bool matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState);
diff --git a/include/input/RingBuffer.h b/include/input/RingBuffer.h
index 67984b7..37fe5af 100644
--- a/include/input/RingBuffer.h
+++ b/include/input/RingBuffer.h
@@ -103,6 +103,11 @@
iterator end() { return {*this, mSize}; }
const_iterator end() const { return {*this, mSize}; }
+ reference front() { return mBuffer[mBegin]; }
+ const_reference front() const { return mBuffer[mBegin]; }
+ reference back() { return mBuffer[bufferIndex(mSize - 1)]; }
+ const_reference back() const { return mBuffer[bufferIndex(mSize - 1)]; }
+
reference operator[](size_type i) { return mBuffer[bufferIndex(i)]; }
const_reference operator[](size_type i) const { return mBuffer[bufferIndex(i)]; }
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index 0de804c..69b11c0 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -128,6 +128,15 @@
remote()->transact(NOTE_RESET_FLASHLIGHT_TRANSACTION, data, &reply);
}
+ virtual binder::Status noteWakeupSensorEvent(int64_t elapsedNanos, int uid, int handle) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+ data.writeInt64(elapsedNanos);
+ data.writeInt32(uid);
+ data.writeInt32(handle);
+ status_t ret = remote()->transact(NOTE_WAKEUP_SENSOR_EVENT_TRANSACTION, data, &reply);
+ return binder::Status::fromStatusT(ret);
+ }
};
IMPLEMENT_META_INTERFACE(BatteryStats, "com.android.internal.app.IBatteryStats")
@@ -235,6 +244,16 @@
reply->writeNoException();
return NO_ERROR;
} break;
+ case NOTE_WAKEUP_SENSOR_EVENT_TRANSACTION: {
+ CHECK_INTERFACE(IBatteryStats, data, reply);
+ int64_t elapsedNanos = data.readInt64();
+ int uid = data.readInt32();
+ int handle = data.readInt32();
+ noteWakeupSensorEvent(elapsedNanos, uid, handle);
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/binder/RecordedTransaction.cpp b/libs/binder/RecordedTransaction.cpp
index ef58ed3..1c76135 100644
--- a/libs/binder/RecordedTransaction.cpp
+++ b/libs/binder/RecordedTransaction.cpp
@@ -131,12 +131,12 @@
return std::nullopt;
}
- if (t.mSent.setData(dataParcel.data(), dataParcel.dataSize()) != android::NO_ERROR) {
+ if (t.mSent.setData(dataParcel.data(), dataParcel.dataBufferSize()) != android::NO_ERROR) {
LOG(ERROR) << "Failed to set sent parcel data.";
return std::nullopt;
}
- if (t.mReply.setData(replyParcel.data(), replyParcel.dataSize()) != android::NO_ERROR) {
+ if (t.mReply.setData(replyParcel.data(), replyParcel.dataBufferSize()) != android::NO_ERROR) {
LOG(ERROR) << "Failed to set reply parcel data.";
return std::nullopt;
}
@@ -349,11 +349,11 @@
return UNKNOWN_ERROR;
}
- if (NO_ERROR != writeChunk(fd, DATA_PARCEL_CHUNK, mSent.dataSize(), mSent.data())) {
+ if (NO_ERROR != writeChunk(fd, DATA_PARCEL_CHUNK, mSent.dataBufferSize(), mSent.data())) {
LOG(ERROR) << "Failed to write sent Parcel to fd " << fd.get();
return UNKNOWN_ERROR;
}
- if (NO_ERROR != writeChunk(fd, REPLY_PARCEL_CHUNK, mReply.dataSize(), mReply.data())) {
+ if (NO_ERROR != writeChunk(fd, REPLY_PARCEL_CHUNK, mReply.dataBufferSize(), mReply.data())) {
LOG(ERROR) << "Failed to write reply Parcel to fd " << fd.get();
return UNKNOWN_ERROR;
}
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 851b407..9282856 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -553,7 +553,7 @@
socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
if (!socket_fd.ok()) {
int savedErrno = errno;
- ALOGE("Could not create socket: %s", strerror(savedErrno));
+ ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
return -savedErrno;
}
if (0 != TEMP_FAILURE_RETRY(bind(socket_fd.get(), addr.addr(), addr.addrSize()))) {
diff --git a/libs/binder/include_batterystats/batterystats/IBatteryStats.h b/libs/binder/include_batterystats/batterystats/IBatteryStats.h
index 6defc7f..5bb01dd 100644
--- a/libs/binder/include_batterystats/batterystats/IBatteryStats.h
+++ b/libs/binder/include_batterystats/batterystats/IBatteryStats.h
@@ -19,6 +19,7 @@
#ifndef __ANDROID_VNDK__
#include <binder/IInterface.h>
+#include <binder/Status.h>
namespace android {
@@ -43,6 +44,7 @@
virtual void noteStopCamera(int uid) = 0;
virtual void noteResetCamera() = 0;
virtual void noteResetFlashlight() = 0;
+ virtual binder::Status noteWakeupSensorEvent(int64_t elapsedNanos, int uid, int sensor) = 0;
enum {
NOTE_START_SENSOR_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
@@ -58,7 +60,8 @@
NOTE_START_CAMERA_TRANSACTION,
NOTE_STOP_CAMERA_TRANSACTION,
NOTE_RESET_CAMERA_TRANSACTION,
- NOTE_RESET_FLASHLIGHT_TRANSACTION
+ NOTE_RESET_FLASHLIGHT_TRANSACTION,
+ NOTE_WAKEUP_SENSOR_EVENT_TRANSACTION
};
};
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 504b3ce..8d13007 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1126,6 +1126,11 @@
android::base::unique_fd serverFd(
TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
+
+ if (errno == EAFNOSUPPORT) {
+ return false;
+ }
+
LOG_ALWAYS_FATAL_IF(serverFd == -1, "Could not create socket: %s", strerror(errno));
sockaddr_vm serverAddr{
diff --git a/libs/binder/trusty/RpcServerTrusty.cpp b/libs/binder/trusty/RpcServerTrusty.cpp
index 3a99606..68b0008 100644
--- a/libs/binder/trusty/RpcServerTrusty.cpp
+++ b/libs/binder/trusty/RpcServerTrusty.cpp
@@ -65,6 +65,10 @@
mTipcPort.msg_queue_len = 6; // Three each way
mTipcPort.priv = this;
+ // TODO(b/266741352): follow-up to prevent needing this in the future
+ // Trusty needs to be set to the latest stable version that is in prebuilts there.
+ mRpcServer->setProtocolVersion(0);
+
if (mPortAcl) {
// Initialize the array of pointers to uuids.
// The pointers in mUuidPtrs should stay valid across moves of
diff --git a/libs/bufferqueueconverter/Android.bp b/libs/bufferqueueconverter/Android.bp
index 5f145a1..d4605ea 100644
--- a/libs/bufferqueueconverter/Android.bp
+++ b/libs/bufferqueueconverter/Android.bp
@@ -13,7 +13,7 @@
export_include_dirs: ["include"],
}
-cc_library_shared {
+cc_library {
name: "libbufferqueueconverter",
vendor_available: true,
vndk: {
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 067ce17..97cb810 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -16,6 +16,7 @@
#include <set>
#include <android-base/file.h>
+#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -210,3 +211,18 @@
return cmdline == "zygote" || cmdline == "zygote64" || cmdline == "usap32" ||
cmdline == "usap64" || cmdline == "webview_zygote";
}
+
+bool IsCached(int pid) {
+ std::string oom_score_adj;
+ if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/oom_score_adj",
+ pid),
+ &oom_score_adj)) {
+ return false;
+ }
+ int32_t oom_score_adj_value;
+ if (!android::base::ParseInt(android::base::Trim(oom_score_adj), &oom_score_adj_value)) {
+ return false;
+ }
+ // An OOM score greater than 900 indicates a cached process.
+ return oom_score_adj_value >= 900;
+}
diff --git a/libs/dumputils/include/dumputils/dump_utils.h b/libs/dumputils/include/dumputils/dump_utils.h
index 7c5329d..f973d9f 100644
--- a/libs/dumputils/include/dumputils/dump_utils.h
+++ b/libs/dumputils/include/dumputils/dump_utils.h
@@ -25,4 +25,6 @@
bool IsZygote(int pid);
+bool IsCached(int pid);
+
#endif // DUMPUTILS_H_
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 821dd37..5c324b2 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -582,7 +582,8 @@
// Only update mSize for destination bounds if the incoming buffer matches the requested size.
// Otherwise, it could cause stretching since the destination bounds will update before the
// buffer with the new size is acquired.
- if (mRequestedSize == getBufferSize(bufferItem)) {
+ if (mRequestedSize == getBufferSize(bufferItem) ||
+ bufferItem.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
mSize = mRequestedSize;
}
Rect crop = computeCrop(bufferItem);
@@ -800,34 +801,24 @@
mDequeueTimestamps.erase(bufferId);
};
-void BLASTBufferQueue::syncNextTransaction(
+bool BLASTBufferQueue::syncNextTransaction(
std::function<void(SurfaceComposerClient::Transaction*)> callback,
bool acquireSingleBuffer) {
- std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr;
- SurfaceComposerClient::Transaction* prevTransaction = nullptr;
+ LOG_ALWAYS_FATAL_IF(!callback,
+ "BLASTBufferQueue: callback passed in to syncNextTransaction must not be "
+ "NULL");
- {
- std::lock_guard _lock{mMutex};
- BBQ_TRACE();
- // We're about to overwrite the previous call so we should invoke that callback
- // immediately.
- if (mTransactionReadyCallback) {
- prevCallback = mTransactionReadyCallback;
- prevTransaction = mSyncTransaction;
- }
-
- mTransactionReadyCallback = callback;
- if (callback) {
- mSyncTransaction = new SurfaceComposerClient::Transaction();
- } else {
- mSyncTransaction = nullptr;
- }
- mAcquireSingleBuffer = mTransactionReadyCallback ? acquireSingleBuffer : true;
+ std::lock_guard _lock{mMutex};
+ BBQ_TRACE();
+ if (mTransactionReadyCallback) {
+ ALOGW("Attempting to overwrite transaction callback in syncNextTransaction");
+ return false;
}
- if (prevCallback) {
- prevCallback(prevTransaction);
- }
+ mTransactionReadyCallback = callback;
+ mSyncTransaction = new SurfaceComposerClient::Transaction();
+ mAcquireSingleBuffer = acquireSingleBuffer;
+ return true;
}
void BLASTBufferQueue::stopContinuousSyncTransaction() {
@@ -835,20 +826,35 @@
SurfaceComposerClient::Transaction* prevTransaction = nullptr;
{
std::lock_guard _lock{mMutex};
- bool invokeCallback = mTransactionReadyCallback && !mAcquireSingleBuffer;
- if (invokeCallback) {
- prevCallback = mTransactionReadyCallback;
- prevTransaction = mSyncTransaction;
+ if (mAcquireSingleBuffer || !mTransactionReadyCallback) {
+ ALOGW("Attempting to stop continuous sync when none are active");
+ return;
}
+
+ prevCallback = mTransactionReadyCallback;
+ prevTransaction = mSyncTransaction;
+
mTransactionReadyCallback = nullptr;
mSyncTransaction = nullptr;
mAcquireSingleBuffer = true;
}
+
if (prevCallback) {
prevCallback(prevTransaction);
}
}
+void BLASTBufferQueue::clearSyncTransaction() {
+ std::lock_guard _lock{mMutex};
+ if (!mAcquireSingleBuffer) {
+ ALOGW("Attempting to clear sync transaction when none are active");
+ return;
+ }
+
+ mTransactionReadyCallback = nullptr;
+ mSyncTransaction = nullptr;
+}
+
bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) {
if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
// Only reject buffers if scaling mode is freeze.
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index b18bf5b..a5cf8d6 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -793,11 +793,15 @@
return result;
}
- std::vector<CancelBufferInput> cancelBufferInputs(numBufferRequested);
+ std::vector<CancelBufferInput> cancelBufferInputs;
+ cancelBufferInputs.reserve(numBufferRequested);
std::vector<status_t> cancelBufferOutputs;
for (size_t i = 0; i < numBufferRequested; i++) {
- cancelBufferInputs[i].slot = dequeueOutput[i].slot;
- cancelBufferInputs[i].fence = dequeueOutput[i].fence;
+ if (dequeueOutput[i].result >= 0) {
+ CancelBufferInput& input = cancelBufferInputs.emplace_back();
+ input.slot = dequeueOutput[i].slot;
+ input.fence = dequeueOutput[i].fence;
+ }
}
for (const auto& output : dequeueOutput) {
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 69e9f8a..a49a859 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -97,9 +97,10 @@
void releaseBufferCallbackLocked(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
std::optional<uint32_t> currentMaxAcquiredBufferCount,
bool fakeRelease) REQUIRES(mMutex);
- void syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback,
+ bool syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback,
bool acquireSingleBuffer = true);
void stopContinuousSyncTransaction();
+ void clearSyncTransaction();
void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber);
void applyPendingTransactions(uint64_t frameNumber);
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index cf2593d..a3ad680 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -32,6 +32,7 @@
#include <private/gui/ComposerService.h>
#include <private/gui/ComposerServiceAIDL.h>
#include <ui/DisplayMode.h>
+#include <ui/DisplayState.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicTypes.h>
#include <ui/Transform.h>
@@ -116,15 +117,17 @@
mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer);
}
- void syncNextTransaction(std::function<void(Transaction*)> callback,
+ bool syncNextTransaction(std::function<void(Transaction*)> callback,
bool acquireSingleBuffer = true) {
- mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer);
+ return mBlastBufferQueueAdapter->syncNextTransaction(callback, acquireSingleBuffer);
}
void stopContinuousSyncTransaction() {
mBlastBufferQueueAdapter->stopContinuousSyncTransaction();
}
+ void clearSyncTransaction() { mBlastBufferQueueAdapter->clearSyncTransaction(); }
+
int getWidth() { return mBlastBufferQueueAdapter->mSize.width; }
int getHeight() { return mBlastBufferQueueAdapter->mSize.height; }
@@ -176,13 +179,13 @@
BLASTBufferQueueTest() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name());
+ ALOGD("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name());
}
~BLASTBufferQueueTest() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("End test: %s.%s", testInfo->test_case_name(), testInfo->name());
+ ALOGD("End test: %s.%s", testInfo->test_case_name(), testInfo->name());
}
void SetUp() {
@@ -198,11 +201,13 @@
t.apply();
t.clear();
- ui::DisplayMode mode;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplayToken, &mode));
- const ui::Size& resolution = mode.resolution;
+ ui::DisplayState displayState;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(mDisplayToken, &displayState));
+ const ui::Size& resolution = displayState.layerStackSpaceRect;
mDisplayWidth = resolution.getWidth();
mDisplayHeight = resolution.getHeight();
+ ALOGD("Display: %dx%d orientation:%d", mDisplayWidth, mDisplayHeight,
+ displayState.orientation);
mSurfaceControl = mClient->createSurface(String8("TestSurface"), mDisplayWidth,
mDisplayHeight, PIXEL_FORMAT_RGBA_8888,
@@ -1108,7 +1113,11 @@
ASSERT_NE(nullptr, adapter.getTransactionReadyCallback());
auto callback2 = [](Transaction*) {};
- adapter.syncNextTransaction(callback2);
+ ASSERT_FALSE(adapter.syncNextTransaction(callback2));
+
+ sp<IGraphicBufferProducer> igbProducer;
+ setUpProducer(adapter, igbProducer);
+ queueBuffer(igbProducer, 0, 255, 0, 0);
std::unique_lock<std::mutex> lock(mutex);
if (!receivedCallback) {
@@ -1120,6 +1129,37 @@
ASSERT_TRUE(receivedCallback);
}
+TEST_F(BLASTBufferQueueTest, ClearSyncTransaction) {
+ std::mutex mutex;
+ std::condition_variable callbackReceivedCv;
+ bool receivedCallback = false;
+
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+ ASSERT_EQ(nullptr, adapter.getTransactionReadyCallback());
+ auto callback = [&](Transaction*) {
+ std::unique_lock<std::mutex> lock(mutex);
+ receivedCallback = true;
+ callbackReceivedCv.notify_one();
+ };
+ adapter.syncNextTransaction(callback);
+ ASSERT_NE(nullptr, adapter.getTransactionReadyCallback());
+
+ adapter.clearSyncTransaction();
+
+ sp<IGraphicBufferProducer> igbProducer;
+ setUpProducer(adapter, igbProducer);
+ queueBuffer(igbProducer, 0, 255, 0, 0);
+
+ std::unique_lock<std::mutex> lock(mutex);
+ if (!receivedCallback) {
+ ASSERT_EQ(callbackReceivedCv.wait_for(lock, std::chrono::seconds(3)),
+ std::cv_status::timeout)
+ << "did not receive callback";
+ }
+
+ ASSERT_FALSE(receivedCallback);
+}
+
TEST_F(BLASTBufferQueueTest, SyncNextTransactionDropBuffer) {
uint8_t r = 255;
uint8_t g = 0;
diff --git a/libs/gui/tests/BufferItemConsumer_test.cpp b/libs/gui/tests/BufferItemConsumer_test.cpp
index fc6551c..6880678 100644
--- a/libs/gui/tests/BufferItemConsumer_test.cpp
+++ b/libs/gui/tests/BufferItemConsumer_test.cpp
@@ -68,7 +68,7 @@
void HandleBufferFreed() {
std::lock_guard<std::mutex> lock(mMutex);
mFreedBufferCount++;
- ALOGV("HandleBufferFreed, mFreedBufferCount=%d", mFreedBufferCount);
+ ALOGD("HandleBufferFreed, mFreedBufferCount=%d", mFreedBufferCount);
}
void DequeueBuffer(int* outSlot) {
@@ -80,7 +80,7 @@
nullptr, nullptr);
ASSERT_GE(ret, 0);
- ALOGV("dequeueBuffer: slot=%d", slot);
+ ALOGD("dequeueBuffer: slot=%d", slot);
if (ret & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
ret = mProducer->requestBuffer(slot, &mBuffers[slot]);
ASSERT_EQ(NO_ERROR, ret);
@@ -89,7 +89,7 @@
}
void QueueBuffer(int slot) {
- ALOGV("enqueueBuffer: slot=%d", slot);
+ ALOGD("enqueueBuffer: slot=%d", slot);
IGraphicBufferProducer::QueueBufferInput bufferInput(
0ULL, true, HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
@@ -104,12 +104,12 @@
status_t ret = mBIC->acquireBuffer(&buffer, 0, false);
ASSERT_EQ(NO_ERROR, ret);
- ALOGV("acquireBuffer: slot=%d", buffer.mSlot);
+ ALOGD("acquireBuffer: slot=%d", buffer.mSlot);
*outSlot = buffer.mSlot;
}
void ReleaseBuffer(int slot) {
- ALOGV("releaseBuffer: slot=%d", slot);
+ ALOGD("releaseBuffer: slot=%d", slot);
BufferItem buffer;
buffer.mSlot = slot;
buffer.mGraphicBuffer = mBuffers[slot];
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index d1208ee..2f1fd3e 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -49,14 +49,14 @@
BufferQueueTest() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
+ ALOGD("Begin test: %s.%s", testInfo->test_case_name(),
testInfo->name());
}
~BufferQueueTest() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("End test: %s.%s", testInfo->test_case_name(),
+ ALOGD("End test: %s.%s", testInfo->test_case_name(),
testInfo->name());
}
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 00e32d9..0a14afa 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -62,7 +62,7 @@
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
CpuConsumerTestParams params = GetParam();
- ALOGV("** Starting test %s (%d x %d, %d, 0x%x)",
+ ALOGD("** Starting test %s (%d x %d, %d, 0x%x)",
test_info->name(),
params.width, params.height,
params.maxLockedBuffers, params.format);
@@ -582,7 +582,7 @@
uint32_t stride[numInQueue];
for (int i = 0; i < numInQueue; i++) {
- ALOGV("Producing frame %d", i);
+ ALOGD("Producing frame %d", i);
ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time[i],
&stride[i]));
}
@@ -590,7 +590,7 @@
// Consume
for (int i = 0; i < numInQueue; i++) {
- ALOGV("Consuming frame %d", i);
+ ALOGD("Consuming frame %d", i);
CpuConsumer::LockedBuffer b;
err = mCC->lockNextBuffer(&b);
ASSERT_NO_ERROR(err, "getNextBuffer error: ");
@@ -624,7 +624,7 @@
uint32_t stride;
for (int i = 0; i < params.maxLockedBuffers + 1; i++) {
- ALOGV("Producing frame %d", i);
+ ALOGD("Producing frame %d", i);
ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time,
&stride));
}
@@ -633,7 +633,7 @@
std::vector<CpuConsumer::LockedBuffer> b(params.maxLockedBuffers);
for (int i = 0; i < params.maxLockedBuffers; i++) {
- ALOGV("Locking frame %d", i);
+ ALOGD("Locking frame %d", i);
err = mCC->lockNextBuffer(&b[i]);
ASSERT_NO_ERROR(err, "getNextBuffer error: ");
@@ -647,16 +647,16 @@
checkAnyBuffer(b[i], GetParam().format);
}
- ALOGV("Locking frame %d (too many)", params.maxLockedBuffers);
+ ALOGD("Locking frame %d (too many)", params.maxLockedBuffers);
CpuConsumer::LockedBuffer bTooMuch;
err = mCC->lockNextBuffer(&bTooMuch);
ASSERT_TRUE(err == NOT_ENOUGH_DATA) << "Allowing too many locks";
- ALOGV("Unlocking frame 0");
+ ALOGD("Unlocking frame 0");
err = mCC->unlockBuffer(b[0]);
ASSERT_NO_ERROR(err, "Could not unlock buffer 0: ");
- ALOGV("Locking frame %d (should work now)", params.maxLockedBuffers);
+ ALOGD("Locking frame %d (should work now)", params.maxLockedBuffers);
err = mCC->lockNextBuffer(&bTooMuch);
ASSERT_NO_ERROR(err, "Did not allow new lock after unlock");
@@ -669,11 +669,11 @@
checkAnyBuffer(bTooMuch, GetParam().format);
- ALOGV("Unlocking extra buffer");
+ ALOGD("Unlocking extra buffer");
err = mCC->unlockBuffer(bTooMuch);
ASSERT_NO_ERROR(err, "Could not unlock extra buffer: ");
- ALOGV("Locking frame %d (no more available)", params.maxLockedBuffers + 1);
+ ALOGD("Locking frame %d (no more available)", params.maxLockedBuffers + 1);
err = mCC->lockNextBuffer(&b[0]);
ASSERT_EQ(BAD_VALUE, err) << "Not out of buffers somehow";
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 9e8c65c..4ec7a06 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -164,7 +164,7 @@
void assertFocusChange(bool hasFocus) {
InputEvent *ev = consumeEvent();
ASSERT_NE(ev, nullptr);
- ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, ev->getType());
+ ASSERT_EQ(InputEventType::FOCUS, ev->getType());
FocusEvent *focusEvent = static_cast<FocusEvent *>(ev);
EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
}
@@ -172,7 +172,7 @@
void expectTap(int x, int y) {
InputEvent* ev = consumeEvent();
ASSERT_NE(ev, nullptr);
- ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType());
+ ASSERT_EQ(InputEventType::MOTION, ev->getType());
MotionEvent* mev = static_cast<MotionEvent*>(ev);
EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
EXPECT_EQ(x, mev->getX(0));
@@ -181,7 +181,7 @@
ev = consumeEvent();
ASSERT_NE(ev, nullptr);
- ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType());
+ ASSERT_EQ(InputEventType::MOTION, ev->getType());
mev = static_cast<MotionEvent*>(ev);
EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS);
@@ -190,7 +190,7 @@
void expectTapWithFlag(int x, int y, int32_t flags) {
InputEvent *ev = consumeEvent();
ASSERT_NE(ev, nullptr);
- ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType());
+ ASSERT_EQ(InputEventType::MOTION, ev->getType());
MotionEvent *mev = static_cast<MotionEvent *>(ev);
EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
EXPECT_EQ(x, mev->getX(0));
@@ -199,7 +199,7 @@
ev = consumeEvent();
ASSERT_NE(ev, nullptr);
- ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType());
+ ASSERT_EQ(InputEventType::MOTION, ev->getType());
mev = static_cast<MotionEvent *>(ev);
EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
EXPECT_EQ(flags, mev->getFlags() & flags);
@@ -208,7 +208,7 @@
void expectTapInDisplayCoordinates(int displayX, int displayY) {
InputEvent *ev = consumeEvent();
ASSERT_NE(ev, nullptr);
- ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType());
+ ASSERT_EQ(InputEventType::MOTION, ev->getType());
MotionEvent *mev = static_cast<MotionEvent *>(ev);
EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
const PointerCoords &coords = *mev->getRawPointerCoords(0 /*pointerIndex*/);
@@ -218,7 +218,7 @@
ev = consumeEvent();
ASSERT_NE(ev, nullptr);
- ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType());
+ ASSERT_EQ(InputEventType::MOTION, ev->getType());
mev = static_cast<MotionEvent *>(ev);
EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS);
@@ -227,7 +227,7 @@
void expectKey(uint32_t keycode) {
InputEvent *ev = consumeEvent();
ASSERT_NE(ev, nullptr);
- ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, ev->getType());
+ ASSERT_EQ(InputEventType::KEY, ev->getType());
KeyEvent *keyEvent = static_cast<KeyEvent *>(ev);
EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, keyEvent->getAction());
EXPECT_EQ(keycode, keyEvent->getKeyCode());
@@ -235,7 +235,7 @@
ev = consumeEvent();
ASSERT_NE(ev, nullptr);
- ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, ev->getType());
+ ASSERT_EQ(InputEventType::KEY, ev->getType());
keyEvent = static_cast<KeyEvent *>(ev);
EXPECT_EQ(AMOTION_EVENT_ACTION_UP, keyEvent->getAction());
EXPECT_EQ(keycode, keyEvent->getKeyCode());
@@ -628,7 +628,7 @@
// Expect no crash for overflow.
injectTap(12, 24);
- fgSurface->expectTap(6, 12);
+ bgSurface->expectTap(12, 24);
}
// Ensure we ignore transparent region when getting screen bounds when positioning input frame.
@@ -1235,32 +1235,6 @@
surface->expectKey(AKEYCODE_V);
}
-/**
- * When multiple DisplayDevices are mapped to the same layerStack, use the configuration for the
- * display that can receive input.
- */
-TEST_F(MultiDisplayTests, many_to_one_display_mapping) {
- ui::LayerStack layerStack = ui::LayerStack::fromValue(42);
- createDisplay(1000, 1000, false /*isSecure*/, layerStack, false /*receivesInput*/,
- 100 /*offsetX*/, 100 /*offsetY*/);
- createDisplay(1000, 1000, false /*isSecure*/, layerStack, true /*receivesInput*/,
- 200 /*offsetX*/, 200 /*offsetY*/);
- createDisplay(1000, 1000, false /*isSecure*/, layerStack, false /*receivesInput*/,
- 300 /*offsetX*/, 300 /*offsetY*/);
- std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
- surface->doTransaction([&](auto &t, auto &sc) { t.setLayerStack(sc, layerStack); });
- surface->showAt(10, 10);
-
- // Input injection happens in logical display coordinates.
- injectTapOnDisplay(11, 11, layerStack.id);
- // Expect that the display transform for the display that receives input was used.
- surface->expectTapInDisplayCoordinates(211, 211);
-
- surface->requestFocus(layerStack.id);
- surface->assertFocusChange(true);
- injectKeyOnDisplay(AKEYCODE_V, layerStack.id);
-}
-
TEST_F(MultiDisplayTests, drop_input_for_secure_layer_on_nonsecure_display) {
ui::LayerStack layerStack = ui::LayerStack::fromValue(42);
createDisplay(1000, 1000, false /*isSecure*/, layerStack);
diff --git a/libs/gui/tests/GLTest.cpp b/libs/gui/tests/GLTest.cpp
index a1405fc..3ae4b6d 100644
--- a/libs/gui/tests/GLTest.cpp
+++ b/libs/gui/tests/GLTest.cpp
@@ -31,7 +31,7 @@
void GLTest::SetUp() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name());
+ ALOGD("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name());
mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
@@ -135,7 +135,7 @@
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("End test: %s.%s", testInfo->test_case_name(), testInfo->name());
+ ALOGD("End test: %s.%s", testInfo->test_case_name(), testInfo->name());
}
EGLint const* GLTest::getConfigAttribs() {
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index 3427731..e6cb89c 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -84,7 +84,7 @@
virtual void SetUp() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
+ ALOGD("Begin test: %s.%s", testInfo->test_case_name(),
testInfo->name());
mMC = new MockConsumer;
@@ -114,7 +114,7 @@
virtual void TearDown() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("End test: %s.%s", testInfo->test_case_name(),
+ ALOGD("End test: %s.%s", testInfo->test_case_name(),
testInfo->name());
}
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index b65cdda..2f14924 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -36,14 +36,14 @@
StreamSplitterTest() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
+ ALOGD("Begin test: %s.%s", testInfo->test_case_name(),
testInfo->name());
}
~StreamSplitterTest() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("End test: %s.%s", testInfo->test_case_name(),
+ ALOGD("End test: %s.%s", testInfo->test_case_name(),
testInfo->name());
}
};
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index c7458a3..82b6697 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -42,7 +42,7 @@
virtual void SetUp() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
+ ALOGD("Begin test: %s.%s", testInfo->test_case_name(),
testInfo->name());
sp<IGraphicBufferProducer> producer;
@@ -99,7 +99,7 @@
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
- ALOGV("End test: %s.%s", testInfo->test_case_name(),
+ ALOGD("End test: %s.%s", testInfo->test_case_name(),
testInfo->name());
}
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 4dbf575..00925ba 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -170,30 +170,6 @@
return atan2f(transformedPoint.x, -transformedPoint.y);
}
-const char* inputEventTypeToString(int32_t type) {
- switch (type) {
- case AINPUT_EVENT_TYPE_KEY: {
- return "KEY";
- }
- case AINPUT_EVENT_TYPE_MOTION: {
- return "MOTION";
- }
- case AINPUT_EVENT_TYPE_FOCUS: {
- return "FOCUS";
- }
- case AINPUT_EVENT_TYPE_CAPTURE: {
- return "CAPTURE";
- }
- case AINPUT_EVENT_TYPE_DRAG: {
- return "DRAG";
- }
- case AINPUT_EVENT_TYPE_TOUCH_MODE: {
- return "TOUCH_MODE";
- }
- }
- return "UNKNOWN";
-}
-
std::string inputEventSourceToString(int32_t source) {
if (source == AINPUT_SOURCE_UNKNOWN) {
return "UNKNOWN";
@@ -287,6 +263,37 @@
return idGen.nextId();
}
+std::ostream& operator<<(std::ostream& out, const InputEvent& event) {
+ switch (event.getType()) {
+ case InputEventType::KEY: {
+ const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event);
+ out << keyEvent;
+ return out;
+ }
+ case InputEventType::MOTION: {
+ const MotionEvent& motionEvent = static_cast<const MotionEvent&>(event);
+ out << motionEvent;
+ return out;
+ }
+ case InputEventType::FOCUS: {
+ out << "FocusEvent";
+ return out;
+ }
+ case InputEventType::CAPTURE: {
+ out << "CaptureEvent";
+ return out;
+ }
+ case InputEventType::DRAG: {
+ out << "DragEvent";
+ return out;
+ }
+ case InputEventType::TOUCH_MODE: {
+ out << "TouchModeEvent";
+ return out;
+ }
+ }
+}
+
// --- KeyEvent ---
const char* KeyEvent::getLabel(int32_t keyCode) {
@@ -1165,44 +1172,51 @@
void PooledInputEventFactory::recycle(InputEvent* event) {
switch (event->getType()) {
- case AINPUT_EVENT_TYPE_KEY:
- if (mKeyEventPool.size() < mMaxPoolSize) {
- mKeyEventPool.push(std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event)));
- return;
+ case InputEventType::KEY: {
+ if (mKeyEventPool.size() < mMaxPoolSize) {
+ mKeyEventPool.push(std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event)));
+ return;
+ }
+ break;
}
- break;
- case AINPUT_EVENT_TYPE_MOTION:
- if (mMotionEventPool.size() < mMaxPoolSize) {
- mMotionEventPool.push(std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event)));
- return;
+ case InputEventType::MOTION: {
+ if (mMotionEventPool.size() < mMaxPoolSize) {
+ mMotionEventPool.push(
+ std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event)));
+ return;
+ }
+ break;
}
- break;
- case AINPUT_EVENT_TYPE_FOCUS:
- if (mFocusEventPool.size() < mMaxPoolSize) {
- mFocusEventPool.push(std::unique_ptr<FocusEvent>(static_cast<FocusEvent*>(event)));
- return;
+ case InputEventType::FOCUS: {
+ if (mFocusEventPool.size() < mMaxPoolSize) {
+ mFocusEventPool.push(std::unique_ptr<FocusEvent>(static_cast<FocusEvent*>(event)));
+ return;
+ }
+ break;
}
- break;
- case AINPUT_EVENT_TYPE_CAPTURE:
- if (mCaptureEventPool.size() < mMaxPoolSize) {
- mCaptureEventPool.push(
- std::unique_ptr<CaptureEvent>(static_cast<CaptureEvent*>(event)));
- return;
+ case InputEventType::CAPTURE: {
+ if (mCaptureEventPool.size() < mMaxPoolSize) {
+ mCaptureEventPool.push(
+ std::unique_ptr<CaptureEvent>(static_cast<CaptureEvent*>(event)));
+ return;
+ }
+ break;
}
- break;
- case AINPUT_EVENT_TYPE_DRAG:
- if (mDragEventPool.size() < mMaxPoolSize) {
- mDragEventPool.push(std::unique_ptr<DragEvent>(static_cast<DragEvent*>(event)));
- return;
+ case InputEventType::DRAG: {
+ if (mDragEventPool.size() < mMaxPoolSize) {
+ mDragEventPool.push(std::unique_ptr<DragEvent>(static_cast<DragEvent*>(event)));
+ return;
+ }
+ break;
}
- break;
- case AINPUT_EVENT_TYPE_TOUCH_MODE:
- if (mTouchModeEventPool.size() < mMaxPoolSize) {
- mTouchModeEventPool.push(
- std::unique_ptr<TouchModeEvent>(static_cast<TouchModeEvent*>(event)));
- return;
+ case InputEventType::TOUCH_MODE: {
+ if (mTouchModeEventPool.size() < mMaxPoolSize) {
+ mTouchModeEventPool.push(
+ std::unique_ptr<TouchModeEvent>(static_cast<TouchModeEvent*>(event)));
+ return;
+ }
+ break;
}
- break;
}
delete event;
}
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index 737bd15..136a560 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -272,8 +272,8 @@
char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const {
char16_t result = 0;
- const Key* key;
- if (getKey(keyCode, &key)) {
+ const Key* key = getKey(keyCode);
+ if (key != nullptr) {
result = key->label;
}
#if DEBUG_MAPPING
@@ -284,8 +284,8 @@
char16_t KeyCharacterMap::getNumber(int32_t keyCode) const {
char16_t result = 0;
- const Key* key;
- if (getKey(keyCode, &key)) {
+ const Key* key = getKey(keyCode);
+ if (key != nullptr) {
result = key->number;
}
#if DEBUG_MAPPING
@@ -332,8 +332,8 @@
char16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars,
int32_t metaState) const {
char16_t result = 0;
- const Key* key;
- if (getKey(keyCode, &key)) {
+ const Key* key = getKey(keyCode);
+ if (key != nullptr) {
// Try to find the most general behavior that maps to this character.
// For example, the base key behavior will usually be last in the list.
// However, if we find a perfect meta state match for one behavior then use that one.
@@ -493,19 +493,18 @@
return std::make_pair(toKeyCode, toMetaState);
}
-bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const {
+const KeyCharacterMap::Key* KeyCharacterMap::getKey(int32_t keyCode) const {
ssize_t index = mKeys.indexOfKey(keyCode);
if (index >= 0) {
- *outKey = mKeys.valueAt(index);
- return true;
+ return mKeys.valueAt(index);
}
- return false;
+ return nullptr;
}
const KeyCharacterMap::Behavior* KeyCharacterMap::getKeyBehavior(int32_t keyCode,
int32_t metaState) const {
- const Key* key;
- if (getKey(keyCode, &key)) {
+ const Key* key = getKey(keyCode);
+ if (key != nullptr) {
for (const Behavior& behavior : key->behaviors) {
if (matchesMetaState(metaState, behavior.metaState)) {
return &behavior;
@@ -1048,7 +1047,7 @@
String8 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
if (token == "}") {
mState = STATE_TOP;
- return finishKey(key);
+ return finishKey(*key);
}
Vector<Property> properties;
@@ -1230,12 +1229,12 @@
return NO_ERROR;
}
-status_t KeyCharacterMap::Parser::finishKey(Key* key) {
+status_t KeyCharacterMap::Parser::finishKey(Key& key) {
// Fill in default number property.
- if (!key->number) {
+ if (!key.number) {
char16_t digit = 0;
char16_t symbol = 0;
- for (const Behavior& b : key->behaviors) {
+ for (const Behavior& b : key.behaviors) {
char16_t ch = b.character;
if (ch) {
if (ch >= '0' && ch <= '9') {
@@ -1247,7 +1246,7 @@
}
}
}
- key->number = digit ? digit : symbol;
+ key.number = digit ? digit : symbol;
}
return NO_ERROR;
}
diff --git a/libs/input/android/os/InputEventInjectionSync.aidl b/libs/input/android/os/InputEventInjectionSync.aidl
index 95d24cb..2d225fa 100644
--- a/libs/input/android/os/InputEventInjectionSync.aidl
+++ b/libs/input/android/os/InputEventInjectionSync.aidl
@@ -33,4 +33,7 @@
/* Waits for the input event to be completely processed. */
WAIT_FOR_FINISHED = 2,
+
+ ftl_first = NONE,
+ ftl_last = WAIT_FOR_FINISHED,
}
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 59125dd..a965573 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -197,7 +197,7 @@
ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME);
ASSERT_EQ(id, event.getId());
- ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType());
+ ASSERT_EQ(InputEventType::KEY, event.getType());
ASSERT_EQ(2, event.getDeviceId());
ASSERT_EQ(AINPUT_SOURCE_GAMEPAD, event.getSource());
ASSERT_EQ(DISPLAY_ID, event.getDisplayId());
@@ -346,7 +346,7 @@
void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
// Check properties.
ASSERT_EQ(mId, event->getId());
- ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
+ ASSERT_EQ(InputEventType::MOTION, event->getType());
ASSERT_EQ(2, event->getDeviceId());
ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event->getSource());
ASSERT_EQ(DISPLAY_ID, event->getDisplayId());
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 965fda7..3ecf8ee 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -98,8 +98,7 @@
ASSERT_TRUE(event != nullptr)
<< "consumer should have returned non-NULL event";
- ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event->getType())
- << "consumer should have returned a key event";
+ ASSERT_EQ(InputEventType::KEY, event->getType()) << "consumer should have returned a key event";
KeyEvent* keyEvent = static_cast<KeyEvent*>(event);
EXPECT_EQ(seq, consumeSeq);
@@ -207,7 +206,7 @@
ASSERT_TRUE(event != nullptr)
<< "consumer should have returned non-NULL event";
- ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
+ ASSERT_EQ(InputEventType::MOTION, event->getType())
<< "consumer should have returned a motion event";
MotionEvent* motionEvent = static_cast<MotionEvent*>(event);
@@ -298,7 +297,7 @@
ASSERT_EQ(OK, status) << "consumer consume should return OK";
ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event";
- ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
+ ASSERT_EQ(InputEventType::FOCUS, event->getType())
<< "consumer should have returned a focus event";
FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
@@ -339,7 +338,7 @@
ASSERT_EQ(OK, status) << "consumer consume should return OK";
ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event";
- ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
+ ASSERT_EQ(InputEventType::CAPTURE, event->getType())
<< "consumer should have returned a capture event";
const CaptureEvent* captureEvent = static_cast<CaptureEvent*>(event);
@@ -381,7 +380,7 @@
ASSERT_EQ(OK, status) << "consumer consume should return OK";
ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event";
- ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
+ ASSERT_EQ(InputEventType::DRAG, event->getType())
<< "consumer should have returned a drag event";
const DragEvent& dragEvent = static_cast<const DragEvent&>(*event);
@@ -423,7 +422,7 @@
ASSERT_EQ(OK, status) << "consumer consume should return OK";
ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event";
- ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType())
+ ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
<< "consumer should have returned a touch mode event";
const TouchModeEvent& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
diff --git a/libs/input/tests/RingBuffer_test.cpp b/libs/input/tests/RingBuffer_test.cpp
index 8a6ef4c..a2ef658 100644
--- a/libs/input/tests/RingBuffer_test.cpp
+++ b/libs/input/tests/RingBuffer_test.cpp
@@ -118,6 +118,21 @@
EXPECT_EQ(0u, d.capacity());
}
+TEST(RingBufferTest, FrontBackAccess) {
+ RingBuffer<int> buffer(/*capacity=*/2);
+ buffer.pushBack(1);
+ EXPECT_EQ(1, buffer.front());
+ EXPECT_EQ(1, buffer.back());
+
+ buffer.pushFront(0);
+ EXPECT_EQ(0, buffer.front());
+ EXPECT_EQ(1, buffer.back());
+
+ buffer.pushFront(-1);
+ EXPECT_EQ(-1, buffer.front());
+ EXPECT_EQ(0, buffer.back());
+}
+
TEST(RingBufferTest, Subscripting) {
RingBuffer<int> buffer(/*capacity=*/2);
buffer.pushBack(1);
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegr.h b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegr.h
deleted file mode 100644
index 1ab1dd7..0000000
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegr.h
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright 2022 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.
- */
-
-#ifndef ANDROID_JPEGRECOVERYMAP_JPEGR_H
-#define ANDROID_JPEGRECOVERYMAP_JPEGR_H
-
-#include "jpegrerrorcode.h"
-
-namespace android::jpegrecoverymap {
-
-// Color gamuts for image data
-typedef enum {
- JPEGR_COLORGAMUT_UNSPECIFIED,
- JPEGR_COLORGAMUT_BT709,
- JPEGR_COLORGAMUT_P3,
- JPEGR_COLORGAMUT_BT2100,
-} jpegr_color_gamut;
-
-// Transfer functions for image data
-typedef enum {
- JPEGR_TF_UNSPECIFIED = -1,
- JPEGR_TF_LINEAR = 0,
- JPEGR_TF_HLG = 1,
- JPEGR_TF_PQ = 2,
- JPEGR_TF_SRGB = 3,
-} jpegr_transfer_function;
-
-// Target output formats for decoder
-typedef enum {
- JPEGR_OUTPUT_SDR, // SDR in RGBA_8888 color format
- JPEGR_OUTPUT_HDR_LINEAR, // HDR in F16 color format (linear)
- JPEGR_OUTPUT_HDR_PQ, // HDR in RGBA_1010102 color format (PQ transfer function)
- JPEGR_OUTPUT_HDR_HLG, // HDR in RGBA_1010102 color format (HLG transfer function)
-} jpegr_output_format;
-
-struct jpegr_info_struct {
- size_t width;
- size_t height;
- std::vector<uint8_t>* iccData;
- std::vector<uint8_t>* exifData;
-};
-
-/*
- * Holds information for uncompressed image or recovery map.
- */
-struct jpegr_uncompressed_struct {
- // Pointer to the data location.
- void* data;
- // Width of the recovery map or image in pixels.
- int width;
- // Height of the recovery map or image in pixels.
- int height;
- // Color gamut.
- jpegr_color_gamut colorGamut;
-};
-
-/*
- * Holds information for compressed image or recovery map.
- */
-struct jpegr_compressed_struct {
- // Pointer to the data location.
- void* data;
- // Used data length in bytes.
- int length;
- // Maximum available data length in bytes.
- int maxLength;
- // Color gamut.
- jpegr_color_gamut colorGamut;
-};
-
-/*
- * Holds information for EXIF metadata.
- */
-struct jpegr_exif_struct {
- // Pointer to the data location.
- void* data;
- // Data length;
- int length;
-};
-
-/*
- * Holds information for recovery map related metadata.
- */
-struct jpegr_metadata_struct {
- // JPEG/R version
- uint32_t version;
- // Max Content Boost for the map
- float maxContentBoost;
- // Min Content Boost for the map
- float minContentBoost;
-};
-
-typedef struct jpegr_uncompressed_struct* jr_uncompressed_ptr;
-typedef struct jpegr_compressed_struct* jr_compressed_ptr;
-typedef struct jpegr_exif_struct* jr_exif_ptr;
-typedef struct jpegr_metadata_struct* jr_metadata_ptr;
-typedef struct jpegr_info_struct* jr_info_ptr;
-
-class JpegR {
-public:
- /*
- * Experimental only
- *
- * Encode API-0
- * Compress JPEGR image from 10-bit HDR YUV.
- *
- * Tonemap the HDR input to a SDR image, generate recovery map from the HDR and SDR images,
- * compress SDR YUV to 8-bit JPEG and append the recovery map to the end of the compressed
- * JPEG.
- * @param uncompressed_p010_image uncompressed HDR image in P010 color format
- * @param hdr_tf transfer function of the HDR image
- * @param dest destination of the compressed JPEGR image
- * @param quality target quality of the JPEG encoding, must be in range of 0-100 where 100 is
- * the highest quality
- * @param exif pointer to the exif metadata.
- * @return NO_ERROR if encoding succeeds, error code if error occurs.
- */
- status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
- jpegr_transfer_function hdr_tf,
- jr_compressed_ptr dest,
- int quality,
- jr_exif_ptr exif);
-
- /*
- * Encode API-1
- * Compress JPEGR image from 10-bit HDR YUV and 8-bit SDR YUV.
- *
- * Generate recovery map from the HDR and SDR inputs, compress SDR YUV to 8-bit JPEG and append
- * the recovery map to the end of the compressed JPEG. HDR and SDR inputs must be the same
- * resolution.
- * @param uncompressed_p010_image uncompressed HDR image in P010 color format
- * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
- * @param hdr_tf transfer function of the HDR image
- * @param dest destination of the compressed JPEGR image
- * @param quality target quality of the JPEG encoding, must be in range of 0-100 where 100 is
- * the highest quality
- * @param exif pointer to the exif metadata.
- * @return NO_ERROR if encoding succeeds, error code if error occurs.
- */
- status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
- jr_uncompressed_ptr uncompressed_yuv_420_image,
- jpegr_transfer_function hdr_tf,
- jr_compressed_ptr dest,
- int quality,
- jr_exif_ptr exif);
-
- /*
- * Encode API-2
- * Compress JPEGR image from 10-bit HDR YUV, 8-bit SDR YUV and compressed 8-bit JPEG.
- *
- * This method requires HAL Hardware JPEG encoder.
- *
- * Generate recovery map from the HDR and SDR inputs, append the recovery map to the end of the
- * compressed JPEG. HDR and SDR inputs must be the same resolution and color space.
- * @param uncompressed_p010_image uncompressed HDR image in P010 color format
- * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
- * Note: the SDR image must be the decoded version of the JPEG
- * input
- * @param compressed_jpeg_image compressed 8-bit JPEG image
- * @param hdr_tf transfer function of the HDR image
- * @param dest destination of the compressed JPEGR image
- * @return NO_ERROR if encoding succeeds, error code if error occurs.
- */
- status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
- jr_uncompressed_ptr uncompressed_yuv_420_image,
- jr_compressed_ptr compressed_jpeg_image,
- jpegr_transfer_function hdr_tf,
- jr_compressed_ptr dest);
-
- /*
- * Encode API-3
- * Compress JPEGR image from 10-bit HDR YUV and 8-bit SDR YUV.
- *
- * This method requires HAL Hardware JPEG encoder.
- *
- * Decode the compressed 8-bit JPEG image to YUV SDR, generate recovery map from the HDR input
- * and the decoded SDR result, append the recovery map to the end of the compressed JPEG. HDR
- * and SDR inputs must be the same resolution.
- * @param uncompressed_p010_image uncompressed HDR image in P010 color format
- * @param compressed_jpeg_image compressed 8-bit JPEG image
- * @param hdr_tf transfer function of the HDR image
- * @param dest destination of the compressed JPEGR image
- * @return NO_ERROR if encoding succeeds, error code if error occurs.
- */
- status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
- jr_compressed_ptr compressed_jpeg_image,
- jpegr_transfer_function hdr_tf,
- jr_compressed_ptr dest);
-
- /*
- * Decode API
- * Decompress JPEGR image.
- *
- * @param compressed_jpegr_image compressed JPEGR image.
- * @param dest destination of the uncompressed JPEGR image.
- * @param max_display_boost (optional) the maximum available boost supported by a display
- * @param exif destination of the decoded EXIF metadata. The default value is NULL where the
- decoder will do nothing about it. If configured not NULL the decoder will write
- EXIF data into this structure. The format is defined in {@code jpegr_exif_struct}
- * @param output_format flag for setting output color format. Its value configures the output
- color format. The default value is {@code JPEGR_OUTPUT_HDR_LINEAR}.
- ----------------------------------------------------------------------
- | output_format | decoded color format to be written |
- ----------------------------------------------------------------------
- | JPEGR_OUTPUT_SDR | RGBA_8888 |
- ----------------------------------------------------------------------
- | JPEGR_OUTPUT_HDR_LINEAR | (default)RGBA_F16 linear |
- ----------------------------------------------------------------------
- | JPEGR_OUTPUT_HDR_PQ | RGBA_1010102 PQ |
- ----------------------------------------------------------------------
- | JPEGR_OUTPUT_HDR_HLG | RGBA_1010102 HLG |
- ----------------------------------------------------------------------
- * @param recovery_map destination of the decoded recovery map. The default value is NULL where
- the decoder will do nothing about it. If configured not NULL the decoder
- will write the decoded recovery_map data into this structure. The format
- is defined in {@code jpegr_uncompressed_struct}.
- * @param metadata destination of the decoded metadata. The default value is NULL where the
- decoder will do nothing about it. If configured not NULL the decoder will
- write metadata into this structure. the format of metadata is defined in
- {@code jpegr_metadata}.
- * @return NO_ERROR if decoding succeeds, error code if error occurs.
- */
- status_t decodeJPEGR(jr_compressed_ptr compressed_jpegr_image,
- jr_uncompressed_ptr dest,
- float max_display_boost = -1.0f,
- jr_exif_ptr exif = nullptr,
- jpegr_output_format output_format = JPEGR_OUTPUT_HDR_LINEAR,
- jr_uncompressed_ptr recovery_map = nullptr,
- jr_metadata_ptr metadata = nullptr);
-
- /*
- * Gets Info from JPEGR file without decoding it.
- *
- * The output is filled jpegr_info structure
- * @param compressed_jpegr_image compressed JPEGR image
- * @param jpegr_info pointer to output JPEGR info. Members of jpegr_info
- * are owned by the caller
- * @return NO_ERROR if JPEGR parsing succeeds, error code otherwise
- */
- status_t getJPEGRInfo(jr_compressed_ptr compressed_jpegr_image,
- jr_info_ptr jpegr_info);
-protected:
- /*
- * This method is called in the encoding pipeline. It will take the uncompressed 8-bit and
- * 10-bit yuv images as input, and calculate the uncompressed recovery map. The input images
- * must be the same resolution.
- *
- * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
- * @param uncompressed_p010_image uncompressed HDR image in P010 color format
- * @param hdr_tf transfer function of the HDR image
- * @param dest recovery map; caller responsible for memory of data
- * @param metadata max_content_boost is filled in
- * @return NO_ERROR if calculation succeeds, error code if error occurs.
- */
- status_t generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
- jr_uncompressed_ptr uncompressed_p010_image,
- jpegr_transfer_function hdr_tf,
- jr_metadata_ptr metadata,
- jr_uncompressed_ptr dest);
-
- /*
- * This method is called in the decoding pipeline. It will take the uncompressed (decoded)
- * 8-bit yuv image, the uncompressed (decoded) recovery map, and extracted JPEG/R metadata as
- * input, and calculate the 10-bit recovered image. The recovered output image is the same
- * color gamut as the SDR image, with HLG transfer function, and is in RGBA1010102 data format.
- *
- * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
- * @param uncompressed_recovery_map uncompressed recovery map
- * @param metadata JPEG/R metadata extracted from XMP.
- * @param output_format flag for setting output color format. if set to
- * {@code JPEGR_OUTPUT_SDR}, decoder will only decode the primary image
- * which is SDR. Default value is JPEGR_OUTPUT_HDR_LINEAR.
- * @param max_display_boost the maximum available boost supported by a display
- * @param dest reconstructed HDR image
- * @return NO_ERROR if calculation succeeds, error code if error occurs.
- */
- status_t applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
- jr_uncompressed_ptr uncompressed_recovery_map,
- jr_metadata_ptr metadata,
- jpegr_output_format output_format,
- float max_display_boost,
- jr_uncompressed_ptr dest);
-
-private:
- /*
- * This method is called in the encoding pipeline. It will encode the recovery map.
- *
- * @param uncompressed_recovery_map uncompressed recovery map
- * @param dest encoded recover map
- * @return NO_ERROR if encoding succeeds, error code if error occurs.
- */
- status_t compressRecoveryMap(jr_uncompressed_ptr uncompressed_recovery_map,
- jr_compressed_ptr dest);
-
- /*
- * This methoud is called to separate primary image and recovery map image from JPEGR
- *
- * @param compressed_jpegr_image compressed JPEGR image
- * @param primary_image destination of primary image
- * @param recovery_map destination of compressed recovery map
- * @return NO_ERROR if calculation succeeds, error code if error occurs.
- */
- status_t extractPrimaryImageAndRecoveryMap(jr_compressed_ptr compressed_jpegr_image,
- jr_compressed_ptr primary_image,
- jr_compressed_ptr recovery_map);
- /*
- * This method is called in the decoding pipeline. It will read XMP metadata to find the start
- * position of the compressed recovery map, and will extract the compressed recovery map.
- *
- * @param compressed_jpegr_image compressed JPEGR image
- * @param dest destination of compressed recovery map
- * @return NO_ERROR if calculation succeeds, error code if error occurs.
- */
- status_t extractRecoveryMap(jr_compressed_ptr compressed_jpegr_image,
- jr_compressed_ptr dest);
-
- /*
- * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image,
- * the compressed recovery map and optionally the exif package as inputs, and generate the XMP
- * metadata, and finally append everything in the order of:
- * SOI, APP2(EXIF) (if EXIF is from outside), APP2(XMP), primary image, recovery map
- * Note that EXIF package is only available for encoding API-0 and API-1. For encoding API-2 and
- * API-3 this parameter is null, but the primary image in JPEG/R may still have EXIF as long as
- * the input JPEG has EXIF.
- *
- * @param compressed_jpeg_image compressed 8-bit JPEG image
- * @param compress_recovery_map compressed recover map
- * @param (nullable) exif EXIF package
- * @param metadata JPEG/R metadata to encode in XMP of the jpeg
- * @param dest compressed JPEGR image
- * @return NO_ERROR if calculation succeeds, error code if error occurs.
- */
- status_t appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image,
- jr_compressed_ptr compressed_recovery_map,
- jr_exif_ptr exif,
- jr_metadata_ptr metadata,
- jr_compressed_ptr dest);
-
- /*
- * This method will tone map a HDR image to an SDR image.
- *
- * @param src (input) uncompressed P010 image
- * @param dest (output) tone mapping result as a YUV_420 image
- * @return NO_ERROR if calculation succeeds, error code if error occurs.
- */
- status_t toneMap(jr_uncompressed_ptr src,
- jr_uncompressed_ptr dest);
-};
-
-} // namespace android::jpegrecoverymap
-
-#endif // ANDROID_JPEGRECOVERYMAP_JPEGR_H
diff --git a/libs/jpegrecoverymap/tests/jpegencoderhelper_test.cpp b/libs/jpegrecoverymap/tests/jpegencoderhelper_test.cpp
deleted file mode 100644
index 095ac2f..0000000
--- a/libs/jpegrecoverymap/tests/jpegencoderhelper_test.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2022 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 <jpegrecoverymap/jpegencoderhelper.h>
-#include <gtest/gtest.h>
-#include <utils/Log.h>
-
-#include <fcntl.h>
-
-namespace android::jpegrecoverymap {
-
-#define VALID_IMAGE "/sdcard/Documents/minnie-320x240.yu12"
-#define VALID_IMAGE_WIDTH 320
-#define VALID_IMAGE_HEIGHT 240
-#define SINGLE_CHANNEL_IMAGE "/sdcard/Documents/minnie-320x240.y"
-#define SINGLE_CHANNEL_IMAGE_WIDTH VALID_IMAGE_WIDTH
-#define SINGLE_CHANNEL_IMAGE_HEIGHT VALID_IMAGE_HEIGHT
-#define INVALID_SIZE_IMAGE "/sdcard/Documents/minnie-318x240.yu12"
-#define INVALID_SIZE_IMAGE_WIDTH 318
-#define INVALID_SIZE_IMAGE_HEIGHT 240
-#define JPEG_QUALITY 90
-
-class JpegEncoderHelperTest : public testing::Test {
-public:
- struct Image {
- std::unique_ptr<uint8_t[]> buffer;
- size_t width;
- size_t height;
- };
- JpegEncoderHelperTest();
- ~JpegEncoderHelperTest();
-protected:
- virtual void SetUp();
- virtual void TearDown();
-
- Image mValidImage, mInvalidSizeImage, mSingleChannelImage;
-};
-
-JpegEncoderHelperTest::JpegEncoderHelperTest() {}
-
-JpegEncoderHelperTest::~JpegEncoderHelperTest() {}
-
-static size_t getFileSize(int fd) {
- struct stat st;
- if (fstat(fd, &st) < 0) {
- ALOGW("%s : fstat failed", __func__);
- return 0;
- }
- return st.st_size; // bytes
-}
-
-static bool loadFile(const char filename[], JpegEncoderHelperTest::Image* result) {
- int fd = open(filename, O_CLOEXEC);
- if (fd < 0) {
- return false;
- }
- int length = getFileSize(fd);
- if (length == 0) {
- close(fd);
- return false;
- }
- result->buffer.reset(new uint8_t[length]);
- if (read(fd, result->buffer.get(), length) != static_cast<ssize_t>(length)) {
- close(fd);
- return false;
- }
- close(fd);
- return true;
-}
-
-void JpegEncoderHelperTest::SetUp() {
- if (!loadFile(VALID_IMAGE, &mValidImage)) {
- FAIL() << "Load file " << VALID_IMAGE << " failed";
- }
- mValidImage.width = VALID_IMAGE_WIDTH;
- mValidImage.height = VALID_IMAGE_HEIGHT;
- if (!loadFile(INVALID_SIZE_IMAGE, &mInvalidSizeImage)) {
- FAIL() << "Load file " << INVALID_SIZE_IMAGE << " failed";
- }
- mInvalidSizeImage.width = INVALID_SIZE_IMAGE_WIDTH;
- mInvalidSizeImage.height = INVALID_SIZE_IMAGE_HEIGHT;
- if (!loadFile(SINGLE_CHANNEL_IMAGE, &mSingleChannelImage)) {
- FAIL() << "Load file " << SINGLE_CHANNEL_IMAGE << " failed";
- }
- mSingleChannelImage.width = SINGLE_CHANNEL_IMAGE_WIDTH;
- mSingleChannelImage.height = SINGLE_CHANNEL_IMAGE_HEIGHT;
-}
-
-void JpegEncoderHelperTest::TearDown() {}
-
-TEST_F(JpegEncoderHelperTest, validImage) {
- JpegEncoderHelper encoder;
- EXPECT_TRUE(encoder.compressImage(mValidImage.buffer.get(), mValidImage.width,
- mValidImage.height, JPEG_QUALITY, NULL, 0));
- ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
-}
-
-TEST_F(JpegEncoderHelperTest, invalidSizeImage) {
- JpegEncoderHelper encoder;
- EXPECT_FALSE(encoder.compressImage(mInvalidSizeImage.buffer.get(), mInvalidSizeImage.width,
- mInvalidSizeImage.height, JPEG_QUALITY, NULL, 0));
-}
-
-TEST_F(JpegEncoderHelperTest, singleChannelImage) {
- JpegEncoderHelper encoder;
- EXPECT_TRUE(encoder.compressImage(mSingleChannelImage.buffer.get(), mSingleChannelImage.width,
- mSingleChannelImage.height, JPEG_QUALITY, NULL, 0, true));
- ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
-}
-
-} // namespace android::jpegrecoverymap
-
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index 936e316..b99e385 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -52,6 +52,20 @@
PFN_vkDestroyInstance vkDestroyInstance = nullptr;
};
+// Ref-Count a semaphore
+struct DestroySemaphoreInfo {
+ VkSemaphore mSemaphore;
+ // We need to make sure we don't delete the VkSemaphore until it is done being used by both Skia
+ // (including by the GPU) and inside SkiaVkRenderEngine. So we always start with two refs, one
+ // owned by Skia and one owned by the SkiaVkRenderEngine. The refs are decremented each time
+ // delete_semaphore* is called with this object. Skia will call destroy_semaphore* once it is
+ // done with the semaphore and the GPU has finished work on the semaphore. SkiaVkRenderEngine
+ // calls delete_semaphore* after sending the semaphore to Skia and exporting it if need be.
+ int mRefs = 2;
+
+ DestroySemaphoreInfo(VkSemaphore semaphore) : mSemaphore(semaphore) {}
+};
+
struct VulkanInterface {
bool initialized = false;
VkInstance instance;
@@ -588,14 +602,22 @@
return true;
}
-static void delete_semaphore(void* _semaphore) {
- VkSemaphore semaphore = (VkSemaphore)_semaphore;
- sVulkanInterface.destroySemaphore(semaphore);
+static void delete_semaphore(void* semaphore) {
+ DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
+ --info->mRefs;
+ if (!info->mRefs) {
+ sVulkanInterface.destroySemaphore(info->mSemaphore);
+ delete info;
+ }
}
-static void delete_semaphore_protected(void* _semaphore) {
- VkSemaphore semaphore = (VkSemaphore)_semaphore;
- sProtectedContentVulkanInterface.destroySemaphore(semaphore);
+static void delete_semaphore_protected(void* semaphore) {
+ DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
+ --info->mRefs;
+ if (!info->mRefs) {
+ sProtectedContentVulkanInterface.destroySemaphore(info->mSemaphore);
+ delete info;
+ }
}
static VulkanInterface& getVulkanInterface(bool protectedContext) {
@@ -624,19 +646,30 @@
}
base::unique_fd SkiaVkRenderEngine::flushAndSubmit(GrDirectContext* grContext) {
- VkSemaphore signalSemaphore = getVulkanInterface(isProtected()).createExportableSemaphore();
- GrBackendSemaphore beSignalSemaphore;
- beSignalSemaphore.initVulkan(signalSemaphore);
+ VulkanInterface& vi = getVulkanInterface(isProtected());
+ VkSemaphore semaphore = vi.createExportableSemaphore();
+
+ GrBackendSemaphore backendSemaphore;
+ backendSemaphore.initVulkan(semaphore);
+
GrFlushInfo flushInfo;
- flushInfo.fNumSemaphores = 1;
- flushInfo.fSignalSemaphores = &beSignalSemaphore;
- flushInfo.fFinishedProc = isProtected() ? delete_semaphore_protected : delete_semaphore;
- flushInfo.fFinishedContext = (void*)signalSemaphore;
+ DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
+ if (semaphore != VK_NULL_HANDLE) {
+ destroySemaphoreInfo = new DestroySemaphoreInfo(semaphore);
+ flushInfo.fNumSemaphores = 1;
+ flushInfo.fSignalSemaphores = &backendSemaphore;
+ flushInfo.fFinishedProc = isProtected() ? delete_semaphore_protected : delete_semaphore;
+ flushInfo.fFinishedContext = destroySemaphoreInfo;
+ }
GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
grContext->submit(false /* no cpu sync */);
int drawFenceFd = -1;
- if (GrSemaphoresSubmitted::kYes == submitted) {
- drawFenceFd = getVulkanInterface(isProtected()).exportSemaphoreSyncFd(signalSemaphore);
+ if (semaphore != VK_NULL_HANDLE) {
+ if (GrSemaphoresSubmitted::kYes == submitted) {
+ drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
+ }
+ // Now that drawFenceFd has been created, we can delete our reference to this semaphore
+ flushInfo.fFinishedProc(destroySemaphoreInfo);
}
base::unique_fd res(drawFenceFd);
return res;
diff --git a/libs/jpegrecoverymap/Android.bp b/libs/ultrahdr/Android.bp
similarity index 96%
rename from libs/jpegrecoverymap/Android.bp
rename to libs/ultrahdr/Android.bp
index a1b0e19..e3f709b 100644
--- a/libs/jpegrecoverymap/Android.bp
+++ b/libs/ultrahdr/Android.bp
@@ -22,7 +22,7 @@
}
cc_library {
- name: "libjpegrecoverymap",
+ name: "libultrahdr",
host_supported: true,
vendor_available: true,
export_include_dirs: ["include"],
@@ -31,7 +31,7 @@
srcs: [
"icc.cpp",
"jpegr.cpp",
- "recoverymapmath.cpp",
+ "gainmapmath.cpp",
"jpegrutils.cpp",
"multipictureformat.cpp",
],
diff --git a/libs/jpegrecoverymap/OWNERS b/libs/ultrahdr/OWNERS
similarity index 100%
rename from libs/jpegrecoverymap/OWNERS
rename to libs/ultrahdr/OWNERS
diff --git a/libs/jpegrecoverymap/recoverymapmath.cpp b/libs/ultrahdr/gainmapmath.cpp
similarity index 87%
rename from libs/jpegrecoverymap/recoverymapmath.cpp
rename to libs/ultrahdr/gainmapmath.cpp
index 2cffde3..37c3cf3 100644
--- a/libs/jpegrecoverymap/recoverymapmath.cpp
+++ b/libs/ultrahdr/gainmapmath.cpp
@@ -16,9 +16,9 @@
#include <cmath>
#include <vector>
-#include <jpegrecoverymap/recoverymapmath.h>
+#include <ultrahdr/gainmapmath.h>
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
static const std::vector<float> kPqOETF = [] {
std::vector<float> result;
@@ -396,53 +396,60 @@
// TODO: confirm we always want to convert like this before calculating
// luminance.
-ColorTransformFn getHdrConversionFn(jpegr_color_gamut sdr_gamut, jpegr_color_gamut hdr_gamut) {
+ColorTransformFn getHdrConversionFn(ultrahdr_color_gamut sdr_gamut,
+ ultrahdr_color_gamut hdr_gamut) {
switch (sdr_gamut) {
- case JPEGR_COLORGAMUT_BT709:
+ case ULTRAHDR_COLORGAMUT_BT709:
switch (hdr_gamut) {
- case JPEGR_COLORGAMUT_BT709:
+ case ULTRAHDR_COLORGAMUT_BT709:
return identityConversion;
- case JPEGR_COLORGAMUT_P3:
+ case ULTRAHDR_COLORGAMUT_P3:
return p3ToBt709;
- case JPEGR_COLORGAMUT_BT2100:
+ case ULTRAHDR_COLORGAMUT_BT2100:
return bt2100ToBt709;
- case JPEGR_COLORGAMUT_UNSPECIFIED:
+ case ULTRAHDR_COLORGAMUT_UNSPECIFIED:
return nullptr;
}
break;
- case JPEGR_COLORGAMUT_P3:
+ case ULTRAHDR_COLORGAMUT_P3:
switch (hdr_gamut) {
- case JPEGR_COLORGAMUT_BT709:
+ case ULTRAHDR_COLORGAMUT_BT709:
return bt709ToP3;
- case JPEGR_COLORGAMUT_P3:
+ case ULTRAHDR_COLORGAMUT_P3:
return identityConversion;
- case JPEGR_COLORGAMUT_BT2100:
+ case ULTRAHDR_COLORGAMUT_BT2100:
return bt2100ToP3;
- case JPEGR_COLORGAMUT_UNSPECIFIED:
+ case ULTRAHDR_COLORGAMUT_UNSPECIFIED:
return nullptr;
}
break;
- case JPEGR_COLORGAMUT_BT2100:
+ case ULTRAHDR_COLORGAMUT_BT2100:
switch (hdr_gamut) {
- case JPEGR_COLORGAMUT_BT709:
+ case ULTRAHDR_COLORGAMUT_BT709:
return bt709ToBt2100;
- case JPEGR_COLORGAMUT_P3:
+ case ULTRAHDR_COLORGAMUT_P3:
return p3ToBt2100;
- case JPEGR_COLORGAMUT_BT2100:
+ case ULTRAHDR_COLORGAMUT_BT2100:
return identityConversion;
- case JPEGR_COLORGAMUT_UNSPECIFIED:
+ case ULTRAHDR_COLORGAMUT_UNSPECIFIED:
return nullptr;
}
break;
- case JPEGR_COLORGAMUT_UNSPECIFIED:
+ case ULTRAHDR_COLORGAMUT_UNSPECIFIED:
return nullptr;
}
}
////////////////////////////////////////////////////////////////////////////////
-// Recovery map calculations
-uint8_t encodeRecovery(float y_sdr, float y_hdr, jr_metadata_ptr metadata) {
+// Gain map calculations
+uint8_t encodeGain(float y_sdr, float y_hdr, ultrahdr_metadata_ptr metadata) {
+ return encodeGain(y_sdr, y_hdr, metadata,
+ log2(metadata->minContentBoost), log2(metadata->maxContentBoost));
+}
+
+uint8_t encodeGain(float y_sdr, float y_hdr, ultrahdr_metadata_ptr metadata,
+ float log2MinContentBoost, float log2MaxContentBoost) {
float gain = 1.0f;
if (y_sdr > 0.0f) {
gain = y_hdr / y_sdr;
@@ -451,28 +458,28 @@
if (gain < metadata->minContentBoost) gain = metadata->minContentBoost;
if (gain > metadata->maxContentBoost) gain = metadata->maxContentBoost;
- return static_cast<uint8_t>((log2(gain) - log2(metadata->minContentBoost))
- / (log2(metadata->maxContentBoost) - log2(metadata->minContentBoost))
+ return static_cast<uint8_t>((log2(gain) - log2MinContentBoost)
+ / (log2MaxContentBoost - log2MinContentBoost)
* 255.0f);
}
-Color applyRecovery(Color e, float recovery, jr_metadata_ptr metadata) {
- float logBoost = log2(metadata->minContentBoost) * (1.0f - recovery)
- + log2(metadata->maxContentBoost) * recovery;
- float recoveryFactor = exp2(logBoost);
- return e * recoveryFactor;
+Color applyGain(Color e, float gain, ultrahdr_metadata_ptr metadata) {
+ float logBoost = log2(metadata->minContentBoost) * (1.0f - gain)
+ + log2(metadata->maxContentBoost) * gain;
+ float gainFactor = exp2(logBoost);
+ return e * gainFactor;
}
-Color applyRecovery(Color e, float recovery, jr_metadata_ptr metadata, float displayBoost) {
- float logBoost = log2(metadata->minContentBoost) * (1.0f - recovery)
- + log2(metadata->maxContentBoost) * recovery;
- float recoveryFactor = exp2(logBoost * displayBoost / metadata->maxContentBoost);
- return e * recoveryFactor;
+Color applyGain(Color e, float gain, ultrahdr_metadata_ptr metadata, float displayBoost) {
+ float logBoost = log2(metadata->minContentBoost) * (1.0f - gain)
+ + log2(metadata->maxContentBoost) * gain;
+ float gainFactor = exp2(logBoost * displayBoost / metadata->maxContentBoost);
+ return e * gainFactor;
}
-Color applyRecoveryLUT(Color e, float recovery, RecoveryLUT& recoveryLUT) {
- float recoveryFactor = recoveryLUT.getRecoveryFactor(recovery);
- return e * recoveryFactor;
+Color applyGainLUT(Color e, float gain, GainLUT& gainLUT) {
+ float gainFactor = gainLUT.getGainFactor(gain);
+ return e * gainFactor;
}
Color getYuv420Pixel(jr_uncompressed_ptr image, size_t x, size_t y) {
@@ -493,17 +500,28 @@
}
Color getP010Pixel(jr_uncompressed_ptr image, size_t x, size_t y) {
- size_t pixel_count = image->width * image->height;
+ size_t luma_stride = image->luma_stride;
+ size_t chroma_stride = image->chroma_stride;
+ uint16_t* luma_data = reinterpret_cast<uint16_t*>(image->data);
+ uint16_t* chroma_data = reinterpret_cast<uint16_t*>(image->chroma_data);
- size_t pixel_y_idx = x + y * image->width;
- size_t pixel_uv_idx = x / 2 + (y / 2) * (image->width / 2);
+ if (luma_stride == 0) {
+ luma_stride = image->width;
+ }
+ if (chroma_stride == 0) {
+ chroma_stride = luma_stride;
+ }
+ if (chroma_data == nullptr) {
+ chroma_data = &reinterpret_cast<uint16_t*>(image->data)[luma_stride * image->height];
+ }
- uint16_t y_uint = reinterpret_cast<uint16_t*>(image->data)[pixel_y_idx]
- >> 6;
- uint16_t u_uint = reinterpret_cast<uint16_t*>(image->data)[pixel_count + pixel_uv_idx * 2]
- >> 6;
- uint16_t v_uint = reinterpret_cast<uint16_t*>(image->data)[pixel_count + pixel_uv_idx * 2 + 1]
- >> 6;
+ size_t pixel_y_idx = y * luma_stride + x;
+ size_t pixel_u_idx = (y >> 1) * chroma_stride + (x & ~0x1);
+ size_t pixel_v_idx = pixel_u_idx + 1;
+
+ uint16_t y_uint = luma_data[pixel_y_idx] >> 6;
+ uint16_t u_uint = chroma_data[pixel_u_idx] >> 6;
+ uint16_t v_uint = chroma_data[pixel_v_idx] >> 6;
// Conversions include taking narrow-range into account.
return {{{ (static_cast<float>(y_uint) - 64.0f) / 876.0f,
@@ -645,4 +663,4 @@
| (((uint64_t) floatToHalf(1.0f)) << 48);
}
-} // namespace android::jpegrecoverymap
+} // namespace android::ultrahdr
diff --git a/libs/jpegrecoverymap/icc.cpp b/libs/ultrahdr/icc.cpp
similarity index 92%
rename from libs/jpegrecoverymap/icc.cpp
rename to libs/ultrahdr/icc.cpp
index 5412cb1..c807705 100644
--- a/libs/jpegrecoverymap/icc.cpp
+++ b/libs/ultrahdr/icc.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include <jpegrecoverymap/icc.h>
-#include <jpegrecoverymap/recoverymapmath.h>
+#include <ultrahdr/icc.h>
+#include <ultrahdr/gainmapmath.h>
#include <vector>
#include <utils/Log.h>
@@ -23,7 +23,7 @@
#define FLT_MAX 0x1.fffffep127f
#endif
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
static void Matrix3x3_apply(const Matrix3x3* m, float* x) {
float y0 = x[0] * m->vals[0][0] + x[1] * m->vals[0][1] + x[2] * m->vals[0][2];
float y1 = x[0] * m->vals[1][0] + x[1] * m->vals[1][1] + x[2] * m->vals[1][2];
@@ -127,17 +127,17 @@
}
}
-std::string IccHelper::get_desc_string(const jpegr_transfer_function tf,
- const jpegr_color_gamut gamut) {
+std::string IccHelper::get_desc_string(const ultrahdr_transfer_function tf,
+ const ultrahdr_color_gamut gamut) {
std::string result;
switch (gamut) {
- case JPEGR_COLORGAMUT_BT709:
+ case ULTRAHDR_COLORGAMUT_BT709:
result += "sRGB";
break;
- case JPEGR_COLORGAMUT_P3:
+ case ULTRAHDR_COLORGAMUT_P3:
result += "Display P3";
break;
- case JPEGR_COLORGAMUT_BT2100:
+ case ULTRAHDR_COLORGAMUT_BT2100:
result += "Rec2020";
break;
default:
@@ -146,16 +146,16 @@
}
result += " Gamut with ";
switch (tf) {
- case JPEGR_TF_SRGB:
+ case ULTRAHDR_TF_SRGB:
result += "sRGB";
break;
- case JPEGR_TF_LINEAR:
+ case ULTRAHDR_TF_LINEAR:
result += "Linear";
break;
- case JPEGR_TF_PQ:
+ case ULTRAHDR_TF_PQ:
result += "PQ";
break;
- case JPEGR_TF_HLG:
+ case ULTRAHDR_TF_HLG:
result += "HLG";
break;
default:
@@ -234,11 +234,11 @@
return dataStruct;
}
-float IccHelper::compute_tone_map_gain(const jpegr_transfer_function tf, float L) {
+float IccHelper::compute_tone_map_gain(const ultrahdr_transfer_function tf, float L) {
if (L <= 0.f) {
return 1.f;
}
- if (tf == JPEGR_TF_PQ) {
+ if (tf == ULTRAHDR_TF_PQ) {
// The PQ transfer function will map to the range [0, 1]. Linearly scale
// it up to the range [0, 10,000/203]. We will then tone map that back
// down to [0, 1].
@@ -251,7 +251,7 @@
constexpr float kToneMapB = 1.f / kOutputMaxLuminance;
return kInputMaxLuminance * (1.f + kToneMapA * L) / (1.f + kToneMapB * L);
}
- if (tf == JPEGR_TF_HLG) {
+ if (tf == ULTRAHDR_TF_HLG) {
// Let Lw be the brightness of the display in nits.
constexpr float Lw = 203.f;
const float gamma = 1.2f + 0.42f * std::log(Lw / 1000.f) / std::log(10.f);
@@ -295,7 +295,7 @@
float L = bt2100Luminance({{{rgb[0], rgb[1], rgb[2]}}});
// Compute the tone map gain based on the luminance.
- float tone_map_gain = compute_tone_map_gain(JPEGR_TF_PQ, L);
+ float tone_map_gain = compute_tone_map_gain(ULTRAHDR_TF_PQ, L);
// Apply the tone map gain.
for (size_t i = 0; i < kNumChannels; ++i) {
@@ -397,7 +397,8 @@
return dataStruct;
}
-sp<DataStruct> IccHelper::writeIccProfile(jpegr_transfer_function tf, jpegr_color_gamut gamut) {
+sp<DataStruct> IccHelper::writeIccProfile(ultrahdr_transfer_function tf,
+ ultrahdr_color_gamut gamut) {
ICCHeader header;
std::vector<std::pair<uint32_t, sp<DataStruct>>> tags;
@@ -409,13 +410,13 @@
Matrix3x3 toXYZD50;
switch (gamut) {
- case JPEGR_COLORGAMUT_BT709:
+ case ULTRAHDR_COLORGAMUT_BT709:
toXYZD50 = kSRGB;
break;
- case JPEGR_COLORGAMUT_P3:
+ case ULTRAHDR_COLORGAMUT_P3:
toXYZD50 = kDisplayP3;
break;
- case JPEGR_COLORGAMUT_BT2100:
+ case ULTRAHDR_COLORGAMUT_BT2100:
toXYZD50 = kRec2020;
break;
default:
@@ -437,8 +438,8 @@
tags.emplace_back(kTAG_wtpt, write_xyz_tag(kD50_x, kD50_y, kD50_z));
// Compute transfer curves.
- if (tf != JPEGR_TF_PQ) {
- if (tf == JPEGR_TF_HLG) {
+ if (tf != ULTRAHDR_TF_PQ) {
+ if (tf == ULTRAHDR_TF_HLG) {
std::vector<uint8_t> trc_table;
trc_table.resize(kTrcTableSize * 2);
for (uint32_t i = 0; i < kTrcTableSize; ++i) {
@@ -462,32 +463,32 @@
}
// Compute CICP.
- if (tf == JPEGR_TF_HLG || tf == JPEGR_TF_PQ) {
+ if (tf == ULTRAHDR_TF_HLG || tf == ULTRAHDR_TF_PQ) {
// The CICP tag is present in ICC 4.4, so update the header's version.
header.version = Endian_SwapBE32(0x04400000);
uint32_t color_primaries = 0;
- if (gamut == JPEGR_COLORGAMUT_BT709) {
+ if (gamut == ULTRAHDR_COLORGAMUT_BT709) {
color_primaries = kCICPPrimariesSRGB;
- } else if (gamut == JPEGR_COLORGAMUT_P3) {
+ } else if (gamut == ULTRAHDR_COLORGAMUT_P3) {
color_primaries = kCICPPrimariesP3;
}
uint32_t transfer_characteristics = 0;
- if (tf == JPEGR_TF_SRGB) {
+ if (tf == ULTRAHDR_TF_SRGB) {
transfer_characteristics = kCICPTrfnSRGB;
- } else if (tf == JPEGR_TF_LINEAR) {
+ } else if (tf == ULTRAHDR_TF_LINEAR) {
transfer_characteristics = kCICPTrfnLinear;
- } else if (tf == JPEGR_TF_PQ) {
+ } else if (tf == ULTRAHDR_TF_PQ) {
transfer_characteristics = kCICPTrfnPQ;
- } else if (tf == JPEGR_TF_HLG) {
+ } else if (tf == ULTRAHDR_TF_HLG) {
transfer_characteristics = kCICPTrfnHLG;
}
tags.emplace_back(kTAG_cicp, write_cicp_tag(color_primaries, transfer_characteristics));
}
// Compute A2B0.
- if (tf == JPEGR_TF_PQ) {
+ if (tf == ULTRAHDR_TF_PQ) {
std::vector<uint8_t> a2b_grid;
a2b_grid.resize(kGridSize * kGridSize * kGridSize * kNumChannels * 2);
size_t a2b_grid_index = 0;
@@ -520,7 +521,7 @@
}
// Compute B2A0.
- if (tf == JPEGR_TF_PQ) {
+ if (tf == ULTRAHDR_TF_PQ) {
auto b2a_data = write_mAB_or_mBA_tag(kTAG_mBAType,
/* has_a_curves */ false,
/* grid_points */ nullptr,
@@ -541,7 +542,7 @@
// Write the header.
header.data_color_space = Endian_SwapBE32(Signature_RGB);
- header.pcs = Endian_SwapBE32(tf == JPEGR_TF_PQ ? Signature_Lab : Signature_XYZ);
+ header.pcs = Endian_SwapBE32(tf == ULTRAHDR_TF_PQ ? Signature_Lab : Signature_XYZ);
header.size = Endian_SwapBE32(profile_size);
header.tag_count = Endian_SwapBE32(tags.size());
@@ -581,4 +582,4 @@
return dataStruct;
}
-} // namespace android::jpegrecoverymap
\ No newline at end of file
+} // namespace android::ultrahdr
\ No newline at end of file
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymapmath.h b/libs/ultrahdr/include/ultrahdr/gainmapmath.h
similarity index 79%
rename from libs/jpegrecoverymap/include/jpegrecoverymap/recoverymapmath.h
rename to libs/ultrahdr/include/ultrahdr/gainmapmath.h
index 67d2a6a..abc9356 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymapmath.h
+++ b/libs/ultrahdr/include/ultrahdr/gainmapmath.h
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-#ifndef ANDROID_JPEGRECOVERYMAP_RECOVERYMAPMATH_H
-#define ANDROID_JPEGRECOVERYMAP_RECOVERYMAPMATH_H
+#ifndef ANDROID_ULTRAHDR_RECOVERYMAPMATH_H
+#define ANDROID_ULTRAHDR_RECOVERYMAPMATH_H
#include <cmath>
#include <stdint.h>
-#include <jpegrecoverymap/jpegr.h>
+#include <ultrahdr/jpegr.h>
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
#define CLIP3(x, min, max) ((x) < (min)) ? (min) : ((x) > (max)) ? (max) : (x)
@@ -116,47 +116,53 @@
}
inline uint16_t floatToHalf(float f) {
- uint32_t x = *((uint32_t*)&f);
- uint16_t h = ((x >> 16) & 0x8000)
- | ((((x & 0x7f800000) - 0x38000000) >> 13) & 0x7c00)
- | ((x >> 13) & 0x03ff);
- return h;
+ // round-to-nearest-even: add last bit after truncated mantissa
+ const uint32_t b = *((uint32_t*)&f) + 0x00001000;
+
+ const uint32_t e = (b & 0x7F800000) >> 23; // exponent
+ const uint32_t m = b & 0x007FFFFF; // mantissa
+
+ // sign : normalized : denormalized : saturate
+ return (b & 0x80000000) >> 16
+ | (e > 112) * ((((e - 112) << 10) & 0x7C00) | m >> 13)
+ | ((e < 113) & (e > 101)) * ((((0x007FF000 + m) >> (125 - e)) + 1) >> 1)
+ | (e > 143) * 0x7FFF;
}
-constexpr size_t kRecoveryFactorPrecision = 10;
-constexpr size_t kRecoveryFactorNumEntries = 1 << kRecoveryFactorPrecision;
-struct RecoveryLUT {
- RecoveryLUT(jr_metadata_ptr metadata) {
- for (int idx = 0; idx < kRecoveryFactorNumEntries; idx++) {
- float value = static_cast<float>(idx) / static_cast<float>(kRecoveryFactorNumEntries - 1);
+constexpr size_t kGainFactorPrecision = 10;
+constexpr size_t kGainFactorNumEntries = 1 << kGainFactorPrecision;
+struct GainLUT {
+ GainLUT(ultrahdr_metadata_ptr metadata) {
+ for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
+ float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
float logBoost = log2(metadata->minContentBoost) * (1.0f - value)
+ log2(metadata->maxContentBoost) * value;
- mRecoveryTable[idx] = exp2(logBoost);
+ mGainTable[idx] = exp2(logBoost);
}
}
- RecoveryLUT(jr_metadata_ptr metadata, float displayBoost) {
+ GainLUT(ultrahdr_metadata_ptr metadata, float displayBoost) {
float boostFactor = displayBoost > 0 ? displayBoost / metadata->maxContentBoost : 1.0f;
- for (int idx = 0; idx < kRecoveryFactorNumEntries; idx++) {
- float value = static_cast<float>(idx) / static_cast<float>(kRecoveryFactorNumEntries - 1);
+ for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
+ float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
float logBoost = log2(metadata->minContentBoost) * (1.0f - value)
+ log2(metadata->maxContentBoost) * value;
- mRecoveryTable[idx] = exp2(logBoost * boostFactor);
+ mGainTable[idx] = exp2(logBoost * boostFactor);
}
}
- ~RecoveryLUT() {
+ ~GainLUT() {
}
- float getRecoveryFactor(float recovery) {
- uint32_t idx = static_cast<uint32_t>(recovery * (kRecoveryFactorNumEntries - 1));
+ float getGainFactor(float gain) {
+ uint32_t idx = static_cast<uint32_t>(gain * (kGainFactorNumEntries - 1));
//TODO() : Remove once conversion modules have appropriate clamping in place
- idx = CLIP3(idx, 0, kRecoveryFactorNumEntries - 1);
- return mRecoveryTable[idx];
+ idx = CLIP3(idx, 0, kGainFactorNumEntries - 1);
+ return mGainTable[idx];
}
private:
- float mRecoveryTable[kRecoveryFactorNumEntries];
+ float mGainTable[kGainFactorNumEntries];
};
struct ShepardsIDW {
@@ -189,11 +195,11 @@
// p60 p61 p62 p63 p64 p65 p66 p67
// p70 p71 p72 p73 p74 p75 p76 p77
- // Recovery Map (for 4 scale factor) :-
+ // Gain Map (for 4 scale factor) :-
// m00 p01
// m10 m11
- // Recovery sample of curr 4x4, right 4x4, bottom 4x4, bottom right 4x4 are used during
+ // Gain sample of curr 4x4, right 4x4, bottom 4x4, bottom right 4x4 are used during
// reconstruction. hence table weight size is 4.
float* mWeights;
// TODO: check if its ok to mWeights at places
@@ -348,27 +354,29 @@
inline Color identityConversion(Color e) { return e; }
/*
- * Get the conversion to apply to the HDR image for recovery map generation
+ * Get the conversion to apply to the HDR image for gain map generation
*/
-ColorTransformFn getHdrConversionFn(jpegr_color_gamut sdr_gamut, jpegr_color_gamut hdr_gamut);
+ColorTransformFn getHdrConversionFn(ultrahdr_color_gamut sdr_gamut, ultrahdr_color_gamut hdr_gamut);
////////////////////////////////////////////////////////////////////////////////
-// Recovery map calculations
+// Gain map calculations
/*
- * Calculate the 8-bit unsigned integer recovery value for the given SDR and HDR
+ * Calculate the 8-bit unsigned integer gain value for the given SDR and HDR
* luminances in linear space, and the hdr ratio to encode against.
*/
-uint8_t encodeRecovery(float y_sdr, float y_hdr, jr_metadata_ptr metadata);
+uint8_t encodeGain(float y_sdr, float y_hdr, ultrahdr_metadata_ptr metadata);
+uint8_t encodeGain(float y_sdr, float y_hdr, ultrahdr_metadata_ptr metadata,
+ float log2MinContentBoost, float log2MaxContentBoost);
/*
- * Calculates the linear luminance in nits after applying the given recovery
+ * Calculates the linear luminance in nits after applying the given gain
* value, with the given hdr ratio, to the given sdr input in the range [0, 1].
*/
-Color applyRecovery(Color e, float recovery, jr_metadata_ptr metadata);
-Color applyRecovery(Color e, float recovery, jr_metadata_ptr metadata, float displayBoost);
-Color applyRecoveryLUT(Color e, float recovery, RecoveryLUT& recoveryLUT);
+Color applyGain(Color e, float gain, ultrahdr_metadata_ptr metadata);
+Color applyGain(Color e, float gain, ultrahdr_metadata_ptr metadata, float displayBoost);
+Color applyGainLUT(Color e, float gain, GainLUT& gainLUT);
/*
* Helper for sampling from YUV 420 images.
@@ -397,7 +405,7 @@
Color sampleP010(jr_uncompressed_ptr map, size_t map_scale_factor, size_t x, size_t y);
/*
- * Sample the recovery value for the map from a given x,y coordinate on a scale
+ * Sample the gain value for the map from a given x,y coordinate on a scale
* that is map scale factor larger than the map size.
*/
float sampleMap(jr_uncompressed_ptr map, float map_scale_factor, size_t x, size_t y);
@@ -418,6 +426,6 @@
*/
uint64_t colorToRgbaF16(Color e_gamma);
-} // namespace android::jpegrecoverymap
+} // namespace android::ultrahdr
-#endif // ANDROID_JPEGRECOVERYMAP_RECOVERYMAPMATH_H
+#endif // ANDROID_ULTRAHDR_RECOVERYMAPMATH_H
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/icc.h b/libs/ultrahdr/include/ultrahdr/icc.h
similarity index 92%
rename from libs/jpegrecoverymap/include/jpegrecoverymap/icc.h
rename to libs/ultrahdr/include/ultrahdr/icc.h
index a81aa62..7f6ab88 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/icc.h
+++ b/libs/ultrahdr/include/ultrahdr/icc.h
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#ifndef ANDROID_JPEGRECOVERYMAP_ICC_H
-#define ANDROID_JPEGRECOVERYMAP_ICC_H
+#ifndef ANDROID_ULTRAHDR_ICC_H
+#define ANDROID_ULTRAHDR_ICC_H
-#include <jpegrecoverymap/jpegr.h>
-#include <jpegrecoverymap/jpegrutils.h>
+#include <ultrahdr/jpegr.h>
+#include <ultrahdr/jpegrutils.h>
#include <utils/RefBase.h>
#include <cmath>
#include <string>
@@ -28,7 +28,7 @@
#define USE_BIG_ENDIAN true
#endif
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
typedef int32_t Fixed;
#define Fixed1 (1 << 16)
@@ -210,12 +210,12 @@
static constexpr size_t kNumChannels = 3;
static sp<DataStruct> write_text_tag(const char* text);
- static std::string get_desc_string(const jpegr_transfer_function tf,
- const jpegr_color_gamut gamut);
+ static std::string get_desc_string(const ultrahdr_transfer_function tf,
+ const ultrahdr_color_gamut gamut);
static sp<DataStruct> write_xyz_tag(float x, float y, float z);
static sp<DataStruct> write_trc_tag(const int table_entries, const void* table_16);
static sp<DataStruct> write_trc_tag_for_linear();
- static float compute_tone_map_gain(const jpegr_transfer_function tf, float L);
+ static float compute_tone_map_gain(const ultrahdr_transfer_function tf, float L);
static sp<DataStruct> write_cicp_tag(uint32_t color_primaries,
uint32_t transfer_characteristics);
static sp<DataStruct> write_mAB_or_mBA_tag(uint32_t type,
@@ -226,9 +226,9 @@
static sp<DataStruct> write_clut(const uint8_t* grid_points, const uint8_t* grid_16);
public:
- static sp<DataStruct> writeIccProfile(const jpegr_transfer_function tf,
- const jpegr_color_gamut gamut);
+ static sp<DataStruct> writeIccProfile(const ultrahdr_transfer_function tf,
+ const ultrahdr_color_gamut gamut);
};
-} // namespace android::jpegrecoverymap
+} // namespace android::ultrahdr
-#endif //ANDROID_JPEGRECOVERYMAP_ICC_H
\ No newline at end of file
+#endif //ANDROID_ULTRAHDR_ICC_H
\ No newline at end of file
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoderhelper.h b/libs/ultrahdr/include/ultrahdr/jpegdecoderhelper.h
similarity index 94%
rename from libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoderhelper.h
rename to libs/ultrahdr/include/ultrahdr/jpegdecoderhelper.h
index 8748237..f642bad 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoderhelper.h
+++ b/libs/ultrahdr/include/ultrahdr/jpegdecoderhelper.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H
-#define ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H
+#ifndef ANDROID_ULTRAHDR_JPEGDECODERHELPER_H
+#define ANDROID_ULTRAHDR_JPEGDECODERHELPER_H
// We must include cstdio before jpeglib.h. It is a requirement of libjpeg.
#include <cstdio>
@@ -25,7 +25,7 @@
}
#include <utils/Errors.h>
#include <vector>
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
/*
* Encapsulates a converter from JPEG to raw image (YUV420planer or grey-scale) format.
* This class is not thread-safe.
@@ -115,6 +115,6 @@
// Position of EXIF package, default value is -1 which means no EXIF package appears.
size_t mExifPos;
};
-} /* namespace android::jpegrecoverymap */
+} /* namespace android::ultrahdr */
-#endif // ANDROID_JPEGRECOVERYMAP_JPEGDECODERHELPER_H
+#endif // ANDROID_ULTRAHDR_JPEGDECODERHELPER_H
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoderhelper.h b/libs/ultrahdr/include/ultrahdr/jpegencoderhelper.h
similarity index 89%
rename from libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoderhelper.h
rename to libs/ultrahdr/include/ultrahdr/jpegencoderhelper.h
index 8b82b2b..2c6778e 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegencoderhelper.h
+++ b/libs/ultrahdr/include/ultrahdr/jpegencoderhelper.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H
-#define ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H
+#ifndef ANDROID_ULTRAHDR_JPEGENCODERHELPER_H
+#define ANDROID_ULTRAHDR_JPEGENCODERHELPER_H
// We must include cstdio before jpeglib.h. It is a requirement of libjpeg.
#include <cstdio>
@@ -28,7 +28,7 @@
#include <utils/Errors.h>
#include <vector>
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
/*
* Encapsulates a converter from raw image (YUV420planer or grey-scale) to JPEG format.
@@ -61,6 +61,11 @@
*/
size_t getCompressedImageSize();
+ /*
+ * Process 16 lines of Y and 16 lines of U/V each time.
+ * We must pass at least 16 scanlines according to libjpeg documentation.
+ */
+ static const int kCompressBatchSize = 16;
private:
// initDestination(), emptyOutputBuffer() and emptyOutputBuffer() are callback functions to be
// passed into jpeg library.
@@ -82,14 +87,11 @@
// The block size for encoded jpeg image buffer.
static const int kBlockSize = 16384;
- // Process 16 lines of Y and 16 lines of U/V each time.
- // We must pass at least 16 scanlines according to libjpeg documentation.
- static const int kCompressBatchSize = 16;
// The buffer that holds the compressed result.
std::vector<JOCTET> mResultBuffer;
};
-} /* namespace android::jpegrecoverymap */
+} /* namespace android::ultrahdr */
-#endif // ANDROID_JPEGRECOVERYMAP_JPEGENCODERHELPER_H
+#endif // ANDROID_ULTRAHDR_JPEGENCODERHELPER_H
diff --git a/libs/ultrahdr/include/ultrahdr/jpegr.h b/libs/ultrahdr/include/ultrahdr/jpegr.h
new file mode 100644
index 0000000..88038f1
--- /dev/null
+++ b/libs/ultrahdr/include/ultrahdr/jpegr.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#ifndef ANDROID_ULTRAHDR_JPEGR_H
+#define ANDROID_ULTRAHDR_JPEGR_H
+
+#include "jpegrerrorcode.h"
+#include "ultrahdr.h"
+
+#ifndef FLT_MAX
+#define FLT_MAX 0x1.fffffep127f
+#endif
+
+namespace android::ultrahdr {
+
+struct jpegr_info_struct {
+ size_t width;
+ size_t height;
+ std::vector<uint8_t>* iccData;
+ std::vector<uint8_t>* exifData;
+};
+
+/*
+ * Holds information for uncompressed image or gain map.
+ */
+struct jpegr_uncompressed_struct {
+ // Pointer to the data location.
+ void* data;
+ // Width of the gain map or the luma plane of the image in pixels.
+ int width;
+ // Height of the gain map or the luma plane of the image in pixels.
+ int height;
+ // Color gamut.
+ ultrahdr_color_gamut colorGamut;
+
+ // Values below are optional
+ // Pointer to chroma data, if it's NULL, chroma plane is considered to be immediately
+ // following after the luma plane.
+ // Note: currently this feature is only supported for P010 image (HDR input).
+ void* chroma_data = nullptr;
+ // Strides of Y plane in number of pixels, using 0 to present uninitialized, must be
+ // larger than or equal to luma width.
+ // Note: currently this feature is only supported for P010 image (HDR input).
+ int luma_stride = 0;
+ // Strides of UV plane in number of pixels, using 0 to present uninitialized, must be
+ // larger than or equal to chroma width.
+ // Note: currently this feature is only supported for P010 image (HDR input).
+ int chroma_stride = 0;
+};
+
+/*
+ * Holds information for compressed image or gain map.
+ */
+struct jpegr_compressed_struct {
+ // Pointer to the data location.
+ void* data;
+ // Used data length in bytes.
+ int length;
+ // Maximum available data length in bytes.
+ int maxLength;
+ // Color gamut.
+ ultrahdr_color_gamut colorGamut;
+};
+
+/*
+ * Holds information for EXIF metadata.
+ */
+struct jpegr_exif_struct {
+ // Pointer to the data location.
+ void* data;
+ // Data length;
+ int length;
+};
+
+typedef struct jpegr_uncompressed_struct* jr_uncompressed_ptr;
+typedef struct jpegr_compressed_struct* jr_compressed_ptr;
+typedef struct jpegr_exif_struct* jr_exif_ptr;
+typedef struct jpegr_info_struct* jr_info_ptr;
+
+class JpegR {
+public:
+ /*
+ * Experimental only
+ *
+ * Encode API-0
+ * Compress JPEGR image from 10-bit HDR YUV.
+ *
+ * Tonemap the HDR input to a SDR image, generate gain map from the HDR and SDR images,
+ * compress SDR YUV to 8-bit JPEG and append the gain map to the end of the compressed
+ * JPEG.
+ * @param uncompressed_p010_image uncompressed HDR image in P010 color format
+ * @param hdr_tf transfer function of the HDR image
+ * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
+ * represents the maximum available size of the desitination buffer, and it must be
+ * set before calling this method. If the encoded JPEGR size exceeds
+ * {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
+ * @param quality target quality of the JPEG encoding, must be in range of 0-100 where 100 is
+ * the highest quality
+ * @param exif pointer to the exif metadata.
+ * @return NO_ERROR if encoding succeeds, error code if error occurs.
+ */
+ status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
+ ultrahdr_transfer_function hdr_tf,
+ jr_compressed_ptr dest,
+ int quality,
+ jr_exif_ptr exif);
+
+ /*
+ * Encode API-1
+ * Compress JPEGR image from 10-bit HDR YUV and 8-bit SDR YUV.
+ *
+ * Generate gain map from the HDR and SDR inputs, compress SDR YUV to 8-bit JPEG and append
+ * the gain map to the end of the compressed JPEG. HDR and SDR inputs must be the same
+ * resolution.
+ * @param uncompressed_p010_image uncompressed HDR image in P010 color format
+ * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
+ * @param hdr_tf transfer function of the HDR image
+ * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
+ * represents the maximum available size of the desitination buffer, and it must be
+ * set before calling this method. If the encoded JPEGR size exceeds
+ * {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
+ * @param quality target quality of the JPEG encoding, must be in range of 0-100 where 100 is
+ * the highest quality
+ * @param exif pointer to the exif metadata.
+ * @return NO_ERROR if encoding succeeds, error code if error occurs.
+ */
+ status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
+ jr_uncompressed_ptr uncompressed_yuv_420_image,
+ ultrahdr_transfer_function hdr_tf,
+ jr_compressed_ptr dest,
+ int quality,
+ jr_exif_ptr exif);
+
+ /*
+ * Encode API-2
+ * Compress JPEGR image from 10-bit HDR YUV, 8-bit SDR YUV and compressed 8-bit JPEG.
+ *
+ * This method requires HAL Hardware JPEG encoder.
+ *
+ * Generate gain map from the HDR and SDR inputs, append the gain map to the end of the
+ * compressed JPEG. HDR and SDR inputs must be the same resolution and color space.
+ * @param uncompressed_p010_image uncompressed HDR image in P010 color format
+ * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
+ * Note: the SDR image must be the decoded version of the JPEG
+ * input
+ * @param compressed_jpeg_image compressed 8-bit JPEG image
+ * @param hdr_tf transfer function of the HDR image
+ * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
+ * represents the maximum available size of the desitination buffer, and it must be
+ * set before calling this method. If the encoded JPEGR size exceeds
+ * {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
+ * @return NO_ERROR if encoding succeeds, error code if error occurs.
+ */
+ status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
+ jr_uncompressed_ptr uncompressed_yuv_420_image,
+ jr_compressed_ptr compressed_jpeg_image,
+ ultrahdr_transfer_function hdr_tf,
+ jr_compressed_ptr dest);
+
+ /*
+ * Encode API-3
+ * Compress JPEGR image from 10-bit HDR YUV and 8-bit SDR YUV.
+ *
+ * This method requires HAL Hardware JPEG encoder.
+ *
+ * Decode the compressed 8-bit JPEG image to YUV SDR, generate gain map from the HDR input
+ * and the decoded SDR result, append the gain map to the end of the compressed JPEG. HDR
+ * and SDR inputs must be the same resolution.
+ * @param uncompressed_p010_image uncompressed HDR image in P010 color format
+ * @param compressed_jpeg_image compressed 8-bit JPEG image
+ * @param hdr_tf transfer function of the HDR image
+ * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
+ * represents the maximum available size of the desitination buffer, and it must be
+ * set before calling this method. If the encoded JPEGR size exceeds
+ * {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
+ * @return NO_ERROR if encoding succeeds, error code if error occurs.
+ */
+ status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
+ jr_compressed_ptr compressed_jpeg_image,
+ ultrahdr_transfer_function hdr_tf,
+ jr_compressed_ptr dest);
+
+ /*
+ * Encode API-4
+ * Assemble JPEGR image from SDR JPEG and gainmap JPEG.
+ *
+ * Assemble the primary JPEG image, the gain map and the metadata to JPEG/R format.
+ * @param compressed_jpeg_image compressed 8-bit JPEG image
+ * @param compressed_gainmap compressed 8-bit JPEG single channel image
+ * @param metadata metadata to be written in XMP of the primary jpeg
+ * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
+ * represents the maximum available size of the desitination buffer, and it must be
+ * set before calling this method. If the encoded JPEGR size exceeds
+ * {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
+ * @return NO_ERROR if encoding succeeds, error code if error occurs.
+ */
+ status_t encodeJPEGR(jr_compressed_ptr compressed_jpeg_image,
+ jr_compressed_ptr compressed_gainmap,
+ ultrahdr_metadata_ptr metadata,
+ jr_compressed_ptr dest);
+
+ /*
+ * Decode API
+ * Decompress JPEGR image.
+ *
+ * @param compressed_jpegr_image compressed JPEGR image.
+ * @param dest destination of the uncompressed JPEGR image.
+ * @param max_display_boost (optional) the maximum available boost supported by a display,
+ * the value must be greater than or equal to 1.0.
+ * @param exif destination of the decoded EXIF metadata. The default value is NULL where the
+ decoder will do nothing about it. If configured not NULL the decoder will write
+ EXIF data into this structure. The format is defined in {@code jpegr_exif_struct}
+ * @param output_format flag for setting output color format. Its value configures the output
+ color format. The default value is {@code JPEGR_OUTPUT_HDR_LINEAR}.
+ ----------------------------------------------------------------------
+ | output_format | decoded color format to be written |
+ ----------------------------------------------------------------------
+ | JPEGR_OUTPUT_SDR | RGBA_8888 |
+ ----------------------------------------------------------------------
+ | JPEGR_OUTPUT_HDR_LINEAR | (default)RGBA_F16 linear |
+ ----------------------------------------------------------------------
+ | JPEGR_OUTPUT_HDR_PQ | RGBA_1010102 PQ |
+ ----------------------------------------------------------------------
+ | JPEGR_OUTPUT_HDR_HLG | RGBA_1010102 HLG |
+ ----------------------------------------------------------------------
+ * @param gain_map destination of the decoded gain map. The default value is NULL where
+ the decoder will do nothing about it. If configured not NULL the decoder
+ will write the decoded gain_map data into this structure. The format
+ is defined in {@code jpegr_uncompressed_struct}.
+ * @param metadata destination of the decoded metadata. The default value is NULL where the
+ decoder will do nothing about it. If configured not NULL the decoder will
+ write metadata into this structure. the format of metadata is defined in
+ {@code ultrahdr_metadata_struct}.
+ * @return NO_ERROR if decoding succeeds, error code if error occurs.
+ */
+ status_t decodeJPEGR(jr_compressed_ptr compressed_jpegr_image,
+ jr_uncompressed_ptr dest,
+ float max_display_boost = FLT_MAX,
+ jr_exif_ptr exif = nullptr,
+ ultrahdr_output_format output_format = ULTRAHDR_OUTPUT_HDR_LINEAR,
+ jr_uncompressed_ptr gain_map = nullptr,
+ ultrahdr_metadata_ptr metadata = nullptr);
+
+ /*
+ * Gets Info from JPEGR file without decoding it.
+ *
+ * The output is filled jpegr_info structure
+ * @param compressed_jpegr_image compressed JPEGR image
+ * @param jpegr_info pointer to output JPEGR info. Members of jpegr_info
+ * are owned by the caller
+ * @return NO_ERROR if JPEGR parsing succeeds, error code otherwise
+ */
+ status_t getJPEGRInfo(jr_compressed_ptr compressed_jpegr_image,
+ jr_info_ptr jpegr_info);
+protected:
+ /*
+ * This method is called in the encoding pipeline. It will take the uncompressed 8-bit and
+ * 10-bit yuv images as input, and calculate the uncompressed gain map. The input images
+ * must be the same resolution.
+ *
+ * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
+ * @param uncompressed_p010_image uncompressed HDR image in P010 color format
+ * @param hdr_tf transfer function of the HDR image
+ * @param dest gain map; caller responsible for memory of data
+ * @param metadata max_content_boost is filled in
+ * @return NO_ERROR if calculation succeeds, error code if error occurs.
+ */
+ status_t generateGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
+ jr_uncompressed_ptr uncompressed_p010_image,
+ ultrahdr_transfer_function hdr_tf,
+ ultrahdr_metadata_ptr metadata,
+ jr_uncompressed_ptr dest);
+
+ /*
+ * This method is called in the decoding pipeline. It will take the uncompressed (decoded)
+ * 8-bit yuv image, the uncompressed (decoded) gain map, and extracted JPEG/R metadata as
+ * input, and calculate the 10-bit recovered image. The recovered output image is the same
+ * color gamut as the SDR image, with HLG transfer function, and is in RGBA1010102 data format.
+ *
+ * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
+ * @param uncompressed_gain_map uncompressed gain map
+ * @param metadata JPEG/R metadata extracted from XMP.
+ * @param output_format flag for setting output color format. if set to
+ * {@code JPEGR_OUTPUT_SDR}, decoder will only decode the primary image
+ * which is SDR. Default value is JPEGR_OUTPUT_HDR_LINEAR.
+ * @param max_display_boost the maximum available boost supported by a display
+ * @param dest reconstructed HDR image
+ * @return NO_ERROR if calculation succeeds, error code if error occurs.
+ */
+ status_t applyGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
+ jr_uncompressed_ptr uncompressed_gain_map,
+ ultrahdr_metadata_ptr metadata,
+ ultrahdr_output_format output_format,
+ float max_display_boost,
+ jr_uncompressed_ptr dest);
+
+private:
+ /*
+ * This method is called in the encoding pipeline. It will encode the gain map.
+ *
+ * @param uncompressed_gain_map uncompressed gain map
+ * @param dest encoded recover map
+ * @return NO_ERROR if encoding succeeds, error code if error occurs.
+ */
+ status_t compressGainMap(jr_uncompressed_ptr uncompressed_gain_map,
+ jr_compressed_ptr dest);
+
+ /*
+ * This methoud is called to separate primary image and gain map image from JPEGR
+ *
+ * @param compressed_jpegr_image compressed JPEGR image
+ * @param primary_image destination of primary image
+ * @param gain_map destination of compressed gain map
+ * @return NO_ERROR if calculation succeeds, error code if error occurs.
+ */
+ status_t extractPrimaryImageAndGainMap(jr_compressed_ptr compressed_jpegr_image,
+ jr_compressed_ptr primary_image,
+ jr_compressed_ptr gain_map);
+ /*
+ * This method is called in the decoding pipeline. It will read XMP metadata to find the start
+ * position of the compressed gain map, and will extract the compressed gain map.
+ *
+ * @param compressed_jpegr_image compressed JPEGR image
+ * @param dest destination of compressed gain map
+ * @return NO_ERROR if calculation succeeds, error code if error occurs.
+ */
+ status_t extractGainMap(jr_compressed_ptr compressed_jpegr_image,
+ jr_compressed_ptr dest);
+
+ /*
+ * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image,
+ * the compressed gain map and optionally the exif package as inputs, and generate the XMP
+ * metadata, and finally append everything in the order of:
+ * SOI, APP2(EXIF) (if EXIF is from outside), APP2(XMP), primary image, gain map
+ * Note that EXIF package is only available for encoding API-0 and API-1. For encoding API-2 and
+ * API-3 this parameter is null, but the primary image in JPEG/R may still have EXIF as long as
+ * the input JPEG has EXIF.
+ *
+ * @param compressed_jpeg_image compressed 8-bit JPEG image
+ * @param compress_gain_map compressed recover map
+ * @param (nullable) exif EXIF package
+ * @param metadata JPEG/R metadata to encode in XMP of the jpeg
+ * @param dest compressed JPEGR image
+ * @return NO_ERROR if calculation succeeds, error code if error occurs.
+ */
+ status_t appendGainMap(jr_compressed_ptr compressed_jpeg_image,
+ jr_compressed_ptr compressed_gain_map,
+ jr_exif_ptr exif,
+ ultrahdr_metadata_ptr metadata,
+ jr_compressed_ptr dest);
+
+ /*
+ * This method will tone map a HDR image to an SDR image.
+ *
+ * @param src (input) uncompressed P010 image
+ * @param dest (output) tone mapping result as a YUV_420 image
+ * @return NO_ERROR if calculation succeeds, error code if error occurs.
+ */
+ status_t toneMap(jr_uncompressed_ptr src,
+ jr_uncompressed_ptr dest);
+
+ /*
+ * This method will check the validity of the input images.
+ *
+ * @param uncompressed_p010_image uncompressed HDR image in P010 color format
+ * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
+ * @return NO_ERROR if the input images are valid, error code is not valid.
+ */
+ status_t areInputImagesValid(jr_uncompressed_ptr uncompressed_p010_image,
+ jr_uncompressed_ptr uncompressed_yuv_420_image);
+};
+
+} // namespace android::ultrahdr
+
+#endif // ANDROID_ULTRAHDR_JPEGR_H
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrerrorcode.h b/libs/ultrahdr/include/ultrahdr/jpegrerrorcode.h
similarity index 89%
rename from libs/jpegrecoverymap/include/jpegrecoverymap/jpegrerrorcode.h
rename to libs/ultrahdr/include/ultrahdr/jpegrerrorcode.h
index f730343..9f59c3e 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrerrorcode.h
+++ b/libs/ultrahdr/include/ultrahdr/jpegrerrorcode.h
@@ -14,9 +14,12 @@
* limitations under the License.
*/
+#ifndef ANDROID_ULTRAHDR_JPEGRERRORCODE_H
+#define ANDROID_ULTRAHDR_JPEGRERRORCODE_H
+
#include <utils/Errors.h>
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
enum {
// status_t map for errors in the media framework
@@ -46,6 +49,10 @@
ERROR_JPEGR_CALCULATION_ERROR = JPEGR_RUNTIME_ERROR_BASE - 3,
ERROR_JPEGR_METADATA_ERROR = JPEGR_RUNTIME_ERROR_BASE - 4,
ERROR_JPEGR_TONEMAP_ERROR = JPEGR_RUNTIME_ERROR_BASE - 5,
+
+ ERROR_JPEGR_UNSUPPORTED_FEATURE = -20000,
};
-} // namespace android::jpegrecoverymap
+} // namespace android::ultrahdr
+
+#endif // ANDROID_ULTRAHDR_JPEGRERRORCODE_H
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrutils.h b/libs/ultrahdr/include/ultrahdr/jpegrutils.h
similarity index 90%
rename from libs/jpegrecoverymap/include/jpegrecoverymap/jpegrutils.h
rename to libs/ultrahdr/include/ultrahdr/jpegrutils.h
index 09f4165..ed38e07 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrutils.h
+++ b/libs/ultrahdr/include/ultrahdr/jpegrutils.h
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#ifndef ANDROID_JPEGRECOVERYMAP_JPEGRUTILS_H
-#define ANDROID_JPEGRECOVERYMAP_JPEGRUTILS_H
+#ifndef ANDROID_ULTRAHDR_JPEGRUTILS_H
+#define ANDROID_ULTRAHDR_JPEGRUTILS_H
-#include <jpegrecoverymap/jpegr.h>
+#include <ultrahdr/jpegr.h>
#include <utils/RefBase.h>
#include <sstream>
@@ -25,7 +25,7 @@
#include <string>
#include <cstdio>
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
static constexpr uint32_t EndianSwap32(uint32_t value) {
return ((value & 0xFF) << 24) |
@@ -45,7 +45,7 @@
#define Endian_SwapBE16(n) (n)
#endif
-struct jpegr_metadata_struct;
+struct ultrahdr_metadata_struct;
/*
* Mutable data structure. Holds information for metadata.
*/
@@ -87,7 +87,7 @@
* @param metadata place to store HDR metadata values
* @return true if metadata is successfully retrieved, false otherwise
*/
-bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata_struct* metadata);
+bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, ultrahdr_metadata_struct* metadata);
/*
* This method generates XMP metadata for the primary image.
@@ -158,7 +158,7 @@
* @param metadata JPEG/R metadata to encode as XMP
* @return XMP metadata in type of string
*/
- std::string generateXmpForSecondaryImage(jpegr_metadata_struct& metadata);
-} // namespace android::jpegrecoverymap
+ std::string generateXmpForSecondaryImage(ultrahdr_metadata_struct& metadata);
+} // namespace android::ultrahdr
-#endif //ANDROID_JPEGRECOVERYMAP_JPEGRUTILS_H
+#endif //ANDROID_ULTRAHDR_JPEGRUTILS_H
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/multipictureformat.h b/libs/ultrahdr/include/ultrahdr/multipictureformat.h
similarity index 87%
rename from libs/jpegrecoverymap/include/jpegrecoverymap/multipictureformat.h
rename to libs/ultrahdr/include/ultrahdr/multipictureformat.h
index cf3387d..c5bd09d 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/multipictureformat.h
+++ b/libs/ultrahdr/include/ultrahdr/multipictureformat.h
@@ -14,17 +14,17 @@
* limitations under the License.
*/
-#ifndef ANDROID_JPEGRECOVERYMAP_MULTIPICTUREFORMAT_H
-#define ANDROID_JPEGRECOVERYMAP_MULTIPICTUREFORMAT_H
+#ifndef ANDROID_ULTRAHDR_MULTIPICTUREFORMAT_H
+#define ANDROID_ULTRAHDR_MULTIPICTUREFORMAT_H
-#include <jpegrecoverymap/jpegrutils.h>
+#include <ultrahdr/jpegrutils.h>
#ifdef USE_BIG_ENDIAN
#undef USE_BIG_ENDIAN
#define USE_BIG_ENDIAN true
#endif
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
constexpr size_t kNumPictures = 2;
constexpr size_t kMpEndianSize = 4;
@@ -59,6 +59,6 @@
sp<DataStruct> generateMpf(int primary_image_size, int primary_image_offset,
int secondary_image_size, int secondary_image_offset);
-} // namespace android::jpegrecoverymap
+} // namespace android::ultrahdr
-#endif //ANDROID_JPEGRECOVERYMAP_MULTIPICTUREFORMAT_H
+#endif //ANDROID_ULTRAHDR_MULTIPICTUREFORMAT_H
diff --git a/libs/ultrahdr/include/ultrahdr/ultrahdr.h b/libs/ultrahdr/include/ultrahdr/ultrahdr.h
new file mode 100644
index 0000000..302aeee
--- /dev/null
+++ b/libs/ultrahdr/include/ultrahdr/ultrahdr.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#ifndef ANDROID_ULTRAHDR_ULTRAHDR_H
+#define ANDROID_ULTRAHDR_ULTRAHDR_H
+
+namespace android::ultrahdr {
+// Color gamuts for image data
+typedef enum {
+ ULTRAHDR_COLORGAMUT_UNSPECIFIED,
+ ULTRAHDR_COLORGAMUT_BT709,
+ ULTRAHDR_COLORGAMUT_P3,
+ ULTRAHDR_COLORGAMUT_BT2100,
+} ultrahdr_color_gamut;
+
+// Transfer functions for image data
+typedef enum {
+ ULTRAHDR_TF_UNSPECIFIED = -1,
+ ULTRAHDR_TF_LINEAR = 0,
+ ULTRAHDR_TF_HLG = 1,
+ ULTRAHDR_TF_PQ = 2,
+ ULTRAHDR_TF_SRGB = 3,
+} ultrahdr_transfer_function;
+
+// Target output formats for decoder
+typedef enum {
+ ULTRAHDR_OUTPUT_SDR, // SDR in RGBA_8888 color format
+ ULTRAHDR_OUTPUT_HDR_LINEAR, // HDR in F16 color format (linear)
+ ULTRAHDR_OUTPUT_HDR_PQ, // HDR in RGBA_1010102 color format (PQ transfer function)
+ ULTRAHDR_OUTPUT_HDR_HLG, // HDR in RGBA_1010102 color format (HLG transfer function)
+} ultrahdr_output_format;
+
+/*
+ * Holds information for gain map related metadata.
+ */
+struct ultrahdr_metadata_struct {
+ // Ultra HDR library version
+ uint32_t version;
+ // Max Content Boost for the map
+ float maxContentBoost;
+ // Min Content Boost for the map
+ float minContentBoost;
+};
+typedef struct ultrahdr_metadata_struct* ultrahdr_metadata_ptr;
+
+} // namespace android::ultrahdr
+
+#endif //ANDROID_ULTRAHDR_ULTRAHDR_H
\ No newline at end of file
diff --git a/libs/jpegrecoverymap/jpegdecoderhelper.cpp b/libs/ultrahdr/jpegdecoderhelper.cpp
similarity index 98%
rename from libs/jpegrecoverymap/jpegdecoderhelper.cpp
rename to libs/ultrahdr/jpegdecoderhelper.cpp
index d36bbf8..12217b7 100644
--- a/libs/jpegrecoverymap/jpegdecoderhelper.cpp
+++ b/libs/ultrahdr/jpegdecoderhelper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <jpegrecoverymap/jpegdecoderhelper.h>
+#include <ultrahdr/jpegdecoderhelper.h>
#include <utils/Log.h>
@@ -24,7 +24,7 @@
using namespace std;
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
const uint32_t kAPP0Marker = JPEG_APP0; // JFIF
const uint32_t kAPP1Marker = JPEG_APP0 + 1; // EXIF, XMP
@@ -413,4 +413,4 @@
return true;
}
-} // namespace jpegrecoverymap
+} // namespace ultrahdr
diff --git a/libs/jpegrecoverymap/jpegencoderhelper.cpp b/libs/ultrahdr/jpegencoderhelper.cpp
similarity index 96%
rename from libs/jpegrecoverymap/jpegencoderhelper.cpp
rename to libs/ultrahdr/jpegencoderhelper.cpp
index 586cd34..10a7630 100644
--- a/libs/jpegrecoverymap/jpegencoderhelper.cpp
+++ b/libs/ultrahdr/jpegencoderhelper.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#include <jpegrecoverymap/jpegencoderhelper.h>
+#include <ultrahdr/jpegencoderhelper.h>
#include <utils/Log.h>
#include <errno.h>
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
// The destination manager that can access |mResultBuffer| in JpegEncoderHelper.
struct destination_mgr {
@@ -38,11 +38,6 @@
bool JpegEncoderHelper::compressImage(const void* image, int width, int height, int quality,
const void* iccBuffer, unsigned int iccSize,
bool isSingleChannel) {
- if (width % 8 != 0 || height % 2 != 0) {
- ALOGE("Image size can not be handled: %dx%d", width, height);
- return false;
- }
-
mResultBuffer.clear();
if (!encode(image, width, height, quality, iccBuffer, iccSize, isSingleChannel)) {
return false;
@@ -236,4 +231,4 @@
return true;
}
-} // namespace jpegrecoverymap
+} // namespace ultrahdr
diff --git a/libs/jpegrecoverymap/jpegr.cpp b/libs/ultrahdr/jpegr.cpp
similarity index 71%
rename from libs/jpegrecoverymap/jpegr.cpp
rename to libs/ultrahdr/jpegr.cpp
index e395d51..5f55d1b 100644
--- a/libs/jpegrecoverymap/jpegr.cpp
+++ b/libs/ultrahdr/jpegr.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#include <jpegrecoverymap/jpegr.h>
-#include <jpegrecoverymap/jpegencoderhelper.h>
-#include <jpegrecoverymap/jpegdecoderhelper.h>
-#include <jpegrecoverymap/recoverymapmath.h>
-#include <jpegrecoverymap/jpegrutils.h>
-#include <jpegrecoverymap/multipictureformat.h>
-#include <jpegrecoverymap/icc.h>
+#include <ultrahdr/jpegr.h>
+#include <ultrahdr/jpegencoderhelper.h>
+#include <ultrahdr/jpegdecoderhelper.h>
+#include <ultrahdr/gainmapmath.h>
+#include <ultrahdr/jpegrutils.h>
+#include <ultrahdr/multipictureformat.h>
+#include <ultrahdr/icc.h>
#include <image_io/jpeg/jpeg_marker.h>
#include <image_io/jpeg/jpeg_info.h>
@@ -43,14 +43,14 @@
using namespace std;
using namespace photos_editing_formats::image_io;
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
#define USE_SRGB_INVOETF_LUT 1
#define USE_HLG_OETF_LUT 1
#define USE_PQ_OETF_LUT 1
#define USE_HLG_INVOETF_LUT 1
#define USE_PQ_INVOETF_LUT 1
-#define USE_APPLY_RECOVERY_LUT 1
+#define USE_APPLY_GAIN_LUT 1
#define JPEGR_CHECK(x) \
{ \
@@ -66,10 +66,13 @@
// Map is quarter res / sixteenth size
static const size_t kMapDimensionScaleFactor = 4;
// JPEG block size.
-// JPEG encoding / decoding will require 8 x 8 DCT transform.
-// Width must be 8 dividable, and height must be 2 dividable.
-static const size_t kJpegBlock = 8;
-// JPEG compress quality (0 ~ 100) for recovery map
+// JPEG encoding / decoding will require block based DCT transform 16 x 16 for luma,
+// and 8 x 8 for chroma.
+// Width must be 16 dividable for luma, and 8 dividable for chroma.
+// If this criteria is not ficilitated, we will pad zeros based on the required block size.
+static const size_t kJpegBlock = JpegEncoderHelper::kCompressBatchSize;
+static const size_t kJpegBlockSquare = kJpegBlock * kJpegBlock;
+// JPEG compress quality (0 ~ 100) for gain map
static const int kMapCompressQuality = 85;
#define CONFIG_MULTITHREAD 1
@@ -86,9 +89,50 @@
return cpuCoreCount;
}
+status_t JpegR::areInputImagesValid(jr_uncompressed_ptr uncompressed_p010_image,
+ jr_uncompressed_ptr uncompressed_yuv_420_image) {
+ if (uncompressed_p010_image == nullptr) {
+ return ERROR_JPEGR_INVALID_NULL_PTR;
+ }
+
+ if (uncompressed_p010_image->luma_stride != 0
+ && uncompressed_p010_image->luma_stride < uncompressed_p010_image->width) {
+ ALOGE("Image stride can not be smaller than width, stride=%d, width=%d",
+ uncompressed_p010_image->luma_stride, uncompressed_p010_image->width);
+ return ERROR_JPEGR_INVALID_INPUT_TYPE;
+ }
+
+ if (uncompressed_yuv_420_image == nullptr) {
+ return NO_ERROR;
+ }
+
+ if (uncompressed_yuv_420_image->luma_stride != 0) {
+ ALOGE("Stride is not supported for YUV420 image");
+ return ERROR_JPEGR_UNSUPPORTED_FEATURE;
+ }
+
+ if (uncompressed_yuv_420_image->chroma_data != nullptr) {
+ ALOGE("Pointer to chroma plane is not supported for YUV420 image, chroma data must"
+ "be immediately after the luma data.");
+ return ERROR_JPEGR_UNSUPPORTED_FEATURE;
+ }
+
+ if (uncompressed_p010_image->width != uncompressed_yuv_420_image->width
+ || uncompressed_p010_image->height != uncompressed_yuv_420_image->height) {
+ ALOGE("Image resolutions mismatch: P010: %dx%d, YUV420: %dx%d",
+ uncompressed_p010_image->width,
+ uncompressed_p010_image->height,
+ uncompressed_yuv_420_image->width,
+ uncompressed_yuv_420_image->height);
+ return ERROR_JPEGR_RESOLUTION_MISMATCH;
+ }
+
+ return NO_ERROR;
+}
+
/* Encode API-0 */
status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
- jpegr_transfer_function hdr_tf,
+ ultrahdr_transfer_function hdr_tf,
jr_compressed_ptr dest,
int quality,
jr_exif_ptr exif) {
@@ -100,24 +144,27 @@
return ERROR_JPEGR_INVALID_INPUT_TYPE;
}
- if (uncompressed_p010_image->width % kJpegBlock != 0
- || uncompressed_p010_image->height % 2 != 0) {
- ALOGE("Image size can not be handled: %dx%d",
- uncompressed_p010_image->width, uncompressed_p010_image->height);
- return ERROR_JPEGR_INVALID_INPUT_TYPE;
+ if (status_t ret = areInputImagesValid(
+ uncompressed_p010_image, /* uncompressed_yuv_420_image */ nullptr) != NO_ERROR) {
+ return ret;
}
- jpegr_metadata_struct metadata;
+ ultrahdr_metadata_struct metadata;
metadata.version = kJpegrVersion;
jpegr_uncompressed_struct uncompressed_yuv_420_image;
- unique_ptr<uint8_t[]> uncompressed_yuv_420_image_data = make_unique<uint8_t[]>(
- uncompressed_p010_image->width * uncompressed_p010_image->height * 3 / 2);
+ size_t gain_map_length = uncompressed_p010_image->width * uncompressed_p010_image->height * 3 / 2;
+ // Pad a pseudo chroma block (kJpegBlock / 2) x (kJpegBlock / 2)
+ // if width is not kJpegBlock aligned.
+ if (uncompressed_p010_image->width % kJpegBlock != 0) {
+ gain_map_length += kJpegBlockSquare / 4;
+ }
+ unique_ptr<uint8_t[]> uncompressed_yuv_420_image_data = make_unique<uint8_t[]>(gain_map_length);
uncompressed_yuv_420_image.data = uncompressed_yuv_420_image_data.get();
JPEGR_CHECK(toneMap(uncompressed_p010_image, &uncompressed_yuv_420_image));
jpegr_uncompressed_struct map;
- JPEGR_CHECK(generateRecoveryMap(
+ JPEGR_CHECK(generateGainMap(
&uncompressed_yuv_420_image, uncompressed_p010_image, hdr_tf, &metadata, &map));
std::unique_ptr<uint8_t[]> map_data;
map_data.reset(reinterpret_cast<uint8_t*>(map.data));
@@ -126,9 +173,9 @@
compressed_map.maxLength = map.width * map.height;
unique_ptr<uint8_t[]> compressed_map_data = make_unique<uint8_t[]>(compressed_map.maxLength);
compressed_map.data = compressed_map_data.get();
- JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map));
+ JPEGR_CHECK(compressGainMap(&map, &compressed_map));
- sp<DataStruct> icc = IccHelper::writeIccProfile(JPEGR_TF_SRGB,
+ sp<DataStruct> icc = IccHelper::writeIccProfile(ULTRAHDR_TF_SRGB,
uncompressed_yuv_420_image.colorGamut);
JpegEncoderHelper jpeg_encoder;
@@ -142,7 +189,7 @@
jpeg.data = jpeg_encoder.getCompressedImagePtr();
jpeg.length = jpeg_encoder.getCompressedImageSize();
- JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, exif, &metadata, dest));
+ JPEGR_CHECK(appendGainMap(&jpeg, &compressed_map, exif, &metadata, dest));
return NO_ERROR;
}
@@ -150,7 +197,7 @@
/* Encode API-1 */
status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
jr_uncompressed_ptr uncompressed_yuv_420_image,
- jpegr_transfer_function hdr_tf,
+ ultrahdr_transfer_function hdr_tf,
jr_compressed_ptr dest,
int quality,
jr_exif_ptr exif) {
@@ -164,23 +211,16 @@
return ERROR_JPEGR_INVALID_INPUT_TYPE;
}
- if (uncompressed_p010_image->width != uncompressed_yuv_420_image->width
- || uncompressed_p010_image->height != uncompressed_yuv_420_image->height) {
- return ERROR_JPEGR_RESOLUTION_MISMATCH;
+ if (status_t ret = areInputImagesValid(
+ uncompressed_p010_image, uncompressed_yuv_420_image) != NO_ERROR) {
+ return ret;
}
- if (uncompressed_p010_image->width % kJpegBlock != 0
- || uncompressed_p010_image->height % 2 != 0) {
- ALOGE("Image size can not be handled: %dx%d",
- uncompressed_p010_image->width, uncompressed_p010_image->height);
- return ERROR_JPEGR_INVALID_INPUT_TYPE;
- }
-
- jpegr_metadata_struct metadata;
+ ultrahdr_metadata_struct metadata;
metadata.version = kJpegrVersion;
jpegr_uncompressed_struct map;
- JPEGR_CHECK(generateRecoveryMap(
+ JPEGR_CHECK(generateGainMap(
uncompressed_yuv_420_image, uncompressed_p010_image, hdr_tf, &metadata, &map));
std::unique_ptr<uint8_t[]> map_data;
map_data.reset(reinterpret_cast<uint8_t*>(map.data));
@@ -189,9 +229,9 @@
compressed_map.maxLength = map.width * map.height;
unique_ptr<uint8_t[]> compressed_map_data = make_unique<uint8_t[]>(compressed_map.maxLength);
compressed_map.data = compressed_map_data.get();
- JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map));
+ JPEGR_CHECK(compressGainMap(&map, &compressed_map));
- sp<DataStruct> icc = IccHelper::writeIccProfile(JPEGR_TF_SRGB,
+ sp<DataStruct> icc = IccHelper::writeIccProfile(ULTRAHDR_TF_SRGB,
uncompressed_yuv_420_image->colorGamut);
JpegEncoderHelper jpeg_encoder;
@@ -205,7 +245,7 @@
jpeg.data = jpeg_encoder.getCompressedImagePtr();
jpeg.length = jpeg_encoder.getCompressedImageSize();
- JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, exif, &metadata, dest));
+ JPEGR_CHECK(appendGainMap(&jpeg, &compressed_map, exif, &metadata, dest));
return NO_ERROR;
}
@@ -214,7 +254,7 @@
status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
jr_uncompressed_ptr uncompressed_yuv_420_image,
jr_compressed_ptr compressed_jpeg_image,
- jpegr_transfer_function hdr_tf,
+ ultrahdr_transfer_function hdr_tf,
jr_compressed_ptr dest) {
if (uncompressed_p010_image == nullptr
|| uncompressed_yuv_420_image == nullptr
@@ -223,23 +263,16 @@
return ERROR_JPEGR_INVALID_NULL_PTR;
}
- if (uncompressed_p010_image->width != uncompressed_yuv_420_image->width
- || uncompressed_p010_image->height != uncompressed_yuv_420_image->height) {
- return ERROR_JPEGR_RESOLUTION_MISMATCH;
+ if (status_t ret = areInputImagesValid(
+ uncompressed_p010_image, uncompressed_yuv_420_image) != NO_ERROR) {
+ return ret;
}
- if (uncompressed_p010_image->width % kJpegBlock != 0
- || uncompressed_p010_image->height % 2 != 0) {
- ALOGE("Image size can not be handled: %dx%d",
- uncompressed_p010_image->width, uncompressed_p010_image->height);
- return ERROR_JPEGR_INVALID_INPUT_TYPE;
- }
-
- jpegr_metadata_struct metadata;
+ ultrahdr_metadata_struct metadata;
metadata.version = kJpegrVersion;
jpegr_uncompressed_struct map;
- JPEGR_CHECK(generateRecoveryMap(
+ JPEGR_CHECK(generateGainMap(
uncompressed_yuv_420_image, uncompressed_p010_image, hdr_tf, &metadata, &map));
std::unique_ptr<uint8_t[]> map_data;
map_data.reset(reinterpret_cast<uint8_t*>(map.data));
@@ -248,9 +281,9 @@
compressed_map.maxLength = map.width * map.height;
unique_ptr<uint8_t[]> compressed_map_data = make_unique<uint8_t[]>(compressed_map.maxLength);
compressed_map.data = compressed_map_data.get();
- JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map));
+ JPEGR_CHECK(compressGainMap(&map, &compressed_map));
- JPEGR_CHECK(appendRecoveryMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest));
+ JPEGR_CHECK(appendGainMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest));
return NO_ERROR;
}
@@ -258,7 +291,7 @@
/* Encode API-3 */
status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
jr_compressed_ptr compressed_jpeg_image,
- jpegr_transfer_function hdr_tf,
+ ultrahdr_transfer_function hdr_tf,
jr_compressed_ptr dest) {
if (uncompressed_p010_image == nullptr
|| compressed_jpeg_image == nullptr
@@ -266,11 +299,9 @@
return ERROR_JPEGR_INVALID_NULL_PTR;
}
- if (uncompressed_p010_image->width % kJpegBlock != 0
- || uncompressed_p010_image->height % 2 != 0) {
- ALOGE("Image size can not be handled: %dx%d",
- uncompressed_p010_image->width, uncompressed_p010_image->height);
- return ERROR_JPEGR_INVALID_INPUT_TYPE;
+ if (status_t ret = areInputImagesValid(
+ uncompressed_p010_image, /* uncompressed_yuv_420_image */ nullptr) != NO_ERROR) {
+ return ret;
}
JpegDecoderHelper jpeg_decoder;
@@ -288,11 +319,11 @@
return ERROR_JPEGR_RESOLUTION_MISMATCH;
}
- jpegr_metadata_struct metadata;
+ ultrahdr_metadata_struct metadata;
metadata.version = kJpegrVersion;
jpegr_uncompressed_struct map;
- JPEGR_CHECK(generateRecoveryMap(
+ JPEGR_CHECK(generateGainMap(
&uncompressed_yuv_420_image, uncompressed_p010_image, hdr_tf, &metadata, &map));
std::unique_ptr<uint8_t[]> map_data;
map_data.reset(reinterpret_cast<uint8_t*>(map.data));
@@ -301,21 +332,31 @@
compressed_map.maxLength = map.width * map.height;
unique_ptr<uint8_t[]> compressed_map_data = make_unique<uint8_t[]>(compressed_map.maxLength);
compressed_map.data = compressed_map_data.get();
- JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map));
+ JPEGR_CHECK(compressGainMap(&map, &compressed_map));
- JPEGR_CHECK(appendRecoveryMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest));
+ JPEGR_CHECK(appendGainMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest));
return NO_ERROR;
}
+/* Encode API-4 */
+status_t JpegR::encodeJPEGR(jr_compressed_ptr compressed_jpeg_image,
+ jr_compressed_ptr compressed_gainmap,
+ ultrahdr_metadata_ptr metadata,
+ jr_compressed_ptr dest) {
+ JPEGR_CHECK(appendGainMap(compressed_jpeg_image, compressed_gainmap, /* exif */ nullptr,
+ metadata, dest));
+ return NO_ERROR;
+}
+
status_t JpegR::getJPEGRInfo(jr_compressed_ptr compressed_jpegr_image, jr_info_ptr jpegr_info) {
if (compressed_jpegr_image == nullptr || jpegr_info == nullptr) {
return ERROR_JPEGR_INVALID_NULL_PTR;
}
- jpegr_compressed_struct primary_image, recovery_map;
- JPEGR_CHECK(extractPrimaryImageAndRecoveryMap(compressed_jpegr_image,
- &primary_image, &recovery_map));
+ jpegr_compressed_struct primary_image, gain_map;
+ JPEGR_CHECK(extractPrimaryImageAndGainMap(compressed_jpegr_image,
+ &primary_image, &gain_map));
JpegDecoderHelper jpeg_decoder;
if (!jpeg_decoder.getCompressedImageParameters(primary_image.data, primary_image.length,
@@ -332,14 +373,18 @@
jr_uncompressed_ptr dest,
float max_display_boost,
jr_exif_ptr exif,
- jpegr_output_format output_format,
- jr_uncompressed_ptr recovery_map,
- jr_metadata_ptr metadata) {
+ ultrahdr_output_format output_format,
+ jr_uncompressed_ptr gain_map,
+ ultrahdr_metadata_ptr metadata) {
if (compressed_jpegr_image == nullptr || dest == nullptr) {
return ERROR_JPEGR_INVALID_NULL_PTR;
}
- if (output_format == JPEGR_OUTPUT_SDR) {
+ if (max_display_boost < 1.0f) {
+ return ERROR_JPEGR_INVALID_INPUT_TYPE;
+ }
+
+ if (output_format == ULTRAHDR_OUTPUT_SDR) {
JpegDecoderHelper jpeg_decoder;
if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length,
true)) {
@@ -354,7 +399,7 @@
dest->width = uncompressed_rgba_image.width;
dest->height = uncompressed_rgba_image.height;
- if (recovery_map == nullptr && exif == nullptr) {
+ if (gain_map == nullptr && exif == nullptr) {
return NO_ERROR;
}
@@ -368,40 +413,40 @@
memcpy(exif->data, jpeg_decoder.getEXIFPtr(), jpeg_decoder.getEXIFSize());
exif->length = jpeg_decoder.getEXIFSize();
}
- if (recovery_map == nullptr) {
+ if (gain_map == nullptr) {
return NO_ERROR;
}
}
jpegr_compressed_struct compressed_map;
- JPEGR_CHECK(extractRecoveryMap(compressed_jpegr_image, &compressed_map));
+ JPEGR_CHECK(extractGainMap(compressed_jpegr_image, &compressed_map));
- JpegDecoderHelper recovery_map_decoder;
- if (!recovery_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) {
+ JpegDecoderHelper gain_map_decoder;
+ if (!gain_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) {
return ERROR_JPEGR_DECODE_ERROR;
}
- if (recovery_map != nullptr) {
- recovery_map->width = recovery_map_decoder.getDecompressedImageWidth();
- recovery_map->height = recovery_map_decoder.getDecompressedImageHeight();
- int size = recovery_map->width * recovery_map->height;
- recovery_map->data = malloc(size);
- memcpy(recovery_map->data, recovery_map_decoder.getDecompressedImagePtr(), size);
+ if (gain_map != nullptr) {
+ gain_map->width = gain_map_decoder.getDecompressedImageWidth();
+ gain_map->height = gain_map_decoder.getDecompressedImageHeight();
+ int size = gain_map->width * gain_map->height;
+ gain_map->data = malloc(size);
+ memcpy(gain_map->data, gain_map_decoder.getDecompressedImagePtr(), size);
}
- jpegr_metadata_struct jr_metadata;
- if (!getMetadataFromXMP(static_cast<uint8_t*>(recovery_map_decoder.getXMPPtr()),
- recovery_map_decoder.getXMPSize(), &jr_metadata)) {
+ ultrahdr_metadata_struct uhdr_metadata;
+ if (!getMetadataFromXMP(static_cast<uint8_t*>(gain_map_decoder.getXMPPtr()),
+ gain_map_decoder.getXMPSize(), &uhdr_metadata)) {
return ERROR_JPEGR_DECODE_ERROR;
}
if (metadata != nullptr) {
- metadata->version = jr_metadata.version;
- metadata->minContentBoost = jr_metadata.minContentBoost;
- metadata->maxContentBoost = jr_metadata.maxContentBoost;
+ metadata->version = uhdr_metadata.version;
+ metadata->minContentBoost = uhdr_metadata.minContentBoost;
+ metadata->maxContentBoost = uhdr_metadata.maxContentBoost;
}
- if (output_format == JPEGR_OUTPUT_SDR) {
+ if (output_format == ULTRAHDR_OUTPUT_SDR) {
return NO_ERROR;
}
@@ -422,30 +467,30 @@
}
jpegr_uncompressed_struct map;
- map.data = recovery_map_decoder.getDecompressedImagePtr();
- map.width = recovery_map_decoder.getDecompressedImageWidth();
- map.height = recovery_map_decoder.getDecompressedImageHeight();
+ map.data = gain_map_decoder.getDecompressedImagePtr();
+ map.width = gain_map_decoder.getDecompressedImageWidth();
+ map.height = gain_map_decoder.getDecompressedImageHeight();
jpegr_uncompressed_struct uncompressed_yuv_420_image;
uncompressed_yuv_420_image.data = jpeg_decoder.getDecompressedImagePtr();
uncompressed_yuv_420_image.width = jpeg_decoder.getDecompressedImageWidth();
uncompressed_yuv_420_image.height = jpeg_decoder.getDecompressedImageHeight();
- JPEGR_CHECK(applyRecoveryMap(&uncompressed_yuv_420_image, &map, &jr_metadata, output_format,
- max_display_boost, dest));
+ JPEGR_CHECK(applyGainMap(&uncompressed_yuv_420_image, &map, &uhdr_metadata, output_format,
+ max_display_boost, dest));
return NO_ERROR;
}
-status_t JpegR::compressRecoveryMap(jr_uncompressed_ptr uncompressed_recovery_map,
- jr_compressed_ptr dest) {
- if (uncompressed_recovery_map == nullptr || dest == nullptr) {
+status_t JpegR::compressGainMap(jr_uncompressed_ptr uncompressed_gain_map,
+ jr_compressed_ptr dest) {
+ if (uncompressed_gain_map == nullptr || dest == nullptr) {
return ERROR_JPEGR_INVALID_NULL_PTR;
}
JpegEncoderHelper jpeg_encoder;
- if (!jpeg_encoder.compressImage(uncompressed_recovery_map->data,
- uncompressed_recovery_map->width,
- uncompressed_recovery_map->height,
+ if (!jpeg_encoder.compressImage(uncompressed_gain_map->data,
+ uncompressed_gain_map->width,
+ uncompressed_gain_map->height,
kMapCompressQuality,
nullptr,
0,
@@ -459,7 +504,7 @@
memcpy(dest->data, jpeg_encoder.getCompressedImagePtr(), jpeg_encoder.getCompressedImageSize());
dest->length = jpeg_encoder.getCompressedImageSize();
- dest->colorGamut = JPEGR_COLORGAMUT_UNSPECIFIED;
+ dest->colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED;
return NO_ERROR;
}
@@ -520,11 +565,11 @@
mQueuedAllJobs = false;
}
-status_t JpegR::generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
- jr_uncompressed_ptr uncompressed_p010_image,
- jpegr_transfer_function hdr_tf,
- jr_metadata_ptr metadata,
- jr_uncompressed_ptr dest) {
+status_t JpegR::generateGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
+ jr_uncompressed_ptr uncompressed_p010_image,
+ ultrahdr_transfer_function hdr_tf,
+ ultrahdr_metadata_ptr metadata,
+ jr_uncompressed_ptr dest) {
if (uncompressed_yuv_420_image == nullptr
|| uncompressed_p010_image == nullptr
|| metadata == nullptr
@@ -537,8 +582,8 @@
return ERROR_JPEGR_RESOLUTION_MISMATCH;
}
- if (uncompressed_yuv_420_image->colorGamut == JPEGR_COLORGAMUT_UNSPECIFIED
- || uncompressed_p010_image->colorGamut == JPEGR_COLORGAMUT_UNSPECIFIED) {
+ if (uncompressed_yuv_420_image->colorGamut == ULTRAHDR_COLORGAMUT_UNSPECIFIED
+ || uncompressed_p010_image->colorGamut == ULTRAHDR_COLORGAMUT_UNSPECIFIED) {
return ERROR_JPEGR_INVALID_COLORGAMUT;
}
@@ -552,7 +597,7 @@
dest->width = map_stride;
dest->height = map_height_aligned;
- dest->colorGamut = JPEGR_COLORGAMUT_UNSPECIFIED;
+ dest->colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED;
dest->data = new uint8_t[map_stride * map_height_aligned];
std::unique_ptr<uint8_t[]> map_data;
map_data.reset(reinterpret_cast<uint8_t*>(dest->data));
@@ -560,10 +605,10 @@
ColorTransformFn hdrInvOetf = nullptr;
float hdr_white_nits = 0.0f;
switch (hdr_tf) {
- case JPEGR_TF_LINEAR:
+ case ULTRAHDR_TF_LINEAR:
hdrInvOetf = identityConversion;
break;
- case JPEGR_TF_HLG:
+ case ULTRAHDR_TF_HLG:
#if USE_HLG_INVOETF_LUT
hdrInvOetf = hlgInvOetfLUT;
#else
@@ -571,7 +616,7 @@
#endif
hdr_white_nits = kHlgMaxNits;
break;
- case JPEGR_TF_PQ:
+ case ULTRAHDR_TF_PQ:
#if USE_PQ_INVOETF_LUT
hdrInvOetf = pqInvOetfLUT;
#else
@@ -586,22 +631,24 @@
metadata->maxContentBoost = hdr_white_nits / kSdrWhiteNits;
metadata->minContentBoost = 1.0f;
+ float log2MinBoost = log2(metadata->minContentBoost);
+ float log2MaxBoost = log2(metadata->maxContentBoost);
ColorTransformFn hdrGamutConversionFn = getHdrConversionFn(
uncompressed_yuv_420_image->colorGamut, uncompressed_p010_image->colorGamut);
ColorCalculationFn luminanceFn = nullptr;
switch (uncompressed_yuv_420_image->colorGamut) {
- case JPEGR_COLORGAMUT_BT709:
+ case ULTRAHDR_COLORGAMUT_BT709:
luminanceFn = srgbLuminance;
break;
- case JPEGR_COLORGAMUT_P3:
+ case ULTRAHDR_COLORGAMUT_P3:
luminanceFn = p3Luminance;
break;
- case JPEGR_COLORGAMUT_BT2100:
+ case ULTRAHDR_COLORGAMUT_BT2100:
luminanceFn = bt2100Luminance;
break;
- case JPEGR_COLORGAMUT_UNSPECIFIED:
+ case ULTRAHDR_COLORGAMUT_UNSPECIFIED:
// Should be impossible to hit after input validation.
return ERROR_JPEGR_INVALID_COLORGAMUT;
}
@@ -613,7 +660,8 @@
std::function<void()> generateMap = [uncompressed_yuv_420_image, uncompressed_p010_image,
metadata, dest, hdrInvOetf, hdrGamutConversionFn,
- luminanceFn, hdr_white_nits, &jobQueue]() -> void {
+ luminanceFn, hdr_white_nits, log2MinBoost, log2MaxBoost,
+ &jobQueue]() -> void {
size_t rowStart, rowEnd;
size_t dest_map_width = uncompressed_yuv_420_image->width / kMapDimensionScaleFactor;
size_t dest_map_stride = dest->width;
@@ -638,7 +686,7 @@
size_t pixel_idx = x + y * dest_map_stride;
reinterpret_cast<uint8_t*>(dest->data)[pixel_idx] =
- encodeRecovery(sdr_y_nits, hdr_y_nits, metadata);
+ encodeGain(sdr_y_nits, hdr_y_nits, metadata, log2MinBoost, log2MaxBoost);
}
}
}
@@ -664,14 +712,14 @@
return NO_ERROR;
}
-status_t JpegR::applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
- jr_uncompressed_ptr uncompressed_recovery_map,
- jr_metadata_ptr metadata,
- jpegr_output_format output_format,
- float max_display_boost,
- jr_uncompressed_ptr dest) {
+status_t JpegR::applyGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
+ jr_uncompressed_ptr uncompressed_gain_map,
+ ultrahdr_metadata_ptr metadata,
+ ultrahdr_output_format output_format,
+ float max_display_boost,
+ jr_uncompressed_ptr dest) {
if (uncompressed_yuv_420_image == nullptr
- || uncompressed_recovery_map == nullptr
+ || uncompressed_gain_map == nullptr
|| metadata == nullptr
|| dest == nullptr) {
return ERROR_JPEGR_INVALID_NULL_PTR;
@@ -680,15 +728,13 @@
dest->width = uncompressed_yuv_420_image->width;
dest->height = uncompressed_yuv_420_image->height;
ShepardsIDW idwTable(kMapDimensionScaleFactor);
- float display_boost = max_display_boost > 0 ?
- std::min(max_display_boost, metadata->maxContentBoost)
- : metadata->maxContentBoost;
- RecoveryLUT recoveryLUT(metadata, display_boost);
+ float display_boost = std::min(max_display_boost, metadata->maxContentBoost);
+ GainLUT gainLUT(metadata, display_boost);
JobQueue jobQueue;
- std::function<void()> applyRecMap = [uncompressed_yuv_420_image, uncompressed_recovery_map,
+ std::function<void()> applyRecMap = [uncompressed_yuv_420_image, uncompressed_gain_map,
metadata, dest, &jobQueue, &idwTable, output_format,
- &recoveryLUT, display_boost]() -> void {
+ &gainLUT, display_boost]() -> void {
size_t width = uncompressed_yuv_420_image->width;
size_t height = uncompressed_yuv_420_image->height;
@@ -703,34 +749,34 @@
#else
Color rgb_sdr = srgbInvOetf(rgb_gamma_sdr);
#endif
- float recovery;
+ float gain;
// TODO: determine map scaling factor based on actual map dims
size_t map_scale_factor = kMapDimensionScaleFactor;
// TODO: If map_scale_factor is guaranteed to be an integer, then remove the following.
// Currently map_scale_factor is of type size_t, but it could be changed to a float
// later.
if (map_scale_factor != floorf(map_scale_factor)) {
- recovery = sampleMap(uncompressed_recovery_map, map_scale_factor, x, y);
+ gain = sampleMap(uncompressed_gain_map, map_scale_factor, x, y);
} else {
- recovery = sampleMap(uncompressed_recovery_map, map_scale_factor, x, y, idwTable);
+ gain = sampleMap(uncompressed_gain_map, map_scale_factor, x, y, idwTable);
}
-#if USE_APPLY_RECOVERY_LUT
- Color rgb_hdr = applyRecoveryLUT(rgb_sdr, recovery, recoveryLUT);
+#if USE_APPLY_GAIN_LUT
+ Color rgb_hdr = applyGainLUT(rgb_sdr, gain, gainLUT);
#else
- Color rgb_hdr = applyRecovery(rgb_sdr, recovery, metadata, display_boost);
+ Color rgb_hdr = applyGain(rgb_sdr, gain, metadata, display_boost);
#endif
rgb_hdr = rgb_hdr / display_boost;
size_t pixel_idx = x + y * width;
switch (output_format) {
- case JPEGR_OUTPUT_HDR_LINEAR:
+ case ULTRAHDR_OUTPUT_HDR_LINEAR:
{
uint64_t rgba_f16 = colorToRgbaF16(rgb_hdr);
reinterpret_cast<uint64_t*>(dest->data)[pixel_idx] = rgba_f16;
break;
}
- case JPEGR_OUTPUT_HDR_HLG:
+ case ULTRAHDR_OUTPUT_HDR_HLG:
{
#if USE_HLG_OETF_LUT
ColorTransformFn hdrOetf = hlgOetfLUT;
@@ -742,7 +788,7 @@
reinterpret_cast<uint32_t*>(dest->data)[pixel_idx] = rgba_1010102;
break;
}
- case JPEGR_OUTPUT_HDR_PQ:
+ case ULTRAHDR_OUTPUT_HDR_PQ:
{
#if USE_HLG_OETF_LUT
ColorTransformFn hdrOetf = pqOetfLUT;
@@ -780,9 +826,9 @@
return NO_ERROR;
}
-status_t JpegR::extractPrimaryImageAndRecoveryMap(jr_compressed_ptr compressed_jpegr_image,
- jr_compressed_ptr primary_image,
- jr_compressed_ptr recovery_map) {
+status_t JpegR::extractPrimaryImageAndGainMap(jr_compressed_ptr compressed_jpegr_image,
+ jr_compressed_ptr primary_image,
+ jr_compressed_ptr gain_map) {
if (compressed_jpegr_image == nullptr) {
return ERROR_JPEGR_INVALID_NULL_PTR;
}
@@ -820,23 +866,23 @@
primary_image->length = image_ranges[0].GetLength();
}
- if (recovery_map != nullptr) {
- recovery_map->data = static_cast<uint8_t*>(compressed_jpegr_image->data) +
+ if (gain_map != nullptr) {
+ gain_map->data = static_cast<uint8_t*>(compressed_jpegr_image->data) +
image_ranges[1].GetBegin();
- recovery_map->length = image_ranges[1].GetLength();
+ gain_map->length = image_ranges[1].GetLength();
}
return NO_ERROR;
}
-status_t JpegR::extractRecoveryMap(jr_compressed_ptr compressed_jpegr_image,
- jr_compressed_ptr dest) {
+status_t JpegR::extractGainMap(jr_compressed_ptr compressed_jpegr_image,
+ jr_compressed_ptr dest) {
if (compressed_jpegr_image == nullptr || dest == nullptr) {
return ERROR_JPEGR_INVALID_NULL_PTR;
}
- return extractPrimaryImageAndRecoveryMap(compressed_jpegr_image, nullptr, dest);
+ return extractPrimaryImageAndGainMap(compressed_jpegr_image, nullptr, dest);
}
// JPEG/R structure:
@@ -865,20 +911,20 @@
// name space ("http://ns.adobe.com/xap/1.0/\0")
// XMP
//
-// (Required) secondary image (the recovery map, without the first two bytes (SOI))
+// (Required) secondary image (the gain map, without the first two bytes (SOI))
//
// Metadata versions we are using:
// ECMA TR-98 for JFIF marker
// Exif 2.2 spec for EXIF marker
// Adobe XMP spec part 3 for XMP marker
// ICC v4.3 spec for ICC
-status_t JpegR::appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image,
- jr_compressed_ptr compressed_recovery_map,
- jr_exif_ptr exif,
- jr_metadata_ptr metadata,
- jr_compressed_ptr dest) {
+status_t JpegR::appendGainMap(jr_compressed_ptr compressed_jpeg_image,
+ jr_compressed_ptr compressed_gain_map,
+ jr_exif_ptr exif,
+ ultrahdr_metadata_ptr metadata,
+ jr_compressed_ptr dest) {
if (compressed_jpeg_image == nullptr
- || compressed_recovery_map == nullptr
+ || compressed_gain_map == nullptr
|| metadata == nullptr
|| dest == nullptr) {
return ERROR_JPEGR_INVALID_NULL_PTR;
@@ -895,7 +941,7 @@
+ xmp_secondary.size(); /* length of xmp packet */
const int secondary_image_size = 2 /* 2 bytes length of APP1 sign */
+ xmp_secondary_length
- + compressed_recovery_map->length;
+ + compressed_gain_map->length;
// primary image
const string xmp_primary = generateXmpForPrimaryImage(secondary_image_size);
// same as primary
@@ -959,7 +1005,7 @@
(uint8_t*)compressed_jpeg_image->data + 2, compressed_jpeg_image->length - 2, pos));
// Finish primary image
- // Begin secondary image (recovery map)
+ // Begin secondary image (gain map)
// Write SOI
JPEGR_CHECK(Write(dest, &photos_editing_formats::image_io::JpegMarker::kStart, 1, pos));
JPEGR_CHECK(Write(dest, &photos_editing_formats::image_io::JpegMarker::kSOI, 1, pos));
@@ -979,7 +1025,7 @@
// Write secondary image
JPEGR_CHECK(Write(dest,
- (uint8_t*)compressed_recovery_map->data + 2, compressed_recovery_map->length - 2, pos));
+ (uint8_t*)compressed_gain_map->data + 2, compressed_gain_map->length - 2, pos));
// Set back length
dest->length = pos;
@@ -993,25 +1039,43 @@
return ERROR_JPEGR_INVALID_NULL_PTR;
}
+ size_t src_luma_stride = src->luma_stride;
+ size_t src_chroma_stride = src->chroma_stride;
+ uint16_t* src_luma_data = reinterpret_cast<uint16_t*>(src->data);
+ uint16_t* src_chroma_data = reinterpret_cast<uint16_t*>(src->chroma_data);
+
+ if (src_chroma_data == nullptr) {
+ src_chroma_data = &reinterpret_cast<uint16_t*>(src->data)[src_luma_stride * src->height];
+ }
+ if (src_luma_stride == 0) {
+ src_luma_stride = src->width;
+ }
+ if (src_chroma_stride == 0) {
+ src_chroma_stride = src_luma_stride;
+ }
+
dest->width = src->width;
dest->height = src->height;
- size_t pixel_count = src->width * src->height;
+ size_t dest_luma_pixel_count = dest->width * dest->height;
+
for (size_t y = 0; y < src->height; ++y) {
for (size_t x = 0; x < src->width; ++x) {
- size_t pixel_y_idx = x + y * src->width;
- size_t pixel_uv_idx = x / 2 + (y / 2) * (src->width / 2);
+ size_t src_y_idx = y * src_luma_stride + x;
+ size_t src_u_idx = (y >> 1) * src_chroma_stride + (x & ~0x1);
+ size_t src_v_idx = src_u_idx + 1;
- uint16_t y_uint = reinterpret_cast<uint16_t*>(src->data)[pixel_y_idx]
- >> 6;
- uint16_t u_uint = reinterpret_cast<uint16_t*>(src->data)[pixel_count + pixel_uv_idx * 2]
- >> 6;
- uint16_t v_uint = reinterpret_cast<uint16_t*>(src->data)[pixel_count + pixel_uv_idx * 2 + 1]
- >> 6;
+ uint16_t y_uint = src_luma_data[src_y_idx] >> 6;
+ uint16_t u_uint = src_chroma_data[src_u_idx] >> 6;
+ uint16_t v_uint = src_chroma_data[src_v_idx] >> 6;
- uint8_t* y = &reinterpret_cast<uint8_t*>(dest->data)[pixel_y_idx];
- uint8_t* u = &reinterpret_cast<uint8_t*>(dest->data)[pixel_count + pixel_uv_idx];
- uint8_t* v = &reinterpret_cast<uint8_t*>(dest->data)[pixel_count * 5 / 4 + pixel_uv_idx];
+ size_t dest_y_idx = x + y * dest->width;
+ size_t dest_uv_idx = x / 2 + (y / 2) * (dest->width / 2);
+
+ uint8_t* y = &reinterpret_cast<uint8_t*>(dest->data)[dest_y_idx];
+ uint8_t* u = &reinterpret_cast<uint8_t*>(dest->data)[dest_luma_pixel_count + dest_uv_idx];
+ uint8_t* v = &reinterpret_cast<uint8_t*>(
+ dest->data)[dest_luma_pixel_count * 5 / 4 + dest_uv_idx];
*y = static_cast<uint8_t>((y_uint >> 2) & 0xff);
*u = static_cast<uint8_t>((u_uint >> 2) & 0xff);
@@ -1024,4 +1088,4 @@
return NO_ERROR;
}
-} // namespace android::jpegrecoverymap
+} // namespace android::ultrahdr
diff --git a/libs/jpegrecoverymap/jpegrutils.cpp b/libs/ultrahdr/jpegrutils.cpp
similarity index 97%
rename from libs/jpegrecoverymap/jpegrutils.cpp
rename to libs/ultrahdr/jpegrutils.cpp
index cde0ceb..9d07a6f 100644
--- a/libs/jpegrecoverymap/jpegrutils.cpp
+++ b/libs/ultrahdr/jpegrutils.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <jpegrecoverymap/jpegrutils.h>
+#include <ultrahdr/jpegrutils.h>
#include <algorithm>
#include <cmath>
@@ -30,7 +30,7 @@
using namespace photos_editing_formats::image_io;
using namespace std;
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
/*
* Helper function used for generating XMP metadata.
*
@@ -256,7 +256,7 @@
const string XMPXmlHandler::minContentBoostAttrName = kMapGainMapMin;
const string XMPXmlHandler::maxContentBoostAttrName = kMapGainMapMax;
-bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata_struct* metadata) {
+bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, ultrahdr_metadata_struct* metadata) {
string nameSpace = "http://ns.adobe.com/xap/1.0/\0";
if (xmp_size < nameSpace.size()+2) {
@@ -338,7 +338,7 @@
return ss.str();
}
-string generateXmpForSecondaryImage(jpegr_metadata_struct& metadata) {
+string generateXmpForSecondaryImage(ultrahdr_metadata_struct& metadata) {
const vector<string> kConDirSeq({kConDirectory, string("rdf:Seq")});
std::stringstream ss;
@@ -365,4 +365,4 @@
return ss.str();
}
-} // namespace android::jpegrecoverymap
+} // namespace android::ultrahdr
diff --git a/libs/jpegrecoverymap/multipictureformat.cpp b/libs/ultrahdr/multipictureformat.cpp
similarity index 95%
rename from libs/jpegrecoverymap/multipictureformat.cpp
rename to libs/ultrahdr/multipictureformat.cpp
index a219aef..7a265c6 100644
--- a/libs/jpegrecoverymap/multipictureformat.cpp
+++ b/libs/ultrahdr/multipictureformat.cpp
@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <jpegrecoverymap/multipictureformat.h>
-#include <jpegrecoverymap/jpegrutils.h>
+#include <ultrahdr/multipictureformat.h>
+#include <ultrahdr/jpegrutils.h>
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
size_t calculateMpfSize() {
return sizeof(kMpfSig) + // Signature
kMpEndianSize + // Endianness
@@ -91,4 +91,4 @@
return dataStruct;
}
-} // namespace android::jpegrecoverymap
+} // namespace android::ultrahdr
diff --git a/libs/jpegrecoverymap/tests/Android.bp b/libs/ultrahdr/tests/Android.bp
similarity index 94%
rename from libs/jpegrecoverymap/tests/Android.bp
rename to libs/ultrahdr/tests/Android.bp
index d5da7fb..7dd9d04 100644
--- a/libs/jpegrecoverymap/tests/Android.bp
+++ b/libs/ultrahdr/tests/Android.bp
@@ -22,11 +22,11 @@
}
cc_test {
- name: "libjpegrecoverymap_test",
+ name: "libultrahdr_test",
test_suites: ["device-tests"],
srcs: [
"jpegr_test.cpp",
- "recoverymapmath_test.cpp",
+ "gainmapmath_test.cpp",
],
shared_libs: [
"libimage_io",
@@ -38,7 +38,7 @@
"libgtest",
"libjpegdecoder",
"libjpegencoder",
- "libjpegrecoverymap",
+ "libultrahdr",
"libutils",
],
}
diff --git a/libs/jpegrecoverymap/tests/data/jpeg_image.jpg b/libs/ultrahdr/tests/data/jpeg_image.jpg
similarity index 100%
rename from libs/jpegrecoverymap/tests/data/jpeg_image.jpg
rename to libs/ultrahdr/tests/data/jpeg_image.jpg
Binary files differ
diff --git a/libs/jpegrecoverymap/tests/data/minnie-318x240.yu12 b/libs/ultrahdr/tests/data/minnie-318x240.yu12
similarity index 100%
rename from libs/jpegrecoverymap/tests/data/minnie-318x240.yu12
rename to libs/ultrahdr/tests/data/minnie-318x240.yu12
Binary files differ
diff --git a/libs/jpegrecoverymap/tests/data/minnie-320x240-y.jpg b/libs/ultrahdr/tests/data/minnie-320x240-y.jpg
similarity index 100%
rename from libs/jpegrecoverymap/tests/data/minnie-320x240-y.jpg
rename to libs/ultrahdr/tests/data/minnie-320x240-y.jpg
Binary files differ
diff --git a/libs/jpegrecoverymap/tests/data/minnie-320x240-yuv.jpg b/libs/ultrahdr/tests/data/minnie-320x240-yuv.jpg
similarity index 100%
rename from libs/jpegrecoverymap/tests/data/minnie-320x240-yuv.jpg
rename to libs/ultrahdr/tests/data/minnie-320x240-yuv.jpg
Binary files differ
diff --git a/libs/jpegrecoverymap/tests/data/minnie-320x240.y b/libs/ultrahdr/tests/data/minnie-320x240.y
similarity index 100%
rename from libs/jpegrecoverymap/tests/data/minnie-320x240.y
rename to libs/ultrahdr/tests/data/minnie-320x240.y
Binary files differ
diff --git a/libs/jpegrecoverymap/tests/data/minnie-320x240.yu12 b/libs/ultrahdr/tests/data/minnie-320x240.yu12
similarity index 100%
rename from libs/jpegrecoverymap/tests/data/minnie-320x240.yu12
rename to libs/ultrahdr/tests/data/minnie-320x240.yu12
Binary files differ
diff --git a/libs/jpegrecoverymap/tests/data/raw_p010_image.p010 b/libs/ultrahdr/tests/data/raw_p010_image.p010
similarity index 100%
rename from libs/jpegrecoverymap/tests/data/raw_p010_image.p010
rename to libs/ultrahdr/tests/data/raw_p010_image.p010
Binary files differ
diff --git a/libs/ultrahdr/tests/data/raw_p010_image_with_stride.p010 b/libs/ultrahdr/tests/data/raw_p010_image_with_stride.p010
new file mode 100644
index 0000000..e7a5dc8
--- /dev/null
+++ b/libs/ultrahdr/tests/data/raw_p010_image_with_stride.p010
Binary files differ
diff --git a/libs/jpegrecoverymap/tests/data/raw_yuv420_image.yuv420 b/libs/ultrahdr/tests/data/raw_yuv420_image.yuv420
similarity index 100%
rename from libs/jpegrecoverymap/tests/data/raw_yuv420_image.yuv420
rename to libs/ultrahdr/tests/data/raw_yuv420_image.yuv420
Binary files differ
diff --git a/libs/jpegrecoverymap/tests/recoverymapmath_test.cpp b/libs/ultrahdr/tests/gainmapmath_test.cpp
similarity index 66%
rename from libs/jpegrecoverymap/tests/recoverymapmath_test.cpp
rename to libs/ultrahdr/tests/gainmapmath_test.cpp
index 5ef79e9..c456653 100644
--- a/libs/jpegrecoverymap/tests/recoverymapmath_test.cpp
+++ b/libs/ultrahdr/tests/gainmapmath_test.cpp
@@ -17,14 +17,14 @@
#include <cmath>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
-#include <jpegrecoverymap/recoverymapmath.h>
+#include <ultrahdr/gainmapmath.h>
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
-class RecoveryMapMathTest : public testing::Test {
+class GainMapMathTest : public testing::Test {
public:
- RecoveryMapMathTest();
- ~RecoveryMapMathTest();
+ GainMapMathTest();
+ ~GainMapMathTest();
float ComparisonEpsilon() { return 1e-4f; }
float LuminanceEpsilon() { return 1e-2f; }
@@ -88,10 +88,10 @@
return luminance_scaled * scale_factor;
}
- Color Recover(Color yuv_gamma, float recovery, jr_metadata_ptr metadata) {
+ Color Recover(Color yuv_gamma, float gain, ultrahdr_metadata_ptr metadata) {
Color rgb_gamma = srgbYuvToRgb(yuv_gamma);
Color rgb = srgbInvOetf(rgb_gamma);
- return applyRecovery(rgb, recovery, metadata);
+ return applyGain(rgb, gain, metadata);
}
jpegr_uncompressed_struct Yuv420Image() {
@@ -108,7 +108,7 @@
0xB0, 0xB1,
0xB2, 0xB3,
};
- return { pixels, 4, 4, JPEGR_COLORGAMUT_BT709 };
+ return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_BT709 };
}
Color (*Yuv420Colors())[4] {
@@ -141,7 +141,7 @@
0xA0 << 6, 0xB0 << 6, 0xA1 << 6, 0xB1 << 6,
0xA2 << 6, 0xB2 << 6, 0xA3 << 6, 0xB3 << 6,
};
- return { pixels, 4, 4, JPEGR_COLORGAMUT_BT709 };
+ return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_BT709 };
}
Color (*P010Colors())[4] {
@@ -170,7 +170,7 @@
0x02, 0x12, 0x22, 0x32,
0x03, 0x13, 0x23, 0x33,
};
- return { pixels, 4, 4, JPEGR_COLORGAMUT_UNSPECIFIED };
+ return { pixels, 4, 4, ULTRAHDR_COLORGAMUT_UNSPECIFIED };
}
float (*MapValues())[4] {
@@ -193,11 +193,11 @@
virtual void TearDown();
};
-RecoveryMapMathTest::RecoveryMapMathTest() {}
-RecoveryMapMathTest::~RecoveryMapMathTest() {}
+GainMapMathTest::GainMapMathTest() {}
+GainMapMathTest::~GainMapMathTest() {}
-void RecoveryMapMathTest::SetUp() {}
-void RecoveryMapMathTest::TearDown() {}
+void GainMapMathTest::SetUp() {}
+void GainMapMathTest::TearDown() {}
#define EXPECT_RGB_EQ(e1, e2) \
EXPECT_FLOAT_EQ((e1).r, (e2).r); \
@@ -231,7 +231,7 @@
// TODO: a bunch of these tests can be parameterized.
-TEST_F(RecoveryMapMathTest, ColorConstruct) {
+TEST_F(GainMapMathTest, ColorConstruct) {
Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
EXPECT_FLOAT_EQ(e1.r, 0.1f);
@@ -243,7 +243,7 @@
EXPECT_FLOAT_EQ(e1.v, 0.3f);
}
-TEST_F(RecoveryMapMathTest, ColorAddColor) {
+TEST_F(GainMapMathTest, ColorAddColor) {
Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
Color e2 = e1 + e1;
@@ -257,7 +257,7 @@
EXPECT_FLOAT_EQ(e2.b, e1.b * 3.0f);
}
-TEST_F(RecoveryMapMathTest, ColorAddFloat) {
+TEST_F(GainMapMathTest, ColorAddFloat) {
Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
Color e2 = e1 + 0.1f;
@@ -271,7 +271,7 @@
EXPECT_FLOAT_EQ(e2.b, e1.b + 0.2f);
}
-TEST_F(RecoveryMapMathTest, ColorSubtractColor) {
+TEST_F(GainMapMathTest, ColorSubtractColor) {
Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
Color e2 = e1 - e1;
@@ -285,7 +285,7 @@
EXPECT_FLOAT_EQ(e2.b, -e1.b);
}
-TEST_F(RecoveryMapMathTest, ColorSubtractFloat) {
+TEST_F(GainMapMathTest, ColorSubtractFloat) {
Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
Color e2 = e1 - 0.1f;
@@ -299,7 +299,7 @@
EXPECT_FLOAT_EQ(e2.b, e1.b - 0.2f);
}
-TEST_F(RecoveryMapMathTest, ColorMultiplyFloat) {
+TEST_F(GainMapMathTest, ColorMultiplyFloat) {
Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
Color e2 = e1 * 2.0f;
@@ -313,7 +313,7 @@
EXPECT_FLOAT_EQ(e2.b, e1.b * 4.0f);
}
-TEST_F(RecoveryMapMathTest, ColorDivideFloat) {
+TEST_F(GainMapMathTest, ColorDivideFloat) {
Color e1 = {{{ 0.1f, 0.2f, 0.3f }}};
Color e2 = e1 / 2.0f;
@@ -327,7 +327,7 @@
EXPECT_FLOAT_EQ(e2.b, e1.b / 4.0f);
}
-TEST_F(RecoveryMapMathTest, SrgbLuminance) {
+TEST_F(GainMapMathTest, SrgbLuminance) {
EXPECT_FLOAT_EQ(srgbLuminance(RgbBlack()), 0.0f);
EXPECT_FLOAT_EQ(srgbLuminance(RgbWhite()), 1.0f);
EXPECT_FLOAT_EQ(srgbLuminance(RgbRed()), 0.2126f);
@@ -335,7 +335,7 @@
EXPECT_FLOAT_EQ(srgbLuminance(RgbBlue()), 0.0722f);
}
-TEST_F(RecoveryMapMathTest, SrgbYuvToRgb) {
+TEST_F(GainMapMathTest, SrgbYuvToRgb) {
Color rgb_black = srgbYuvToRgb(YuvBlack());
EXPECT_RGB_NEAR(rgb_black, RgbBlack());
@@ -352,7 +352,7 @@
EXPECT_RGB_NEAR(rgb_b, RgbBlue());
}
-TEST_F(RecoveryMapMathTest, SrgbRgbToYuv) {
+TEST_F(GainMapMathTest, SrgbRgbToYuv) {
Color yuv_black = srgbRgbToYuv(RgbBlack());
EXPECT_YUV_NEAR(yuv_black, YuvBlack());
@@ -369,7 +369,7 @@
EXPECT_YUV_NEAR(yuv_b, SrgbYuvBlue());
}
-TEST_F(RecoveryMapMathTest, SrgbRgbYuvRoundtrip) {
+TEST_F(GainMapMathTest, SrgbRgbYuvRoundtrip) {
Color rgb_black = srgbYuvToRgb(srgbRgbToYuv(RgbBlack()));
EXPECT_RGB_NEAR(rgb_black, RgbBlack());
@@ -386,7 +386,7 @@
EXPECT_RGB_NEAR(rgb_b, RgbBlue());
}
-TEST_F(RecoveryMapMathTest, SrgbTransferFunction) {
+TEST_F(GainMapMathTest, SrgbTransferFunction) {
EXPECT_FLOAT_EQ(srgbInvOetf(0.0f), 0.0f);
EXPECT_NEAR(srgbInvOetf(0.02f), 0.00154f, ComparisonEpsilon());
EXPECT_NEAR(srgbInvOetf(0.04045f), 0.00313f, ComparisonEpsilon());
@@ -394,7 +394,7 @@
EXPECT_FLOAT_EQ(srgbInvOetf(1.0f), 1.0f);
}
-TEST_F(RecoveryMapMathTest, P3Luminance) {
+TEST_F(GainMapMathTest, P3Luminance) {
EXPECT_FLOAT_EQ(p3Luminance(RgbBlack()), 0.0f);
EXPECT_FLOAT_EQ(p3Luminance(RgbWhite()), 1.0f);
EXPECT_FLOAT_EQ(p3Luminance(RgbRed()), 0.20949f);
@@ -402,7 +402,7 @@
EXPECT_FLOAT_EQ(p3Luminance(RgbBlue()), 0.06891f);
}
-TEST_F(RecoveryMapMathTest, Bt2100Luminance) {
+TEST_F(GainMapMathTest, Bt2100Luminance) {
EXPECT_FLOAT_EQ(bt2100Luminance(RgbBlack()), 0.0f);
EXPECT_FLOAT_EQ(bt2100Luminance(RgbWhite()), 1.0f);
EXPECT_FLOAT_EQ(bt2100Luminance(RgbRed()), 0.2627f);
@@ -410,7 +410,7 @@
EXPECT_FLOAT_EQ(bt2100Luminance(RgbBlue()), 0.0593f);
}
-TEST_F(RecoveryMapMathTest, Bt2100YuvToRgb) {
+TEST_F(GainMapMathTest, Bt2100YuvToRgb) {
Color rgb_black = bt2100YuvToRgb(YuvBlack());
EXPECT_RGB_NEAR(rgb_black, RgbBlack());
@@ -427,7 +427,7 @@
EXPECT_RGB_NEAR(rgb_b, RgbBlue());
}
-TEST_F(RecoveryMapMathTest, Bt2100RgbToYuv) {
+TEST_F(GainMapMathTest, Bt2100RgbToYuv) {
Color yuv_black = bt2100RgbToYuv(RgbBlack());
EXPECT_YUV_NEAR(yuv_black, YuvBlack());
@@ -444,7 +444,7 @@
EXPECT_YUV_NEAR(yuv_b, Bt2100YuvBlue());
}
-TEST_F(RecoveryMapMathTest, Bt2100RgbYuvRoundtrip) {
+TEST_F(GainMapMathTest, Bt2100RgbYuvRoundtrip) {
Color rgb_black = bt2100YuvToRgb(bt2100RgbToYuv(RgbBlack()));
EXPECT_RGB_NEAR(rgb_black, RgbBlack());
@@ -461,7 +461,7 @@
EXPECT_RGB_NEAR(rgb_b, RgbBlue());
}
-TEST_F(RecoveryMapMathTest, HlgOetf) {
+TEST_F(GainMapMathTest, HlgOetf) {
EXPECT_FLOAT_EQ(hlgOetf(0.0f), 0.0f);
EXPECT_NEAR(hlgOetf(0.04167f), 0.35357f, ComparisonEpsilon());
EXPECT_NEAR(hlgOetf(0.08333f), 0.5f, ComparisonEpsilon());
@@ -473,7 +473,7 @@
EXPECT_RGB_NEAR(hlgOetf(e), e_gamma);
}
-TEST_F(RecoveryMapMathTest, HlgInvOetf) {
+TEST_F(GainMapMathTest, HlgInvOetf) {
EXPECT_FLOAT_EQ(hlgInvOetf(0.0f), 0.0f);
EXPECT_NEAR(hlgInvOetf(0.25f), 0.02083f, ComparisonEpsilon());
EXPECT_NEAR(hlgInvOetf(0.5f), 0.08333f, ComparisonEpsilon());
@@ -485,7 +485,7 @@
EXPECT_RGB_NEAR(hlgInvOetf(e_gamma), e);
}
-TEST_F(RecoveryMapMathTest, HlgTransferFunctionRoundtrip) {
+TEST_F(GainMapMathTest, HlgTransferFunctionRoundtrip) {
EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(0.0f)), 0.0f);
EXPECT_NEAR(hlgInvOetf(hlgOetf(0.04167f)), 0.04167f, ComparisonEpsilon());
EXPECT_NEAR(hlgInvOetf(hlgOetf(0.08333f)), 0.08333f, ComparisonEpsilon());
@@ -493,7 +493,7 @@
EXPECT_FLOAT_EQ(hlgInvOetf(hlgOetf(1.0f)), 1.0f);
}
-TEST_F(RecoveryMapMathTest, PqOetf) {
+TEST_F(GainMapMathTest, PqOetf) {
EXPECT_FLOAT_EQ(pqOetf(0.0f), 0.0f);
EXPECT_NEAR(pqOetf(0.01f), 0.50808f, ComparisonEpsilon());
EXPECT_NEAR(pqOetf(0.5f), 0.92655f, ComparisonEpsilon());
@@ -505,7 +505,7 @@
EXPECT_RGB_NEAR(pqOetf(e), e_gamma);
}
-TEST_F(RecoveryMapMathTest, PqInvOetf) {
+TEST_F(GainMapMathTest, PqInvOetf) {
EXPECT_FLOAT_EQ(pqInvOetf(0.0f), 0.0f);
EXPECT_NEAR(pqInvOetf(0.01f), 2.31017e-7f, ComparisonEpsilon());
EXPECT_NEAR(pqInvOetf(0.5f), 0.00922f, ComparisonEpsilon());
@@ -517,135 +517,135 @@
EXPECT_RGB_NEAR(pqInvOetf(e_gamma), e);
}
-TEST_F(RecoveryMapMathTest, PqInvOetfLUT) {
+TEST_F(GainMapMathTest, PqInvOetfLUT) {
for (int idx = 0; idx < kPqInvOETFNumEntries; idx++) {
float value = static_cast<float>(idx) / static_cast<float>(kPqInvOETFNumEntries - 1);
EXPECT_FLOAT_EQ(pqInvOetf(value), pqInvOetfLUT(value));
}
}
-TEST_F(RecoveryMapMathTest, HlgInvOetfLUT) {
+TEST_F(GainMapMathTest, HlgInvOetfLUT) {
for (int idx = 0; idx < kHlgInvOETFNumEntries; idx++) {
float value = static_cast<float>(idx) / static_cast<float>(kHlgInvOETFNumEntries - 1);
EXPECT_FLOAT_EQ(hlgInvOetf(value), hlgInvOetfLUT(value));
}
}
-TEST_F(RecoveryMapMathTest, pqOetfLUT) {
+TEST_F(GainMapMathTest, pqOetfLUT) {
for (int idx = 0; idx < kPqOETFNumEntries; idx++) {
float value = static_cast<float>(idx) / static_cast<float>(kPqOETFNumEntries - 1);
EXPECT_FLOAT_EQ(pqOetf(value), pqOetfLUT(value));
}
}
-TEST_F(RecoveryMapMathTest, hlgOetfLUT) {
+TEST_F(GainMapMathTest, hlgOetfLUT) {
for (int idx = 0; idx < kHlgOETFNumEntries; idx++) {
float value = static_cast<float>(idx) / static_cast<float>(kHlgOETFNumEntries - 1);
EXPECT_FLOAT_EQ(hlgOetf(value), hlgOetfLUT(value));
}
}
-TEST_F(RecoveryMapMathTest, srgbInvOetfLUT) {
+TEST_F(GainMapMathTest, srgbInvOetfLUT) {
for (int idx = 0; idx < kSrgbInvOETFNumEntries; idx++) {
float value = static_cast<float>(idx) / static_cast<float>(kSrgbInvOETFNumEntries - 1);
EXPECT_FLOAT_EQ(srgbInvOetf(value), srgbInvOetfLUT(value));
}
}
-TEST_F(RecoveryMapMathTest, applyRecoveryLUT) {
+TEST_F(GainMapMathTest, applyGainLUT) {
for (int boost = 1; boost <= 10; boost++) {
- jpegr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
+ ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
.minContentBoost = 1.0f / static_cast<float>(boost) };
- RecoveryLUT recoveryLUT(&metadata);
- RecoveryLUT recoveryLUTWithBoost(&metadata, metadata.maxContentBoost);
- for (int idx = 0; idx < kRecoveryFactorNumEntries; idx++) {
- float value = static_cast<float>(idx) / static_cast<float>(kRecoveryFactorNumEntries - 1);
- EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), value, &metadata),
- applyRecoveryLUT(RgbBlack(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), value, &metadata),
- applyRecoveryLUT(RgbWhite(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbRed(), value, &metadata),
- applyRecoveryLUT(RgbRed(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbGreen(), value, &metadata),
- applyRecoveryLUT(RgbGreen(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbBlue(), value, &metadata),
- applyRecoveryLUT(RgbBlue(), value, recoveryLUT));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlack(), value, recoveryLUT),
- applyRecoveryLUT(RgbBlack(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbWhite(), value, recoveryLUT),
- applyRecoveryLUT(RgbWhite(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbRed(), value, recoveryLUT),
- applyRecoveryLUT(RgbRed(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbGreen(), value, recoveryLUT),
- applyRecoveryLUT(RgbGreen(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlue(), value, recoveryLUT),
- applyRecoveryLUT(RgbBlue(), value, recoveryLUTWithBoost));
+ GainLUT gainLUT(&metadata);
+ GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
+ for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
+ float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
+ EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
+ applyGainLUT(RgbBlack(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
+ applyGainLUT(RgbWhite(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
+ applyGainLUT(RgbRed(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
+ applyGainLUT(RgbGreen(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
+ applyGainLUT(RgbBlue(), value, gainLUT));
+ EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
+ applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
+ applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
+ applyGainLUT(RgbRed(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
+ applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
+ applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
}
}
for (int boost = 1; boost <= 10; boost++) {
- jpegr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
+ ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
.minContentBoost = 1.0f };
- RecoveryLUT recoveryLUT(&metadata);
- RecoveryLUT recoveryLUTWithBoost(&metadata, metadata.maxContentBoost);
- for (int idx = 0; idx < kRecoveryFactorNumEntries; idx++) {
- float value = static_cast<float>(idx) / static_cast<float>(kRecoveryFactorNumEntries - 1);
- EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), value, &metadata),
- applyRecoveryLUT(RgbBlack(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), value, &metadata),
- applyRecoveryLUT(RgbWhite(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbRed(), value, &metadata),
- applyRecoveryLUT(RgbRed(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbGreen(), value, &metadata),
- applyRecoveryLUT(RgbGreen(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbBlue(), value, &metadata),
- applyRecoveryLUT(RgbBlue(), value, recoveryLUT));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlack(), value, recoveryLUT),
- applyRecoveryLUT(RgbBlack(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbWhite(), value, recoveryLUT),
- applyRecoveryLUT(RgbWhite(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbRed(), value, recoveryLUT),
- applyRecoveryLUT(RgbRed(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbGreen(), value, recoveryLUT),
- applyRecoveryLUT(RgbGreen(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlue(), value, recoveryLUT),
- applyRecoveryLUT(RgbBlue(), value, recoveryLUTWithBoost));
+ GainLUT gainLUT(&metadata);
+ GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
+ for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
+ float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
+ EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
+ applyGainLUT(RgbBlack(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
+ applyGainLUT(RgbWhite(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
+ applyGainLUT(RgbRed(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
+ applyGainLUT(RgbGreen(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
+ applyGainLUT(RgbBlue(), value, gainLUT));
+ EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
+ applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
+ applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
+ applyGainLUT(RgbRed(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
+ applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
+ applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
}
}
for (int boost = 1; boost <= 10; boost++) {
- jpegr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
+ ultrahdr_metadata_struct metadata = { .maxContentBoost = static_cast<float>(boost),
.minContentBoost = 1.0f / pow(static_cast<float>(boost),
1.0f / 3.0f) };
- RecoveryLUT recoveryLUT(&metadata);
- RecoveryLUT recoveryLUTWithBoost(&metadata, metadata.maxContentBoost);
- for (int idx = 0; idx < kRecoveryFactorNumEntries; idx++) {
- float value = static_cast<float>(idx) / static_cast<float>(kRecoveryFactorNumEntries - 1);
- EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), value, &metadata),
- applyRecoveryLUT(RgbBlack(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), value, &metadata),
- applyRecoveryLUT(RgbWhite(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbRed(), value, &metadata),
- applyRecoveryLUT(RgbRed(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbGreen(), value, &metadata),
- applyRecoveryLUT(RgbGreen(), value, recoveryLUT));
- EXPECT_RGB_NEAR(applyRecovery(RgbBlue(), value, &metadata),
- applyRecoveryLUT(RgbBlue(), value, recoveryLUT));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlack(), value, recoveryLUT),
- applyRecoveryLUT(RgbBlack(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbWhite(), value, recoveryLUT),
- applyRecoveryLUT(RgbWhite(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbRed(), value, recoveryLUT),
- applyRecoveryLUT(RgbRed(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbGreen(), value, recoveryLUT),
- applyRecoveryLUT(RgbGreen(), value, recoveryLUTWithBoost));
- EXPECT_RGB_EQ(applyRecoveryLUT(RgbBlue(), value, recoveryLUT),
- applyRecoveryLUT(RgbBlue(), value, recoveryLUTWithBoost));
+ GainLUT gainLUT(&metadata);
+ GainLUT gainLUTWithBoost(&metadata, metadata.maxContentBoost);
+ for (int idx = 0; idx < kGainFactorNumEntries; idx++) {
+ float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
+ EXPECT_RGB_NEAR(applyGain(RgbBlack(), value, &metadata),
+ applyGainLUT(RgbBlack(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), value, &metadata),
+ applyGainLUT(RgbWhite(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbRed(), value, &metadata),
+ applyGainLUT(RgbRed(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbGreen(), value, &metadata),
+ applyGainLUT(RgbGreen(), value, gainLUT));
+ EXPECT_RGB_NEAR(applyGain(RgbBlue(), value, &metadata),
+ applyGainLUT(RgbBlue(), value, gainLUT));
+ EXPECT_RGB_EQ(applyGainLUT(RgbBlack(), value, gainLUT),
+ applyGainLUT(RgbBlack(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbWhite(), value, gainLUT),
+ applyGainLUT(RgbWhite(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbRed(), value, gainLUT),
+ applyGainLUT(RgbRed(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbGreen(), value, gainLUT),
+ applyGainLUT(RgbGreen(), value, gainLUTWithBoost));
+ EXPECT_RGB_EQ(applyGainLUT(RgbBlue(), value, gainLUT),
+ applyGainLUT(RgbBlue(), value, gainLUTWithBoost));
}
}
}
-TEST_F(RecoveryMapMathTest, PqTransferFunctionRoundtrip) {
+TEST_F(GainMapMathTest, PqTransferFunctionRoundtrip) {
EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(0.0f)), 0.0f);
EXPECT_NEAR(pqInvOetf(pqOetf(0.01f)), 0.01f, ComparisonEpsilon());
EXPECT_NEAR(pqInvOetf(pqOetf(0.5f)), 0.5f, ComparisonEpsilon());
@@ -653,177 +653,177 @@
EXPECT_FLOAT_EQ(pqInvOetf(pqOetf(1.0f)), 1.0f);
}
-TEST_F(RecoveryMapMathTest, ColorConversionLookup) {
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_UNSPECIFIED),
+TEST_F(GainMapMathTest, ColorConversionLookup) {
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
nullptr);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_BT709),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_BT709),
identityConversion);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_P3),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3),
p3ToBt709);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT709, JPEGR_COLORGAMUT_BT2100),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_BT2100),
bt2100ToBt709);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_UNSPECIFIED),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
nullptr);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_BT709),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT709),
bt709ToP3);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_P3),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_P3),
identityConversion);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_P3, JPEGR_COLORGAMUT_BT2100),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100),
bt2100ToP3);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_UNSPECIFIED),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
nullptr);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_BT709),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_BT709),
bt709ToBt2100);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_P3),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_P3),
p3ToBt2100);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_BT2100, JPEGR_COLORGAMUT_BT2100),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_BT2100, ULTRAHDR_COLORGAMUT_BT2100),
identityConversion);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_UNSPECIFIED),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_UNSPECIFIED),
nullptr);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_BT709),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_BT709),
nullptr);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_P3),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_P3),
nullptr);
- EXPECT_EQ(getHdrConversionFn(JPEGR_COLORGAMUT_UNSPECIFIED, JPEGR_COLORGAMUT_BT2100),
+ EXPECT_EQ(getHdrConversionFn(ULTRAHDR_COLORGAMUT_UNSPECIFIED, ULTRAHDR_COLORGAMUT_BT2100),
nullptr);
}
-TEST_F(RecoveryMapMathTest, EncodeRecovery) {
- jpegr_metadata_struct metadata = { .maxContentBoost = 4.0f,
+TEST_F(GainMapMathTest, EncodeGain) {
+ ultrahdr_metadata_struct metadata = { .maxContentBoost = 4.0f,
.minContentBoost = 1.0f / 4.0f };
- EXPECT_EQ(encodeRecovery(0.0f, 0.0f, &metadata), 127);
- EXPECT_EQ(encodeRecovery(0.0f, 1.0f, &metadata), 127);
- EXPECT_EQ(encodeRecovery(1.0f, 0.0f, &metadata), 0);
- EXPECT_EQ(encodeRecovery(0.5f, 0.0f, &metadata), 0);
+ EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 127);
+ EXPECT_EQ(encodeGain(0.0f, 1.0f, &metadata), 127);
+ EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
+ EXPECT_EQ(encodeGain(0.5f, 0.0f, &metadata), 0);
- EXPECT_EQ(encodeRecovery(1.0f, 1.0f, &metadata), 127);
- EXPECT_EQ(encodeRecovery(1.0f, 4.0f, &metadata), 255);
- EXPECT_EQ(encodeRecovery(1.0f, 5.0f, &metadata), 255);
- EXPECT_EQ(encodeRecovery(4.0f, 1.0f, &metadata), 0);
- EXPECT_EQ(encodeRecovery(4.0f, 0.5f, &metadata), 0);
- EXPECT_EQ(encodeRecovery(1.0f, 2.0f, &metadata), 191);
- EXPECT_EQ(encodeRecovery(2.0f, 1.0f, &metadata), 63);
+ EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 127);
+ EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 255);
+ EXPECT_EQ(encodeGain(1.0f, 5.0f, &metadata), 255);
+ EXPECT_EQ(encodeGain(4.0f, 1.0f, &metadata), 0);
+ EXPECT_EQ(encodeGain(4.0f, 0.5f, &metadata), 0);
+ EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 191);
+ EXPECT_EQ(encodeGain(2.0f, 1.0f, &metadata), 63);
metadata.maxContentBoost = 2.0f;
metadata.minContentBoost = 1.0f / 2.0f;
- EXPECT_EQ(encodeRecovery(1.0f, 2.0f, &metadata), 255);
- EXPECT_EQ(encodeRecovery(2.0f, 1.0f, &metadata), 0);
- EXPECT_EQ(encodeRecovery(1.0f, 1.41421f, &metadata), 191);
- EXPECT_EQ(encodeRecovery(1.41421f, 1.0f, &metadata), 63);
+ EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 255);
+ EXPECT_EQ(encodeGain(2.0f, 1.0f, &metadata), 0);
+ EXPECT_EQ(encodeGain(1.0f, 1.41421f, &metadata), 191);
+ EXPECT_EQ(encodeGain(1.41421f, 1.0f, &metadata), 63);
metadata.maxContentBoost = 8.0f;
metadata.minContentBoost = 1.0f / 8.0f;
- EXPECT_EQ(encodeRecovery(1.0f, 8.0f, &metadata), 255);
- EXPECT_EQ(encodeRecovery(8.0f, 1.0f, &metadata), 0);
- EXPECT_EQ(encodeRecovery(1.0f, 2.82843f, &metadata), 191);
- EXPECT_EQ(encodeRecovery(2.82843f, 1.0f, &metadata), 63);
+ EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
+ EXPECT_EQ(encodeGain(8.0f, 1.0f, &metadata), 0);
+ EXPECT_EQ(encodeGain(1.0f, 2.82843f, &metadata), 191);
+ EXPECT_EQ(encodeGain(2.82843f, 1.0f, &metadata), 63);
metadata.maxContentBoost = 8.0f;
metadata.minContentBoost = 1.0f;
- EXPECT_EQ(encodeRecovery(0.0f, 0.0f, &metadata), 0);
- EXPECT_EQ(encodeRecovery(1.0f, 0.0f, &metadata), 0);
+ EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 0);
+ EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
- EXPECT_EQ(encodeRecovery(1.0f, 1.0f, &metadata), 0);
- EXPECT_EQ(encodeRecovery(1.0f, 8.0f, &metadata), 255);
- EXPECT_EQ(encodeRecovery(1.0f, 4.0f, &metadata), 170);
- EXPECT_EQ(encodeRecovery(1.0f, 2.0f, &metadata), 85);
+ EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 0);
+ EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
+ EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 170);
+ EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 85);
metadata.maxContentBoost = 8.0f;
metadata.minContentBoost = 0.5f;
- EXPECT_EQ(encodeRecovery(0.0f, 0.0f, &metadata), 63);
- EXPECT_EQ(encodeRecovery(1.0f, 0.0f, &metadata), 0);
+ EXPECT_EQ(encodeGain(0.0f, 0.0f, &metadata), 63);
+ EXPECT_EQ(encodeGain(1.0f, 0.0f, &metadata), 0);
- EXPECT_EQ(encodeRecovery(1.0f, 1.0f, &metadata), 63);
- EXPECT_EQ(encodeRecovery(1.0f, 8.0f, &metadata), 255);
- EXPECT_EQ(encodeRecovery(1.0f, 4.0f, &metadata), 191);
- EXPECT_EQ(encodeRecovery(1.0f, 2.0f, &metadata), 127);
- EXPECT_EQ(encodeRecovery(1.0f, 0.7071f, &metadata), 31);
- EXPECT_EQ(encodeRecovery(1.0f, 0.5f, &metadata), 0);
+ EXPECT_EQ(encodeGain(1.0f, 1.0f, &metadata), 63);
+ EXPECT_EQ(encodeGain(1.0f, 8.0f, &metadata), 255);
+ EXPECT_EQ(encodeGain(1.0f, 4.0f, &metadata), 191);
+ EXPECT_EQ(encodeGain(1.0f, 2.0f, &metadata), 127);
+ EXPECT_EQ(encodeGain(1.0f, 0.7071f, &metadata), 31);
+ EXPECT_EQ(encodeGain(1.0f, 0.5f, &metadata), 0);
}
-TEST_F(RecoveryMapMathTest, ApplyRecovery) {
- jpegr_metadata_struct metadata = { .maxContentBoost = 4.0f,
+TEST_F(GainMapMathTest, ApplyGain) {
+ ultrahdr_metadata_struct metadata = { .maxContentBoost = 4.0f,
.minContentBoost = 1.0f / 4.0f };
float displayBoost = metadata.maxContentBoost;
- EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), 0.0f, &metadata), RgbBlack());
- EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), 0.5f, &metadata), RgbBlack());
- EXPECT_RGB_NEAR(applyRecovery(RgbBlack(), 1.0f, &metadata), RgbBlack());
+ EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.0f, &metadata), RgbBlack());
+ EXPECT_RGB_NEAR(applyGain(RgbBlack(), 0.5f, &metadata), RgbBlack());
+ EXPECT_RGB_NEAR(applyGain(RgbBlack(), 1.0f, &metadata), RgbBlack());
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, &metadata), RgbWhite() / 4.0f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.0f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.5f, &metadata), RgbWhite());
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.0f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, &metadata), RgbWhite() * 4.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 4.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 4.0f);
metadata.maxContentBoost = 2.0f;
metadata.minContentBoost = 1.0f / 2.0f;
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.25f, &metadata), RgbWhite() / 1.41421f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.5f, &metadata), RgbWhite());
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.75f, &metadata), RgbWhite() * 1.41421f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, &metadata), RgbWhite() * 2.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 1.41421f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 1.41421f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 2.0f);
metadata.maxContentBoost = 8.0f;
metadata.minContentBoost = 1.0f / 8.0f;
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, &metadata), RgbWhite() / 8.0f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.82843f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.5f, &metadata), RgbWhite());
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.82843f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 8.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite() / 2.82843f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite());
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 2.82843f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
metadata.maxContentBoost = 8.0f;
metadata.minContentBoost = 1.0f;
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, &metadata), RgbWhite());
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f / 3.0f, &metadata), RgbWhite() * 2.0f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 2.0f / 3.0f, &metadata), RgbWhite() * 4.0f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite());
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f / 3.0f, &metadata), RgbWhite() * 2.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 2.0f / 3.0f, &metadata), RgbWhite() * 4.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
metadata.maxContentBoost = 8.0f;
metadata.minContentBoost = 0.5f;
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.25f, &metadata), RgbWhite());
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.5f, &metadata), RgbWhite() * 2.0f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 0.75f, &metadata), RgbWhite() * 4.0f);
- EXPECT_RGB_NEAR(applyRecovery(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.0f, &metadata), RgbWhite() / 2.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.25f, &metadata), RgbWhite());
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.5f, &metadata), RgbWhite() * 2.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 0.75f, &metadata), RgbWhite() * 4.0f);
+ EXPECT_RGB_NEAR(applyGain(RgbWhite(), 1.0f, &metadata), RgbWhite() * 8.0f);
Color e = {{{ 0.0f, 0.5f, 1.0f }}};
metadata.maxContentBoost = 4.0f;
metadata.minContentBoost = 1.0f / 4.0f;
- EXPECT_RGB_NEAR(applyRecovery(e, 0.0f, &metadata), e / 4.0f);
- EXPECT_RGB_NEAR(applyRecovery(e, 0.25f, &metadata), e / 2.0f);
- EXPECT_RGB_NEAR(applyRecovery(e, 0.5f, &metadata), e);
- EXPECT_RGB_NEAR(applyRecovery(e, 0.75f, &metadata), e * 2.0f);
- EXPECT_RGB_NEAR(applyRecovery(e, 1.0f, &metadata), e * 4.0f);
+ EXPECT_RGB_NEAR(applyGain(e, 0.0f, &metadata), e / 4.0f);
+ EXPECT_RGB_NEAR(applyGain(e, 0.25f, &metadata), e / 2.0f);
+ EXPECT_RGB_NEAR(applyGain(e, 0.5f, &metadata), e);
+ EXPECT_RGB_NEAR(applyGain(e, 0.75f, &metadata), e * 2.0f);
+ EXPECT_RGB_NEAR(applyGain(e, 1.0f, &metadata), e * 4.0f);
- EXPECT_RGB_EQ(applyRecovery(RgbBlack(), 1.0f, &metadata),
- applyRecovery(RgbBlack(), 1.0f, &metadata, displayBoost));
- EXPECT_RGB_EQ(applyRecovery(RgbWhite(), 1.0f, &metadata),
- applyRecovery(RgbWhite(), 1.0f, &metadata, displayBoost));
- EXPECT_RGB_EQ(applyRecovery(RgbRed(), 1.0f, &metadata),
- applyRecovery(RgbRed(), 1.0f, &metadata, displayBoost));
- EXPECT_RGB_EQ(applyRecovery(RgbGreen(), 1.0f, &metadata),
- applyRecovery(RgbGreen(), 1.0f, &metadata, displayBoost));
- EXPECT_RGB_EQ(applyRecovery(RgbBlue(), 1.0f, &metadata),
- applyRecovery(RgbBlue(), 1.0f, &metadata, displayBoost));
- EXPECT_RGB_EQ(applyRecovery(e, 1.0f, &metadata),
- applyRecovery(e, 1.0f, &metadata, displayBoost));
+ EXPECT_RGB_EQ(applyGain(RgbBlack(), 1.0f, &metadata),
+ applyGain(RgbBlack(), 1.0f, &metadata, displayBoost));
+ EXPECT_RGB_EQ(applyGain(RgbWhite(), 1.0f, &metadata),
+ applyGain(RgbWhite(), 1.0f, &metadata, displayBoost));
+ EXPECT_RGB_EQ(applyGain(RgbRed(), 1.0f, &metadata),
+ applyGain(RgbRed(), 1.0f, &metadata, displayBoost));
+ EXPECT_RGB_EQ(applyGain(RgbGreen(), 1.0f, &metadata),
+ applyGain(RgbGreen(), 1.0f, &metadata, displayBoost));
+ EXPECT_RGB_EQ(applyGain(RgbBlue(), 1.0f, &metadata),
+ applyGain(RgbBlue(), 1.0f, &metadata, displayBoost));
+ EXPECT_RGB_EQ(applyGain(e, 1.0f, &metadata),
+ applyGain(e, 1.0f, &metadata, displayBoost));
}
-TEST_F(RecoveryMapMathTest, GetYuv420Pixel) {
+TEST_F(GainMapMathTest, GetYuv420Pixel) {
jpegr_uncompressed_struct image = Yuv420Image();
Color (*colors)[4] = Yuv420Colors();
@@ -834,7 +834,7 @@
}
}
-TEST_F(RecoveryMapMathTest, GetP010Pixel) {
+TEST_F(GainMapMathTest, GetP010Pixel) {
jpegr_uncompressed_struct image = P010Image();
Color (*colors)[4] = P010Colors();
@@ -845,7 +845,7 @@
}
}
-TEST_F(RecoveryMapMathTest, SampleYuv420) {
+TEST_F(GainMapMathTest, SampleYuv420) {
jpegr_uncompressed_struct image = Yuv420Image();
Color (*colors)[4] = Yuv420Colors();
@@ -871,7 +871,7 @@
}
}
-TEST_F(RecoveryMapMathTest, SampleP010) {
+TEST_F(GainMapMathTest, SampleP010) {
jpegr_uncompressed_struct image = P010Image();
Color (*colors)[4] = P010Colors();
@@ -897,7 +897,7 @@
}
}
-TEST_F(RecoveryMapMathTest, SampleMap) {
+TEST_F(GainMapMathTest, SampleMap) {
jpegr_uncompressed_struct image = MapImage();
float (*values)[4] = MapValues();
@@ -937,7 +937,7 @@
}
}
-TEST_F(RecoveryMapMathTest, ColorToRgba1010102) {
+TEST_F(GainMapMathTest, ColorToRgba1010102) {
EXPECT_EQ(colorToRgba1010102(RgbBlack()), 0x3 << 30);
EXPECT_EQ(colorToRgba1010102(RgbWhite()), 0xFFFFFFFF);
EXPECT_EQ(colorToRgba1010102(RgbRed()), 0x3 << 30 | 0x3ff);
@@ -952,7 +952,28 @@
| static_cast<uint32_t>(0.3f * static_cast<float>(0x3ff)) << 20);
}
-TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgb) {
+TEST_F(GainMapMathTest, ColorToRgbaF16) {
+ EXPECT_EQ(colorToRgbaF16(RgbBlack()), ((uint64_t) 0x3C00) << 48);
+ EXPECT_EQ(colorToRgbaF16(RgbWhite()), 0x3C003C003C003C00);
+ EXPECT_EQ(colorToRgbaF16(RgbRed()), (((uint64_t) 0x3C00) << 48) | ((uint64_t) 0x3C00));
+ EXPECT_EQ(colorToRgbaF16(RgbGreen()), (((uint64_t) 0x3C00) << 48) | (((uint64_t) 0x3C00) << 16));
+ EXPECT_EQ(colorToRgbaF16(RgbBlue()), (((uint64_t) 0x3C00) << 48) | (((uint64_t) 0x3C00) << 32));
+
+ Color e_gamma = {{{ 0.1f, 0.2f, 0.3f }}};
+ EXPECT_EQ(colorToRgbaF16(e_gamma), 0x3C0034CD32662E66);
+}
+
+TEST_F(GainMapMathTest, Float32ToFloat16) {
+ EXPECT_EQ(floatToHalf(0.1f), 0x2E66);
+ EXPECT_EQ(floatToHalf(0.0f), 0x0);
+ EXPECT_EQ(floatToHalf(1.0f), 0x3C00);
+ EXPECT_EQ(floatToHalf(-1.0f), 0xBC00);
+ EXPECT_EQ(floatToHalf(0x1.fffffep127f), 0x7FFF); // float max
+ EXPECT_EQ(floatToHalf(-0x1.fffffep127f), 0xFFFF); // float min
+ EXPECT_EQ(floatToHalf(0x1.0p-126f), 0x0); // float zero
+}
+
+TEST_F(GainMapMathTest, GenerateMapLuminanceSrgb) {
EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), srgbLuminance),
0.0f);
EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), srgbLuminance),
@@ -965,7 +986,7 @@
srgbLuminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
}
-TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgbP3) {
+TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbP3) {
EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), p3Luminance),
0.0f);
EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), p3Luminance),
@@ -978,7 +999,7 @@
p3Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
}
-TEST_F(RecoveryMapMathTest, GenerateMapLuminanceSrgbBt2100) {
+TEST_F(GainMapMathTest, GenerateMapLuminanceSrgbBt2100) {
EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvBlack(), bt2100Luminance),
0.0f);
EXPECT_FLOAT_EQ(SrgbYuvToLuminance(YuvWhite(), bt2100Luminance),
@@ -991,7 +1012,7 @@
bt2100Luminance(RgbBlue()) * kSdrWhiteNits, LuminanceEpsilon());
}
-TEST_F(RecoveryMapMathTest, GenerateMapLuminanceHlg) {
+TEST_F(GainMapMathTest, GenerateMapLuminanceHlg) {
EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), hlgInvOetf, identityConversion,
bt2100Luminance, kHlgMaxNits),
0.0f);
@@ -1009,7 +1030,7 @@
bt2100Luminance(RgbBlue()) * kHlgMaxNits, LuminanceEpsilon());
}
-TEST_F(RecoveryMapMathTest, GenerateMapLuminancePq) {
+TEST_F(GainMapMathTest, GenerateMapLuminancePq) {
EXPECT_FLOAT_EQ(Bt2100YuvToLuminance(YuvBlack(), pqInvOetf, identityConversion,
bt2100Luminance, kPqMaxNits),
0.0f);
@@ -1027,8 +1048,8 @@
bt2100Luminance(RgbBlue()) * kPqMaxNits, LuminanceEpsilon());
}
-TEST_F(RecoveryMapMathTest, ApplyMap) {
- jpegr_metadata_struct metadata = { .maxContentBoost = 8.0f,
+TEST_F(GainMapMathTest, ApplyMap) {
+ ultrahdr_metadata_struct metadata = { .maxContentBoost = 8.0f,
.minContentBoost = 1.0f / 8.0f };
EXPECT_RGB_EQ(Recover(YuvWhite(), 1.0f, &metadata),
@@ -1113,4 +1134,4 @@
RgbWhite() / 2.0f);
}
-} // namespace android::jpegrecoverymap
+} // namespace android::ultrahdr
diff --git a/libs/jpegrecoverymap/tests/jpegdecoderhelper_test.cpp b/libs/ultrahdr/tests/jpegdecoderhelper_test.cpp
similarity index 95%
rename from libs/jpegrecoverymap/tests/jpegdecoderhelper_test.cpp
rename to libs/ultrahdr/tests/jpegdecoderhelper_test.cpp
index 2f32a56..c79dbe3 100644
--- a/libs/jpegrecoverymap/tests/jpegdecoderhelper_test.cpp
+++ b/libs/ultrahdr/tests/jpegdecoderhelper_test.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#include <jpegrecoverymap/jpegdecoderhelper.h>
+#include <ultrahdr/jpegdecoderhelper.h>
#include <gtest/gtest.h>
#include <utils/Log.h>
#include <fcntl.h>
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
#define YUV_IMAGE "/sdcard/Documents/minnie-320x240-yuv.jpg"
#define YUV_IMAGE_SIZE 20193
@@ -99,4 +99,4 @@
ASSERT_GT(decoder.getDecompressedImageSize(), static_cast<uint32_t>(0));
}
-} // namespace android::jpegrecoverymap
\ No newline at end of file
+} // namespace android::ultrahdr
\ No newline at end of file
diff --git a/libs/ultrahdr/tests/jpegencoderhelper_test.cpp b/libs/ultrahdr/tests/jpegencoderhelper_test.cpp
new file mode 100644
index 0000000..8f18ac0
--- /dev/null
+++ b/libs/ultrahdr/tests/jpegencoderhelper_test.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2022 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 <ultrahdr/jpegencoderhelper.h>
+#include <gtest/gtest.h>
+#include <utils/Log.h>
+
+#include <fcntl.h>
+
+namespace android::ultrahdr {
+
+#define ALIGNED_IMAGE "/sdcard/Documents/minnie-320x240.yu12"
+#define ALIGNED_IMAGE_WIDTH 320
+#define ALIGNED_IMAGE_HEIGHT 240
+#define SINGLE_CHANNEL_IMAGE "/sdcard/Documents/minnie-320x240.y"
+#define SINGLE_CHANNEL_IMAGE_WIDTH ALIGNED_IMAGE_WIDTH
+#define SINGLE_CHANNEL_IMAGE_HEIGHT ALIGNED_IMAGE_HEIGHT
+#define UNALIGNED_IMAGE "/sdcard/Documents/minnie-318x240.yu12"
+#define UNALIGNED_IMAGE_WIDTH 318
+#define UNALIGNED_IMAGE_HEIGHT 240
+#define JPEG_QUALITY 90
+
+class JpegEncoderHelperTest : public testing::Test {
+public:
+ struct Image {
+ std::unique_ptr<uint8_t[]> buffer;
+ size_t width;
+ size_t height;
+ };
+ JpegEncoderHelperTest();
+ ~JpegEncoderHelperTest();
+protected:
+ virtual void SetUp();
+ virtual void TearDown();
+
+ Image mAlignedImage, mUnalignedImage, mSingleChannelImage;
+};
+
+JpegEncoderHelperTest::JpegEncoderHelperTest() {}
+
+JpegEncoderHelperTest::~JpegEncoderHelperTest() {}
+
+static size_t getFileSize(int fd) {
+ struct stat st;
+ if (fstat(fd, &st) < 0) {
+ ALOGW("%s : fstat failed", __func__);
+ return 0;
+ }
+ return st.st_size; // bytes
+}
+
+static bool loadFile(const char filename[], JpegEncoderHelperTest::Image* result) {
+ int fd = open(filename, O_CLOEXEC);
+ if (fd < 0) {
+ return false;
+ }
+ int length = getFileSize(fd);
+ if (length == 0) {
+ close(fd);
+ return false;
+ }
+ result->buffer.reset(new uint8_t[length]);
+ if (read(fd, result->buffer.get(), length) != static_cast<ssize_t>(length)) {
+ close(fd);
+ return false;
+ }
+ close(fd);
+ return true;
+}
+
+void JpegEncoderHelperTest::SetUp() {
+ if (!loadFile(ALIGNED_IMAGE, &mAlignedImage)) {
+ FAIL() << "Load file " << ALIGNED_IMAGE << " failed";
+ }
+ mAlignedImage.width = ALIGNED_IMAGE_WIDTH;
+ mAlignedImage.height = ALIGNED_IMAGE_HEIGHT;
+ if (!loadFile(UNALIGNED_IMAGE, &mUnalignedImage)) {
+ FAIL() << "Load file " << UNALIGNED_IMAGE << " failed";
+ }
+ mUnalignedImage.width = UNALIGNED_IMAGE_WIDTH;
+ mUnalignedImage.height = UNALIGNED_IMAGE_HEIGHT;
+ if (!loadFile(SINGLE_CHANNEL_IMAGE, &mSingleChannelImage)) {
+ FAIL() << "Load file " << SINGLE_CHANNEL_IMAGE << " failed";
+ }
+ mSingleChannelImage.width = SINGLE_CHANNEL_IMAGE_WIDTH;
+ mSingleChannelImage.height = SINGLE_CHANNEL_IMAGE_HEIGHT;
+}
+
+void JpegEncoderHelperTest::TearDown() {}
+
+TEST_F(JpegEncoderHelperTest, encodeAlignedImage) {
+ JpegEncoderHelper encoder;
+ EXPECT_TRUE(encoder.compressImage(mAlignedImage.buffer.get(), mAlignedImage.width,
+ mAlignedImage.height, JPEG_QUALITY, NULL, 0));
+ ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
+}
+
+// The width of the "unaligned" image is not 16-aligned, and will fail if encoded directly.
+// Should pass with the padding zero method.
+TEST_F(JpegEncoderHelperTest, encodeUnalignedImage) {
+ JpegEncoderHelper encoder;
+ const size_t paddingZeroLength = JpegEncoderHelper::kCompressBatchSize
+ * JpegEncoderHelper::kCompressBatchSize / 4;
+ std::unique_ptr<uint8_t[]> imageWithPaddingZeros(
+ new uint8_t[UNALIGNED_IMAGE_WIDTH * UNALIGNED_IMAGE_HEIGHT * 3 / 2
+ + paddingZeroLength]);
+ memcpy(imageWithPaddingZeros.get(), mUnalignedImage.buffer.get(),
+ UNALIGNED_IMAGE_WIDTH * UNALIGNED_IMAGE_HEIGHT * 3 / 2);
+ EXPECT_TRUE(encoder.compressImage(imageWithPaddingZeros.get(), mUnalignedImage.width,
+ mUnalignedImage.height, JPEG_QUALITY, NULL, 0));
+ ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
+}
+
+TEST_F(JpegEncoderHelperTest, encodeSingleChannelImage) {
+ JpegEncoderHelper encoder;
+ EXPECT_TRUE(encoder.compressImage(mSingleChannelImage.buffer.get(), mSingleChannelImage.width,
+ mSingleChannelImage.height, JPEG_QUALITY, NULL, 0, true));
+ ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
+}
+
+} // namespace android::ultrahdr
+
diff --git a/libs/jpegrecoverymap/tests/jpegr_test.cpp b/libs/ultrahdr/tests/jpegr_test.cpp
similarity index 70%
rename from libs/jpegrecoverymap/tests/jpegr_test.cpp
rename to libs/ultrahdr/tests/jpegr_test.cpp
index 7c669ab..ba3b4d0 100644
--- a/libs/jpegrecoverymap/tests/jpegr_test.cpp
+++ b/libs/ultrahdr/tests/jpegr_test.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include <jpegrecoverymap/jpegr.h>
-#include <jpegrecoverymap/jpegrutils.h>
-#include <jpegrecoverymap/recoverymapmath.h>
+#include <ultrahdr/jpegr.h>
+#include <ultrahdr/jpegrutils.h>
+#include <ultrahdr/gainmapmath.h>
#include <fcntl.h>
#include <fstream>
#include <gtest/gtest.h>
@@ -24,17 +24,19 @@
#include <utils/Log.h>
#define RAW_P010_IMAGE "/sdcard/Documents/raw_p010_image.p010"
+#define RAW_P010_IMAGE_WITH_STRIDE "/sdcard/Documents/raw_p010_image_with_stride.p010"
#define RAW_YUV420_IMAGE "/sdcard/Documents/raw_yuv420_image.yuv420"
#define JPEG_IMAGE "/sdcard/Documents/jpeg_image.jpg"
#define TEST_IMAGE_WIDTH 1280
#define TEST_IMAGE_HEIGHT 720
+#define TEST_IMAGE_STRIDE 1288
#define DEFAULT_JPEG_QUALITY 90
#define SAVE_ENCODING_RESULT true
#define SAVE_DECODING_RESULT true
#define SAVE_INPUT_RGBA true
-namespace android::jpegrecoverymap {
+namespace android::ultrahdr {
struct Timer {
struct timeval StartingTime;
@@ -97,6 +99,7 @@
virtual void TearDown();
struct jpegr_uncompressed_struct mRawP010Image;
+ struct jpegr_uncompressed_struct mRawP010ImageWithStride;
struct jpegr_uncompressed_struct mRawYuv420Image;
struct jpegr_compressed_struct mJpegImage;
};
@@ -107,24 +110,25 @@
void JpegRTest::SetUp() {}
void JpegRTest::TearDown() {
free(mRawP010Image.data);
+ free(mRawP010ImageWithStride.data);
free(mRawYuv420Image.data);
free(mJpegImage.data);
}
class JpegRBenchmark : public JpegR {
public:
- void BenchmarkGenerateRecoveryMap(jr_uncompressed_ptr yuv420Image, jr_uncompressed_ptr p010Image,
- jr_metadata_ptr metadata, jr_uncompressed_ptr map);
- void BenchmarkApplyRecoveryMap(jr_uncompressed_ptr yuv420Image, jr_uncompressed_ptr map,
- jr_metadata_ptr metadata, jr_uncompressed_ptr dest);
+ void BenchmarkGenerateGainMap(jr_uncompressed_ptr yuv420Image, jr_uncompressed_ptr p010Image,
+ ultrahdr_metadata_ptr metadata, jr_uncompressed_ptr map);
+ void BenchmarkApplyGainMap(jr_uncompressed_ptr yuv420Image, jr_uncompressed_ptr map,
+ ultrahdr_metadata_ptr metadata, jr_uncompressed_ptr dest);
private:
const int kProfileCount = 10;
};
-void JpegRBenchmark::BenchmarkGenerateRecoveryMap(jr_uncompressed_ptr yuv420Image,
- jr_uncompressed_ptr p010Image,
- jr_metadata_ptr metadata,
- jr_uncompressed_ptr map) {
+void JpegRBenchmark::BenchmarkGenerateGainMap(jr_uncompressed_ptr yuv420Image,
+ jr_uncompressed_ptr p010Image,
+ ultrahdr_metadata_ptr metadata,
+ jr_uncompressed_ptr map) {
ASSERT_EQ(yuv420Image->width, p010Image->width);
ASSERT_EQ(yuv420Image->height, p010Image->height);
@@ -132,50 +136,50 @@
timerStart(&genRecMapTime);
for (auto i = 0; i < kProfileCount; i++) {
- ASSERT_EQ(OK, generateRecoveryMap(
- yuv420Image, p010Image, jpegr_transfer_function::JPEGR_TF_HLG, metadata, map));
+ ASSERT_EQ(OK, generateGainMap(
+ yuv420Image, p010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, metadata, map));
if (i != kProfileCount - 1) delete[] static_cast<uint8_t *>(map->data);
}
timerStop(&genRecMapTime);
- ALOGE("Generate Recovery Map:- Res = %i x %i, time = %f ms",
+ ALOGE("Generate Gain Map:- Res = %i x %i, time = %f ms",
yuv420Image->width, yuv420Image->height,
elapsedTime(&genRecMapTime) / (kProfileCount * 1000.f));
}
-void JpegRBenchmark::BenchmarkApplyRecoveryMap(jr_uncompressed_ptr yuv420Image,
- jr_uncompressed_ptr map,
- jr_metadata_ptr metadata,
- jr_uncompressed_ptr dest) {
+void JpegRBenchmark::BenchmarkApplyGainMap(jr_uncompressed_ptr yuv420Image,
+ jr_uncompressed_ptr map,
+ ultrahdr_metadata_ptr metadata,
+ jr_uncompressed_ptr dest) {
Timer applyRecMapTime;
timerStart(&applyRecMapTime);
for (auto i = 0; i < kProfileCount; i++) {
- ASSERT_EQ(OK, applyRecoveryMap(yuv420Image, map, metadata, JPEGR_OUTPUT_HDR_HLG,
- metadata->maxContentBoost /* displayBoost */, dest));
+ ASSERT_EQ(OK, applyGainMap(yuv420Image, map, metadata, ULTRAHDR_OUTPUT_HDR_HLG,
+ metadata->maxContentBoost /* displayBoost */, dest));
}
timerStop(&applyRecMapTime);
- ALOGE("Apply Recovery Map:- Res = %i x %i, time = %f ms",
+ ALOGE("Apply Gain Map:- Res = %i x %i, time = %f ms",
yuv420Image->width, yuv420Image->height,
elapsedTime(&applyRecMapTime) / (kProfileCount * 1000.f));
}
TEST_F(JpegRTest, build) {
- // Force all of the recovery map lib to be linked by calling all public functions.
+ // Force all of the gain map lib to be linked by calling all public functions.
JpegR jpegRCodec;
- jpegRCodec.encodeJPEGR(nullptr, static_cast<jpegr_transfer_function>(0), nullptr, 0, nullptr);
- jpegRCodec.encodeJPEGR(nullptr, nullptr, static_cast<jpegr_transfer_function>(0),
+ jpegRCodec.encodeJPEGR(nullptr, static_cast<ultrahdr_transfer_function>(0), nullptr, 0, nullptr);
+ jpegRCodec.encodeJPEGR(nullptr, nullptr, static_cast<ultrahdr_transfer_function>(0),
nullptr, 0, nullptr);
- jpegRCodec.encodeJPEGR(nullptr, nullptr, nullptr, static_cast<jpegr_transfer_function>(0),
+ jpegRCodec.encodeJPEGR(nullptr, nullptr, nullptr, static_cast<ultrahdr_transfer_function>(0),
nullptr);
- jpegRCodec.encodeJPEGR(nullptr, nullptr, static_cast<jpegr_transfer_function>(0), nullptr);
+ jpegRCodec.encodeJPEGR(nullptr, nullptr, static_cast<ultrahdr_transfer_function>(0), nullptr);
jpegRCodec.decodeJPEGR(nullptr, nullptr);
}
TEST_F(JpegRTest, writeXmpThenRead) {
- jpegr_metadata_struct metadata_expected;
+ ultrahdr_metadata_struct metadata_expected;
metadata_expected.maxContentBoost = 1.25;
metadata_expected.minContentBoost = 0.75;
const std::string nameSpace = "http://ns.adobe.com/xap/1.0/\0";
@@ -190,7 +194,7 @@
xmpData.insert(xmpData.end(), reinterpret_cast<const uint8_t*>(xmp.c_str()),
reinterpret_cast<const uint8_t*>(xmp.c_str()) + xmp.size());
- jpegr_metadata_struct metadata_read;
+ ultrahdr_metadata_struct metadata_read;
EXPECT_TRUE(getMetadataFromXMP(xmpData.data(), xmpData.size(), &metadata_read));
EXPECT_FLOAT_EQ(metadata_expected.maxContentBoost, metadata_read.maxContentBoost);
EXPECT_FLOAT_EQ(metadata_expected.minContentBoost, metadata_read.minContentBoost);
@@ -206,7 +210,7 @@
}
mRawP010Image.width = TEST_IMAGE_WIDTH;
mRawP010Image.height = TEST_IMAGE_HEIGHT;
- mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
+ mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
JpegR jpegRCodec;
@@ -214,7 +218,63 @@
jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
jpegR.data = malloc(jpegR.maxLength);
ret = jpegRCodec.encodeJPEGR(
- &mRawP010Image, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY, nullptr);
+ &mRawP010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY,
+ nullptr);
+ if (ret != OK) {
+ FAIL() << "Error code is " << ret;
+ }
+ if (SAVE_ENCODING_RESULT) {
+ // Output image data to file
+ std::string filePath = "/sdcard/Documents/encoded_from_p010_input.jpgr";
+ std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
+ if (!imageFile.is_open()) {
+ ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
+ }
+ imageFile.write((const char*)jpegR.data, jpegR.length);
+ }
+
+ jpegr_uncompressed_struct decodedJpegR;
+ int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
+ decodedJpegR.data = malloc(decodedJpegRSize);
+ ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
+ if (ret != OK) {
+ FAIL() << "Error code is " << ret;
+ }
+ if (SAVE_DECODING_RESULT) {
+ // Output image data to file
+ std::string filePath = "/sdcard/Documents/decoded_from_p010_input.rgb";
+ std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
+ if (!imageFile.is_open()) {
+ ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
+ }
+ imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
+ }
+
+ free(jpegR.data);
+ free(decodedJpegR.data);
+}
+
+/* Test Encode API-0 (with stride) and decode */
+TEST_F(JpegRTest, encodeFromP010WithStrideThenDecode) {
+ int ret;
+
+ // Load input files.
+ if (!loadFile(RAW_P010_IMAGE_WITH_STRIDE, mRawP010ImageWithStride.data, nullptr)) {
+ FAIL() << "Load file " << RAW_P010_IMAGE_WITH_STRIDE << " failed";
+ }
+ mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
+ mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
+ mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
+ mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
+
+ JpegR jpegRCodec;
+
+ jpegr_compressed_struct jpegR;
+ jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
+ jpegR.data = malloc(jpegR.maxLength);
+ ret = jpegRCodec.encodeJPEGR(
+ &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
+ DEFAULT_JPEG_QUALITY, nullptr);
if (ret != OK) {
FAIL() << "Error code is " << ret;
}
@@ -259,14 +319,14 @@
}
mRawP010Image.width = TEST_IMAGE_WIDTH;
mRawP010Image.height = TEST_IMAGE_HEIGHT;
- mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
+ mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
}
mRawYuv420Image.width = TEST_IMAGE_WIDTH;
mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
- mRawYuv420Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
+ mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
JpegR jpegRCodec;
@@ -274,7 +334,7 @@
jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
jpegR.data = malloc(jpegR.maxLength);
ret = jpegRCodec.encodeJPEGR(
- &mRawP010Image, &mRawYuv420Image, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR,
+ &mRawP010Image, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
DEFAULT_JPEG_QUALITY, nullptr);
if (ret != OK) {
FAIL() << "Error code is " << ret;
@@ -320,19 +380,19 @@
}
mRawP010Image.width = TEST_IMAGE_WIDTH;
mRawP010Image.height = TEST_IMAGE_HEIGHT;
- mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
+ mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
}
mRawYuv420Image.width = TEST_IMAGE_WIDTH;
mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
- mRawYuv420Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
+ mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) {
FAIL() << "Load file " << JPEG_IMAGE << " failed";
}
- mJpegImage.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
+ mJpegImage.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
JpegR jpegRCodec;
@@ -340,7 +400,8 @@
jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
jpegR.data = malloc(jpegR.maxLength);
ret = jpegRCodec.encodeJPEGR(
- &mRawP010Image, &mRawYuv420Image, &mJpegImage, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR);
+ &mRawP010Image, &mRawYuv420Image, &mJpegImage, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
+ &jpegR);
if (ret != OK) {
FAIL() << "Error code is " << ret;
}
@@ -385,7 +446,7 @@
}
mRawP010Image.width = TEST_IMAGE_WIDTH;
mRawP010Image.height = TEST_IMAGE_HEIGHT;
- mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
+ mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
if (SAVE_INPUT_RGBA) {
size_t rgbaSize = mRawP010Image.width * mRawP010Image.height * sizeof(uint32_t);
@@ -413,7 +474,7 @@
if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) {
FAIL() << "Load file " << JPEG_IMAGE << " failed";
}
- mJpegImage.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
+ mJpegImage.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
JpegR jpegRCodec;
@@ -421,7 +482,7 @@
jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
jpegR.data = malloc(jpegR.maxLength);
ret = jpegRCodec.encodeJPEGR(
- &mRawP010Image, &mJpegImage, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR);
+ &mRawP010Image, &mJpegImage, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR);
if (ret != OK) {
FAIL() << "Error code is " << ret;
}
@@ -456,7 +517,7 @@
free(decodedJpegR.data);
}
-TEST_F(JpegRTest, ProfileRecoveryMapFuncs) {
+TEST_F(JpegRTest, ProfileGainMapFuncs) {
const size_t kWidth = TEST_IMAGE_WIDTH;
const size_t kHeight = TEST_IMAGE_HEIGHT;
@@ -466,36 +527,36 @@
}
mRawP010Image.width = kWidth;
mRawP010Image.height = kHeight;
- mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
+ mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
}
mRawYuv420Image.width = kWidth;
mRawYuv420Image.height = kHeight;
- mRawYuv420Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
+ mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
JpegRBenchmark benchmark;
- jpegr_metadata_struct metadata = { .version = 1,
+ ultrahdr_metadata_struct metadata = { .version = 1,
.maxContentBoost = 8.0f,
.minContentBoost = 1.0f / 8.0f };
jpegr_uncompressed_struct map = { .data = NULL,
.width = 0,
.height = 0,
- .colorGamut = JPEGR_COLORGAMUT_UNSPECIFIED };
+ .colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED };
- benchmark.BenchmarkGenerateRecoveryMap(&mRawYuv420Image, &mRawP010Image, &metadata, &map);
+ benchmark.BenchmarkGenerateGainMap(&mRawYuv420Image, &mRawP010Image, &metadata, &map);
const int dstSize = mRawYuv420Image.width * mRawYuv420Image.height * 4;
auto bufferDst = std::make_unique<uint8_t[]>(dstSize);
jpegr_uncompressed_struct dest = { .data = bufferDst.get(),
.width = 0,
.height = 0,
- .colorGamut = JPEGR_COLORGAMUT_UNSPECIFIED };
+ .colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED };
- benchmark.BenchmarkApplyRecoveryMap(&mRawYuv420Image, &map, &metadata, &dest);
+ benchmark.BenchmarkApplyGainMap(&mRawYuv420Image, &map, &metadata, &dest);
}
-} // namespace android::recoverymap
+} // namespace android::ultrahdr
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index b885435..e04481c 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -213,6 +213,7 @@
name: "checkinput",
required: [
// native targets
+ "libgui_test",
"libinput",
"libinputflinger",
"inputflinger_tests",
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index d33b298..aa55873 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -24,7 +24,6 @@
#include <android-base/stringprintf.h>
#include <android/log.h>
-#include <math.h>
#include <utils/Trace.h>
using android::base::StringPrintf;
@@ -47,16 +46,15 @@
void InputListenerInterface::notify(const NotifyArgs& generalArgs) {
Visitor v{
- [&](const NotifyConfigurationChangedArgs& args) { notifyConfigurationChanged(&args); },
- [&](const NotifyKeyArgs& args) { notifyKey(&args); },
- [&](const NotifyMotionArgs& args) { notifyMotion(&args); },
- [&](const NotifySwitchArgs& args) { notifySwitch(&args); },
- [&](const NotifySensorArgs& args) { notifySensor(&args); },
- [&](const NotifyVibratorStateArgs& args) { notifyVibratorState(&args); },
- [&](const NotifyDeviceResetArgs& args) { notifyDeviceReset(&args); },
- [&](const NotifyPointerCaptureChangedArgs& args) {
- notifyPointerCaptureChanged(&args);
- },
+ [&](const NotifyInputDevicesChangedArgs& args) { notifyInputDevicesChanged(args); },
+ [&](const NotifyConfigurationChangedArgs& args) { notifyConfigurationChanged(args); },
+ [&](const NotifyKeyArgs& args) { notifyKey(args); },
+ [&](const NotifyMotionArgs& args) { notifyMotion(args); },
+ [&](const NotifySwitchArgs& args) { notifySwitch(args); },
+ [&](const NotifySensorArgs& args) { notifySensor(args); },
+ [&](const NotifyVibratorStateArgs& args) { notifyVibratorState(args); },
+ [&](const NotifyDeviceResetArgs& args) { notifyDeviceReset(args); },
+ [&](const NotifyPointerCaptureChangedArgs& args) { notifyPointerCaptureChanged(args); },
};
std::visit(v, generalArgs);
}
@@ -73,45 +71,49 @@
QueuedInputListener::QueuedInputListener(InputListenerInterface& innerListener)
: mInnerListener(innerListener) {}
-void QueuedInputListener::notifyConfigurationChanged(
- const NotifyConfigurationChangedArgs* args) {
- traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(*args);
+void QueuedInputListener::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
+ traceEvent(__func__, args.id);
+ mArgsQueue.emplace_back(args);
}
-void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
- traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(*args);
+void QueuedInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
+ traceEvent(__func__, args.id);
+ mArgsQueue.emplace_back(args);
}
-void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
- traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(*args);
+void QueuedInputListener::notifyKey(const NotifyKeyArgs& args) {
+ traceEvent(__func__, args.id);
+ mArgsQueue.emplace_back(args);
}
-void QueuedInputListener::notifySwitch(const NotifySwitchArgs* args) {
- traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(*args);
+void QueuedInputListener::notifyMotion(const NotifyMotionArgs& args) {
+ traceEvent(__func__, args.id);
+ mArgsQueue.emplace_back(args);
}
-void QueuedInputListener::notifySensor(const NotifySensorArgs* args) {
- traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(*args);
+void QueuedInputListener::notifySwitch(const NotifySwitchArgs& args) {
+ traceEvent(__func__, args.id);
+ mArgsQueue.emplace_back(args);
}
-void QueuedInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) {
- traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(*args);
+void QueuedInputListener::notifySensor(const NotifySensorArgs& args) {
+ traceEvent(__func__, args.id);
+ mArgsQueue.emplace_back(args);
}
-void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
- traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(*args);
+void QueuedInputListener::notifyVibratorState(const NotifyVibratorStateArgs& args) {
+ traceEvent(__func__, args.id);
+ mArgsQueue.emplace_back(args);
}
-void QueuedInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
- traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(*args);
+void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
+ traceEvent(__func__, args.id);
+ mArgsQueue.emplace_back(args);
+}
+
+void QueuedInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) {
+ traceEvent(__func__, args.id);
+ mArgsQueue.emplace_back(args);
}
void QueuedInputListener::flush() {
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 9182503..472d7a1 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -110,10 +110,6 @@
return *mReader;
}
-UnwantedInteractionBlockerInterface& InputManager::getBlocker() {
- return *mBlocker;
-}
-
InputProcessorInterface& InputManager::getProcessor() {
return *mProcessor;
}
@@ -129,6 +125,17 @@
mDispatcher->monitor();
}
+void InputManager::dump(std::string& dump) {
+ mReader->dump(dump);
+ dump += '\n';
+ mBlocker->dump(dump);
+ dump += '\n';
+ mProcessor->dump(dump);
+ dump += '\n';
+ mDispatcher->dump(dump);
+ dump += '\n';
+}
+
// Used by tests only.
binder::Status InputManager::createInputChannel(const std::string& name, InputChannel* outChannel) {
IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 1137193..793757d 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -82,9 +82,6 @@
/* Gets the input reader. */
virtual InputReaderInterface& getReader() = 0;
- /* Gets the unwanted interaction blocker. */
- virtual UnwantedInteractionBlockerInterface& getBlocker() = 0;
-
/* Gets the input processor */
virtual InputProcessorInterface& getProcessor() = 0;
@@ -93,6 +90,9 @@
/* Check that the input stages have not deadlocked. */
virtual void monitor() = 0;
+
+ /* Dump the state of the components controlled by the input manager. */
+ virtual void dump(std::string& dump) = 0;
};
class InputManager : public InputManagerInterface, public BnInputFlinger {
@@ -108,10 +108,10 @@
status_t stop() override;
InputReaderInterface& getReader() override;
- UnwantedInteractionBlockerInterface& getBlocker() override;
InputProcessorInterface& getProcessor() override;
InputDispatcherInterface& getDispatcher() override;
void monitor() override;
+ void dump(std::string& dump) override;
status_t dump(int fd, const Vector<String16>& args) override;
binder::Status createInputChannel(const std::string& name, InputChannel* outChannel) override;
diff --git a/services/inputflinger/InputProcessor.cpp b/services/inputflinger/InputProcessor.cpp
index a98b383..7a84be9 100644
--- a/services/inputflinger/InputProcessor.cpp
+++ b/services/inputflinger/InputProcessor.cpp
@@ -413,63 +413,69 @@
}
}
-void InputProcessor::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
+void InputProcessor::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
+ // pass through
+ mQueuedListener.notify(args);
+ mQueuedListener.flush();
+}
+
+void InputProcessor::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
// pass through
mQueuedListener.notifyConfigurationChanged(args);
mQueuedListener.flush();
}
-void InputProcessor::notifyKey(const NotifyKeyArgs* args) {
+void InputProcessor::notifyKey(const NotifyKeyArgs& args) {
// pass through
mQueuedListener.notifyKey(args);
mQueuedListener.flush();
}
-void InputProcessor::notifyMotion(const NotifyMotionArgs* args) {
+void InputProcessor::notifyMotion(const NotifyMotionArgs& args) {
{ // acquire lock
std::scoped_lock lock(mLock);
// MotionClassifier is only used for touch events, for now
- const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(*args);
+ const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(args);
if (!sendToMotionClassifier) {
mQueuedListener.notifyMotion(args);
} else {
- NotifyMotionArgs newArgs(*args);
+ NotifyMotionArgs newArgs(args);
const MotionClassification newClassification = mMotionClassifier->classify(newArgs);
- LOG_ALWAYS_FATAL_IF(args->classification != MotionClassification::NONE &&
+ LOG_ALWAYS_FATAL_IF(args.classification != MotionClassification::NONE &&
newClassification != MotionClassification::NONE,
"Conflicting classifications %s (new) and %s (old)!",
motionClassificationToString(newClassification),
- motionClassificationToString(args->classification));
+ motionClassificationToString(args.classification));
newArgs.classification = newClassification;
- mQueuedListener.notifyMotion(&newArgs);
+ mQueuedListener.notifyMotion(newArgs);
}
} // release lock
mQueuedListener.flush();
}
-void InputProcessor::notifySensor(const NotifySensorArgs* args) {
+void InputProcessor::notifySensor(const NotifySensorArgs& args) {
// pass through
mQueuedListener.notifySensor(args);
mQueuedListener.flush();
}
-void InputProcessor::notifyVibratorState(const NotifyVibratorStateArgs* args) {
+void InputProcessor::notifyVibratorState(const NotifyVibratorStateArgs& args) {
// pass through
mQueuedListener.notifyVibratorState(args);
mQueuedListener.flush();
}
-void InputProcessor::notifySwitch(const NotifySwitchArgs* args) {
+void InputProcessor::notifySwitch(const NotifySwitchArgs& args) {
// pass through
mQueuedListener.notifySwitch(args);
mQueuedListener.flush();
}
-void InputProcessor::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
+void InputProcessor::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
{ // acquire lock
std::scoped_lock lock(mLock);
if (mMotionClassifier) {
- mMotionClassifier->reset(*args);
+ mMotionClassifier->reset(args);
}
} // release lock
@@ -478,7 +484,7 @@
mQueuedListener.flush();
}
-void InputProcessor::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
+void InputProcessor::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) {
// pass through
mQueuedListener.notifyPointerCaptureChanged(args);
mQueuedListener.flush();
diff --git a/services/inputflinger/InputProcessor.h b/services/inputflinger/InputProcessor.h
index f4d02b6..dcbfebc 100644
--- a/services/inputflinger/InputProcessor.h
+++ b/services/inputflinger/InputProcessor.h
@@ -245,14 +245,15 @@
public:
explicit InputProcessor(InputListenerInterface& listener);
- void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
- void notifyKey(const NotifyKeyArgs* args) override;
- void notifyMotion(const NotifyMotionArgs* args) override;
- void notifySwitch(const NotifySwitchArgs* args) override;
- void notifySensor(const NotifySensorArgs* args) override;
- void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
- void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
- void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
+ void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
+ void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
+ void notifyKey(const NotifyKeyArgs& args) override;
+ void notifyMotion(const NotifyMotionArgs& args) override;
+ void notifySwitch(const NotifySwitchArgs& args) override;
+ void notifySensor(const NotifySensorArgs& args) override;
+ void notifyVibratorState(const NotifyVibratorStateArgs& args) override;
+ void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
+ void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
void dump(std::string& dump) override;
void monitor() override;
diff --git a/services/inputflinger/NotifyArgs.cpp b/services/inputflinger/NotifyArgs.cpp
index 5f2a22f..408fbed 100644
--- a/services/inputflinger/NotifyArgs.cpp
+++ b/services/inputflinger/NotifyArgs.cpp
@@ -29,6 +29,12 @@
namespace android {
+// --- NotifyInputDevicesChangedArgs ---
+
+NotifyInputDevicesChangedArgs::NotifyInputDevicesChangedArgs(int32_t id,
+ std::vector<InputDeviceInfo> infos)
+ : id(id), inputDeviceInfos(std::move(infos)) {}
+
// --- NotifyConfigurationChangedArgs ---
NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(int32_t id, nsecs_t eventTime)
@@ -234,6 +240,7 @@
const char* toString(const NotifyArgs& args) {
Visitor toStringVisitor{
+ [&](const NotifyInputDevicesChangedArgs&) { return "NotifyInputDevicesChangedArgs"; },
[&](const NotifyConfigurationChangedArgs&) { return "NotifyConfigurationChangedArgs"; },
[&](const NotifyKeyArgs&) { return "NotifyKeyArgs"; },
[&](const NotifyMotionArgs&) { return "NotifyMotionArgs"; },
diff --git a/services/inputflinger/TEST_MAPPING b/services/inputflinger/TEST_MAPPING
index 495334e..f0b1072 100644
--- a/services/inputflinger/TEST_MAPPING
+++ b/services/inputflinger/TEST_MAPPING
@@ -27,6 +27,14 @@
"name": "libinputservice_test"
},
{
+ "name": "libgui_test",
+ "options": [
+ {
+ "native-test-flag": "--gtest_filter=\"InputSurfacesTest*:MultiDisplayTests*\""
+ }
+ ]
+ },
+ {
"name": "CtsHardwareTestCases",
"options": [
{
@@ -123,6 +131,14 @@
"name": "libinputservice_test"
},
{
+ "name": "libgui_test",
+ "options": [
+ {
+ "native-test-flag": "--gtest_filter=\"InputSurfacesTest*:MultiDisplayTests*\""
+ }
+ ]
+ },
+ {
"name": "CtsHardwareTestCases",
"options": [
{
diff --git a/services/inputflinger/UnwantedInteractionBlocker.cpp b/services/inputflinger/UnwantedInteractionBlocker.cpp
index ae20f86..02bc47d 100644
--- a/services/inputflinger/UnwantedInteractionBlocker.cpp
+++ b/services/inputflinger/UnwantedInteractionBlocker.cpp
@@ -329,24 +329,24 @@
: mQueuedListener(listener), mEnablePalmRejection(enablePalmRejection) {}
void UnwantedInteractionBlocker::notifyConfigurationChanged(
- const NotifyConfigurationChangedArgs* args) {
+ const NotifyConfigurationChangedArgs& args) {
mQueuedListener.notifyConfigurationChanged(args);
mQueuedListener.flush();
}
-void UnwantedInteractionBlocker::notifyKey(const NotifyKeyArgs* args) {
+void UnwantedInteractionBlocker::notifyKey(const NotifyKeyArgs& args) {
mQueuedListener.notifyKey(args);
mQueuedListener.flush();
}
-void UnwantedInteractionBlocker::notifyMotion(const NotifyMotionArgs* args) {
- ALOGD_IF(DEBUG_INBOUND_MOTION, "%s: %s", __func__, args->dump().c_str());
+void UnwantedInteractionBlocker::notifyMotion(const NotifyMotionArgs& args) {
+ ALOGD_IF(DEBUG_INBOUND_MOTION, "%s: %s", __func__, args.dump().c_str());
{ // acquire lock
std::scoped_lock lock(mLock);
const std::vector<NotifyMotionArgs> processedArgs =
- mPreferStylusOverTouchBlocker.processMotion(*args);
+ mPreferStylusOverTouchBlocker.processMotion(args);
for (const NotifyMotionArgs& loopArgs : processedArgs) {
- notifyMotionLocked(&loopArgs);
+ notifyMotionLocked(loopArgs);
}
} // release lock
@@ -356,61 +356,68 @@
void UnwantedInteractionBlocker::enqueueOutboundMotionLocked(const NotifyMotionArgs& args) {
ALOGD_IF(DEBUG_OUTBOUND_MOTION, "%s: %s", __func__, args.dump().c_str());
- mQueuedListener.notifyMotion(&args);
+ mQueuedListener.notifyMotion(args);
}
-void UnwantedInteractionBlocker::notifyMotionLocked(const NotifyMotionArgs* args) {
- auto it = mPalmRejectors.find(args->deviceId);
- const bool sendToPalmRejector = it != mPalmRejectors.end() && isFromTouchscreen(args->source);
+void UnwantedInteractionBlocker::notifyMotionLocked(const NotifyMotionArgs& args) {
+ auto it = mPalmRejectors.find(args.deviceId);
+ const bool sendToPalmRejector = it != mPalmRejectors.end() && isFromTouchscreen(args.source);
if (!sendToPalmRejector) {
- enqueueOutboundMotionLocked(*args);
+ enqueueOutboundMotionLocked(args);
return;
}
- std::vector<NotifyMotionArgs> processedArgs = it->second.processMotion(*args);
+ std::vector<NotifyMotionArgs> processedArgs = it->second.processMotion(args);
for (const NotifyMotionArgs& loopArgs : processedArgs) {
enqueueOutboundMotionLocked(loopArgs);
}
}
-void UnwantedInteractionBlocker::notifySwitch(const NotifySwitchArgs* args) {
+void UnwantedInteractionBlocker::notifySwitch(const NotifySwitchArgs& args) {
mQueuedListener.notifySwitch(args);
mQueuedListener.flush();
}
-void UnwantedInteractionBlocker::notifySensor(const NotifySensorArgs* args) {
+void UnwantedInteractionBlocker::notifySensor(const NotifySensorArgs& args) {
mQueuedListener.notifySensor(args);
mQueuedListener.flush();
}
-void UnwantedInteractionBlocker::notifyVibratorState(const NotifyVibratorStateArgs* args) {
+void UnwantedInteractionBlocker::notifyVibratorState(const NotifyVibratorStateArgs& args) {
mQueuedListener.notifyVibratorState(args);
mQueuedListener.flush();
}
-void UnwantedInteractionBlocker::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
+void UnwantedInteractionBlocker::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
{ // acquire lock
std::scoped_lock lock(mLock);
- auto it = mPalmRejectors.find(args->deviceId);
+ auto it = mPalmRejectors.find(args.deviceId);
if (it != mPalmRejectors.end()) {
AndroidPalmFilterDeviceInfo info = it->second.getPalmFilterDeviceInfo();
// Re-create the object instead of resetting it
mPalmRejectors.erase(it);
- mPalmRejectors.emplace(args->deviceId, info);
+ mPalmRejectors.emplace(args.deviceId, info);
}
mQueuedListener.notifyDeviceReset(args);
- mPreferStylusOverTouchBlocker.notifyDeviceReset(*args);
+ mPreferStylusOverTouchBlocker.notifyDeviceReset(args);
} // release lock
// Send events to the next stage without holding the lock
mQueuedListener.flush();
}
void UnwantedInteractionBlocker::notifyPointerCaptureChanged(
- const NotifyPointerCaptureChangedArgs* args) {
+ const NotifyPointerCaptureChangedArgs& args) {
mQueuedListener.notifyPointerCaptureChanged(args);
mQueuedListener.flush();
}
void UnwantedInteractionBlocker::notifyInputDevicesChanged(
+ const NotifyInputDevicesChangedArgs& args) {
+ onInputDevicesChanged(args.inputDeviceInfos);
+ mQueuedListener.notify(args);
+ mQueuedListener.flush();
+}
+
+void UnwantedInteractionBlocker::onInputDevicesChanged(
const std::vector<InputDeviceInfo>& inputDevices) {
std::scoped_lock lock(mLock);
if (!mEnablePalmRejection) {
diff --git a/services/inputflinger/UnwantedInteractionBlocker.h b/services/inputflinger/UnwantedInteractionBlocker.h
index 5d0dde8..419da83 100644
--- a/services/inputflinger/UnwantedInteractionBlocker.h
+++ b/services/inputflinger/UnwantedInteractionBlocker.h
@@ -90,16 +90,16 @@
explicit UnwantedInteractionBlocker(InputListenerInterface& listener);
explicit UnwantedInteractionBlocker(InputListenerInterface& listener, bool enablePalmRejection);
- void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
- void notifyKey(const NotifyKeyArgs* args) override;
- void notifyMotion(const NotifyMotionArgs* args) override;
- void notifySwitch(const NotifySwitchArgs* args) override;
- void notifySensor(const NotifySensorArgs* args) override;
- void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
- void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
- void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
+ void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
+ void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
+ void notifyKey(const NotifyKeyArgs& args) override;
+ void notifyMotion(const NotifyMotionArgs& args) override;
+ void notifySwitch(const NotifySwitchArgs& args) override;
+ void notifySensor(const NotifySensorArgs& args) override;
+ void notifyVibratorState(const NotifyVibratorStateArgs& args) override;
+ void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
+ void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
- void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override;
void dump(std::string& dump) override;
void monitor() override;
@@ -119,10 +119,12 @@
// Use a separate palm rejector for every touch device.
std::map<int32_t /*deviceId*/, PalmRejector> mPalmRejectors GUARDED_BY(mLock);
// TODO(b/210159205): delete this when simultaneous stylus and touch is supported
- void notifyMotionLocked(const NotifyMotionArgs* args) REQUIRES(mLock);
+ void notifyMotionLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
// Call this function for outbound events so that they can be logged when logging is enabled.
void enqueueOutboundMotionLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
+
+ void onInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices);
};
class SlotState {
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 58324c4..f852001 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -277,12 +277,12 @@
motionArgs.action = AMOTION_EVENT_ACTION_DOWN;
motionArgs.downTime = now();
motionArgs.eventTime = motionArgs.downTime;
- dispatcher.notifyMotion(&motionArgs);
+ dispatcher.notifyMotion(motionArgs);
// Send ACTION_UP
motionArgs.action = AMOTION_EVENT_ACTION_UP;
motionArgs.eventTime = now();
- dispatcher.notifyMotion(&motionArgs);
+ dispatcher.notifyMotion(motionArgs);
window->consumeEvent();
window->consumeEvent();
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 6e2f862..e8434be 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -117,11 +117,7 @@
return systemTime(SYSTEM_TIME_MONOTONIC);
}
-inline const char* toString(bool value) {
- return value ? "true" : "false";
-}
-
-inline const std::string toString(const sp<IBinder>& binder) {
+inline const std::string binderToString(const sp<IBinder>& binder) {
if (binder == nullptr) {
return "<null>";
}
@@ -626,7 +622,9 @@
touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_HOVER_ENTER;
} else {
// This pointer was already sent to the window. Use ACTION_HOVER_MOVE.
- LOG_ALWAYS_FATAL_IF(maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE);
+ if (CC_UNLIKELY(maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE)) {
+ LOG(FATAL) << "Expected ACTION_HOVER_MOVE instead of " << entry.getDescription();
+ }
touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_IS;
}
touchedWindow.pointerIds.set(pointerId);
@@ -2907,7 +2905,7 @@
info->frameBottom, dumpRegion(info->touchableRegion).c_str(),
info->name.c_str(), info->inputConfig.string().c_str(),
toString(info->token != nullptr), info->applicationInfo.name.c_str(),
- toString(info->applicationInfo.token).c_str());
+ binderToString(info->applicationInfo.token).c_str());
}
bool InputDispatcher::isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const {
@@ -3621,8 +3619,8 @@
const sp<Connection>& connection,
bool notify) {
if (DEBUG_DISPATCH_CYCLE) {
- ALOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s",
- connection->getInputChannelName().c_str(), toString(notify));
+ LOG(DEBUG) << "channel '" << connection->getInputChannelName() << "'~ " << __func__
+ << " - notify=" << toString(notify);
}
// Clear the dispatch queues.
@@ -4027,9 +4025,9 @@
return splitMotionEntry;
}
-void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
+void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
if (debugInboundEventDetails()) {
- ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args->eventTime);
+ ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args.eventTime);
}
bool needWake = false;
@@ -4037,7 +4035,7 @@
std::scoped_lock _l(mLock);
std::unique_ptr<ConfigurationChangedEntry> newEntry =
- std::make_unique<ConfigurationChangedEntry>(args->id, args->eventTime);
+ std::make_unique<ConfigurationChangedEntry>(args.id, args.eventTime);
needWake = enqueueInboundEventLocked(std::move(newEntry));
} // release lock
@@ -4085,23 +4083,22 @@
}
}
-void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
+void InputDispatcher::notifyKey(const NotifyKeyArgs& args) {
ALOGD_IF(debugInboundEventDetails(),
"notifyKey - id=%" PRIx32 ", eventTime=%" PRId64
", deviceId=%d, source=%s, displayId=%" PRId32
"policyFlags=0x%x, action=%s, flags=0x%x, keyCode=%s, scanCode=0x%x, metaState=0x%x, "
"downTime=%" PRId64,
- args->id, args->eventTime, args->deviceId,
- inputEventSourceToString(args->source).c_str(), args->displayId, args->policyFlags,
- KeyEvent::actionToString(args->action), args->flags, KeyEvent::getLabel(args->keyCode),
- args->scanCode, args->metaState, args->downTime);
- if (!validateKeyEvent(args->action)) {
+ args.id, args.eventTime, args.deviceId, inputEventSourceToString(args.source).c_str(),
+ args.displayId, args.policyFlags, KeyEvent::actionToString(args.action), args.flags,
+ KeyEvent::getLabel(args.keyCode), args.scanCode, args.metaState, args.downTime);
+ if (!validateKeyEvent(args.action)) {
return;
}
- uint32_t policyFlags = args->policyFlags;
- int32_t flags = args->flags;
- int32_t metaState = args->metaState;
+ uint32_t policyFlags = args.policyFlags;
+ int32_t flags = args.flags;
+ int32_t metaState = args.metaState;
// InputDispatcher tracks and generates key repeats on behalf of
// whatever notifies it, so repeatCount should always be set to 0
constexpr int32_t repeatCount = 0;
@@ -4115,13 +4112,13 @@
policyFlags |= POLICY_FLAG_TRUSTED;
- int32_t keyCode = args->keyCode;
- accelerateMetaShortcuts(args->deviceId, args->action, keyCode, metaState);
+ int32_t keyCode = args.keyCode;
+ accelerateMetaShortcuts(args.deviceId, args.action, keyCode, metaState);
KeyEvent event;
- event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
- args->action, flags, keyCode, args->scanCode, metaState, repeatCount,
- args->downTime, args->eventTime);
+ event.initialize(args.id, args.deviceId, args.source, args.displayId, INVALID_HMAC, args.action,
+ flags, keyCode, args.scanCode, metaState, repeatCount, args.downTime,
+ args.eventTime);
android::base::Timer t;
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
@@ -4146,10 +4143,9 @@
}
std::unique_ptr<KeyEntry> newEntry =
- std::make_unique<KeyEntry>(args->id, args->eventTime, args->deviceId, args->source,
- args->displayId, policyFlags, args->action, flags,
- keyCode, args->scanCode, metaState, repeatCount,
- args->downTime);
+ std::make_unique<KeyEntry>(args.id, args.eventTime, args.deviceId, args.source,
+ args.displayId, policyFlags, args.action, flags, keyCode,
+ args.scanCode, metaState, repeatCount, args.downTime);
needWake = enqueueInboundEventLocked(std::move(newEntry));
mLock.unlock();
@@ -4160,50 +4156,50 @@
}
}
-bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) {
+bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs& args) {
return mInputFilterEnabled;
}
-void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
+void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) {
if (debugInboundEventDetails()) {
ALOGD("notifyMotion - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=%s, "
"displayId=%" PRId32 ", policyFlags=0x%x, "
"action=%s, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, "
"edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, xCursorPosition=%f, "
"yCursorPosition=%f, downTime=%" PRId64,
- args->id, args->eventTime, args->deviceId,
- inputEventSourceToString(args->source).c_str(), args->displayId, args->policyFlags,
- MotionEvent::actionToString(args->action).c_str(), args->actionButton, args->flags,
- args->metaState, args->buttonState, args->edgeFlags, args->xPrecision,
- args->yPrecision, args->xCursorPosition, args->yCursorPosition, args->downTime);
- for (uint32_t i = 0; i < args->pointerCount; i++) {
+ args.id, args.eventTime, args.deviceId, inputEventSourceToString(args.source).c_str(),
+ args.displayId, args.policyFlags, MotionEvent::actionToString(args.action).c_str(),
+ args.actionButton, args.flags, args.metaState, args.buttonState, args.edgeFlags,
+ args.xPrecision, args.yPrecision, args.xCursorPosition, args.yCursorPosition,
+ args.downTime);
+ for (uint32_t i = 0; i < args.pointerCount; i++) {
ALOGD(" Pointer %d: id=%d, toolType=%s, x=%f, y=%f, pressure=%f, size=%f, "
"touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, orientation=%f",
- i, args->pointerProperties[i].id,
- ftl::enum_string(args->pointerProperties[i].toolType).c_str(),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
+ i, args.pointerProperties[i].id,
+ ftl::enum_string(args.pointerProperties[i].toolType).c_str(),
+ args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
+ args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
+ args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
+ args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
+ args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
+ args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
+ args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
+ args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
+ args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
}
}
- if (!validateMotionEvent(args->action, args->actionButton, args->pointerCount,
- args->pointerProperties)) {
- LOG(ERROR) << "Invalid event: " << args->dump();
+ if (!validateMotionEvent(args.action, args.actionButton, args.pointerCount,
+ args.pointerProperties)) {
+ LOG(ERROR) << "Invalid event: " << args.dump();
return;
}
- uint32_t policyFlags = args->policyFlags;
+ uint32_t policyFlags = args.policyFlags;
policyFlags |= POLICY_FLAG_TRUSTED;
android::base::Timer t;
- mPolicy->interceptMotionBeforeQueueing(args->displayId, args->eventTime, /*byref*/ policyFlags);
+ mPolicy->interceptMotionBeforeQueueing(args.displayId, args.eventTime, policyFlags);
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
std::to_string(t.duration().count()).c_str());
@@ -4215,10 +4211,10 @@
if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
// Set the flag anyway if we already have an ongoing gesture. That would allow us to
// complete the processing of the current stroke.
- const auto touchStateIt = mTouchStatesByDisplay.find(args->displayId);
+ const auto touchStateIt = mTouchStatesByDisplay.find(args.displayId);
if (touchStateIt != mTouchStatesByDisplay.end()) {
const TouchState& touchState = touchStateIt->second;
- if (touchState.deviceId == args->deviceId && touchState.isDown()) {
+ if (touchState.deviceId == args.deviceId && touchState.isDown()) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
@@ -4226,20 +4222,20 @@
if (shouldSendMotionToInputFilterLocked(args)) {
ui::Transform displayTransform;
- if (const auto it = mDisplayInfos.find(args->displayId); it != mDisplayInfos.end()) {
+ if (const auto it = mDisplayInfos.find(args.displayId); it != mDisplayInfos.end()) {
displayTransform = it->second.transform;
}
mLock.unlock();
MotionEvent event;
- event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
- args->action, args->actionButton, args->flags, args->edgeFlags,
- args->metaState, args->buttonState, args->classification,
- displayTransform, args->xPrecision, args->yPrecision,
- args->xCursorPosition, args->yCursorPosition, displayTransform,
- args->downTime, args->eventTime, args->pointerCount,
- args->pointerProperties, args->pointerCoords);
+ event.initialize(args.id, args.deviceId, args.source, args.displayId, INVALID_HMAC,
+ args.action, args.actionButton, args.flags, args.edgeFlags,
+ args.metaState, args.buttonState, args.classification,
+ displayTransform, args.xPrecision, args.yPrecision,
+ args.xCursorPosition, args.yCursorPosition, displayTransform,
+ args.downTime, args.eventTime, args.pointerCount,
+ args.pointerProperties, args.pointerCoords);
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
@@ -4251,21 +4247,20 @@
// Just enqueue a new motion event.
std::unique_ptr<MotionEntry> newEntry =
- std::make_unique<MotionEntry>(args->id, args->eventTime, args->deviceId,
- args->source, args->displayId, policyFlags,
- args->action, args->actionButton, args->flags,
- args->metaState, args->buttonState,
- args->classification, args->edgeFlags,
- args->xPrecision, args->yPrecision,
- args->xCursorPosition, args->yCursorPosition,
- args->downTime, args->pointerCount,
- args->pointerProperties, args->pointerCoords);
+ std::make_unique<MotionEntry>(args.id, args.eventTime, args.deviceId, args.source,
+ args.displayId, policyFlags, args.action,
+ args.actionButton, args.flags, args.metaState,
+ args.buttonState, args.classification, args.edgeFlags,
+ args.xPrecision, args.yPrecision,
+ args.xCursorPosition, args.yCursorPosition,
+ args.downTime, args.pointerCount,
+ args.pointerProperties, args.pointerCoords);
- if (args->id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID &&
- IdGenerator::getSource(args->id) == IdGenerator::Source::INPUT_READER &&
+ if (args.id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID &&
+ IdGenerator::getSource(args.id) == IdGenerator::Source::INPUT_READER &&
!mInputFilterEnabled) {
- const bool isDown = args->action == AMOTION_EVENT_ACTION_DOWN;
- mLatencyTracker.trackListener(args->id, isDown, args->eventTime, args->readTime);
+ const bool isDown = args.action == AMOTION_EVENT_ACTION_DOWN;
+ mLatencyTracker.trackListener(args.id, isDown, args.eventTime, args.readTime);
}
needWake = enqueueInboundEventLocked(std::move(newEntry));
@@ -4277,12 +4272,12 @@
}
}
-void InputDispatcher::notifySensor(const NotifySensorArgs* args) {
+void InputDispatcher::notifySensor(const NotifySensorArgs& args) {
if (debugInboundEventDetails()) {
ALOGD("notifySensor - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, "
" sensorType=%s",
- args->id, args->eventTime, args->deviceId, args->source,
- ftl::enum_string(args->sensorType).c_str());
+ args.id, args.eventTime, args.deviceId, args.source,
+ ftl::enum_string(args.sensorType).c_str());
}
bool needWake = false;
@@ -4291,10 +4286,9 @@
// Just enqueue a new sensor event.
std::unique_ptr<SensorEntry> newEntry =
- std::make_unique<SensorEntry>(args->id, args->eventTime, args->deviceId,
- args->source, /* policyFlags=*/0, args->hwTimestamp,
- args->sensorType, args->accuracy,
- args->accuracyChanged, args->values);
+ std::make_unique<SensorEntry>(args.id, args.eventTime, args.deviceId, args.source,
+ /* policyFlags=*/0, args.hwTimestamp, args.sensorType,
+ args.accuracy, args.accuracyChanged, args.values);
needWake = enqueueInboundEventLocked(std::move(newEntry));
mLock.unlock();
@@ -4305,34 +4299,34 @@
}
}
-void InputDispatcher::notifyVibratorState(const NotifyVibratorStateArgs* args) {
+void InputDispatcher::notifyVibratorState(const NotifyVibratorStateArgs& args) {
if (debugInboundEventDetails()) {
- ALOGD("notifyVibratorState - eventTime=%" PRId64 ", device=%d, isOn=%d", args->eventTime,
- args->deviceId, args->isOn);
+ ALOGD("notifyVibratorState - eventTime=%" PRId64 ", device=%d, isOn=%d", args.eventTime,
+ args.deviceId, args.isOn);
}
- mPolicy->notifyVibratorState(args->deviceId, args->isOn);
+ mPolicy->notifyVibratorState(args.deviceId, args.isOn);
}
-bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) {
+bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs& args) {
return mInputFilterEnabled;
}
-void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
+void InputDispatcher::notifySwitch(const NotifySwitchArgs& args) {
if (debugInboundEventDetails()) {
ALOGD("notifySwitch - eventTime=%" PRId64 ", policyFlags=0x%x, switchValues=0x%08x, "
"switchMask=0x%08x",
- args->eventTime, args->policyFlags, args->switchValues, args->switchMask);
+ args.eventTime, args.policyFlags, args.switchValues, args.switchMask);
}
- uint32_t policyFlags = args->policyFlags;
+ uint32_t policyFlags = args.policyFlags;
policyFlags |= POLICY_FLAG_TRUSTED;
- mPolicy->notifySwitch(args->eventTime, args->switchValues, args->switchMask, policyFlags);
+ mPolicy->notifySwitch(args.eventTime, args.switchValues, args.switchMask, policyFlags);
}
-void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
+void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
if (debugInboundEventDetails()) {
- ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d", args->eventTime,
- args->deviceId);
+ ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d", args.eventTime,
+ args.deviceId);
}
bool needWake = false;
@@ -4340,7 +4334,7 @@
std::scoped_lock _l(mLock);
std::unique_ptr<DeviceResetEntry> newEntry =
- std::make_unique<DeviceResetEntry>(args->id, args->eventTime, args->deviceId);
+ std::make_unique<DeviceResetEntry>(args.id, args.eventTime, args.deviceId);
needWake = enqueueInboundEventLocked(std::move(newEntry));
} // release lock
@@ -4349,17 +4343,17 @@
}
}
-void InputDispatcher::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
+void InputDispatcher::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) {
if (debugInboundEventDetails()) {
- ALOGD("notifyPointerCaptureChanged - eventTime=%" PRId64 ", enabled=%s", args->eventTime,
- args->request.enable ? "true" : "false");
+ ALOGD("notifyPointerCaptureChanged - eventTime=%" PRId64 ", enabled=%s", args.eventTime,
+ args.request.enable ? "true" : "false");
}
bool needWake = false;
{ // acquire lock
std::scoped_lock _l(mLock);
- auto entry = std::make_unique<PointerCaptureChangedEntry>(args->id, args->eventTime,
- args->request);
+ auto entry =
+ std::make_unique<PointerCaptureChangedEntry>(args.id, args.eventTime, args.request);
needWake = enqueueInboundEventLocked(std::move(entry));
} // release lock
@@ -4374,10 +4368,10 @@
std::chrono::milliseconds timeout,
uint32_t policyFlags) {
if (debugInboundEventDetails()) {
- ALOGD("injectInputEvent - eventType=%d, targetUid=%s, syncMode=%d, timeout=%lld, "
- "policyFlags=0x%08x",
- event->getType(), targetUid ? std::to_string(*targetUid).c_str() : "none", syncMode,
- timeout.count(), policyFlags);
+ LOG(DEBUG) << __func__ << ": targetUid=" << toString(targetUid)
+ << ", syncMode=" << ftl::enum_string(syncMode) << ", timeout=" << timeout.count()
+ << "ms, policyFlags=0x" << std::hex << policyFlags << std::dec
+ << ", event=" << *event;
}
nsecs_t endTime = now() + std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count();
@@ -4396,7 +4390,7 @@
std::queue<std::unique_ptr<EventEntry>> injectedEntries;
switch (event->getType()) {
- case AINPUT_EVENT_TYPE_KEY: {
+ case InputEventType::KEY: {
const KeyEvent& incomingKey = static_cast<const KeyEvent&>(*event);
int32_t action = incomingKey.getAction();
if (!validateKeyEvent(action)) {
@@ -4442,7 +4436,7 @@
break;
}
- case AINPUT_EVENT_TYPE_MOTION: {
+ case InputEventType::MOTION: {
const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
const int32_t action = motionEvent.getAction();
const bool isPointerEvent =
@@ -4518,7 +4512,7 @@
}
default:
- ALOGW("Cannot inject %s events", inputEventTypeToString(event->getType()));
+ LOG(WARNING) << "Cannot inject " << ftl::enum_string(event->getType()) << " events";
return InputEventInjectionResult::FAILED;
}
@@ -4608,14 +4602,14 @@
std::array<uint8_t, 32> calculatedHmac;
std::unique_ptr<VerifiedInputEvent> result;
switch (event.getType()) {
- case AINPUT_EVENT_TYPE_KEY: {
+ case InputEventType::KEY: {
const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event);
VerifiedKeyEvent verifiedKeyEvent = verifiedKeyEventFromKeyEvent(keyEvent);
result = std::make_unique<VerifiedKeyEvent>(verifiedKeyEvent);
calculatedHmac = sign(verifiedKeyEvent);
break;
}
- case AINPUT_EVENT_TYPE_MOTION: {
+ case InputEventType::MOTION: {
const MotionEvent& motionEvent = static_cast<const MotionEvent&>(event);
VerifiedMotionEvent verifiedMotionEvent =
verifiedMotionEventFromMotionEvent(motionEvent);
@@ -5517,14 +5511,14 @@
windowInfo->frameTop, windowInfo->frameRight,
windowInfo->frameBottom, windowInfo->globalScaleFactor,
windowInfo->applicationInfo.name.c_str(),
- toString(windowInfo->applicationInfo.token).c_str());
+ binderToString(windowInfo->applicationInfo.token).c_str());
dump += dumpRegion(windowInfo->touchableRegion);
dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%" PRId64
"ms, hasToken=%s, "
"touchOcclusionMode=%s\n",
windowInfo->ownerPid, windowInfo->ownerUid,
millis(windowInfo->dispatchingTimeout),
- toString(windowInfo->token != nullptr),
+ binderToString(windowInfo->token).c_str(),
toString(windowInfo->touchOcclusionMode).c_str());
windowInfo->transform.dump(dump, "transform", INDENT4);
}
@@ -6199,7 +6193,7 @@
// Get the fallback key state.
// Clear it out after dispatching the UP.
int32_t originalKeyCode = keyEntry.keyCode;
- int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
+ std::optional<int32_t> fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
if (keyEntry.action == AKEY_EVENT_ACTION_UP) {
connection->inputState.removeFallbackKey(originalKeyCode);
}
@@ -6208,7 +6202,7 @@
// If the application handles the original key for which we previously
// generated a fallback or if the window is not a foreground window,
// then cancel the associated fallback key, if any.
- if (fallbackKeyCode != -1) {
+ if (fallbackKeyCode) {
// Dispatch the unhandled key to the policy with the cancel flag.
if (DEBUG_OUTBOUND_EVENT_DETAILS) {
ALOGD("Unhandled key event: Asking policy to cancel fallback action. "
@@ -6227,12 +6221,12 @@
mLock.lock();
// Cancel the fallback key.
- if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
+ if (*fallbackKeyCode != AKEYCODE_UNKNOWN) {
CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS,
"application handled the original non-fallback key "
"or is no longer a foreground target, "
"canceling previously dispatched fallback key");
- options.keyCode = fallbackKeyCode;
+ options.keyCode = *fallbackKeyCode;
synthesizeCancelationEventsForConnectionLocked(connection, options);
}
connection->inputState.removeFallbackKey(originalKeyCode);
@@ -6242,7 +6236,7 @@
// that we are in a good state to perform unhandled key event processing
// Then ask the policy what to do with it.
bool initialDown = keyEntry.action == AKEY_EVENT_ACTION_DOWN && keyEntry.repeatCount == 0;
- if (fallbackKeyCode == -1 && !initialDown) {
+ if (!fallbackKeyCode && !initialDown) {
if (DEBUG_OUTBOUND_EVENT_DETAILS) {
ALOGD("Unhandled key event: Skipping unhandled key event processing "
"since this is not an initial down. "
@@ -6277,53 +6271,53 @@
// The fallback keycode cannot change at any other point in the lifecycle.
if (initialDown) {
if (fallback) {
- fallbackKeyCode = event.getKeyCode();
+ *fallbackKeyCode = event.getKeyCode();
} else {
- fallbackKeyCode = AKEYCODE_UNKNOWN;
+ *fallbackKeyCode = AKEYCODE_UNKNOWN;
}
- connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
+ connection->inputState.setFallbackKey(originalKeyCode, *fallbackKeyCode);
}
- ALOG_ASSERT(fallbackKeyCode != -1);
+ ALOG_ASSERT(fallbackKeyCode);
// Cancel the fallback key if the policy decides not to send it anymore.
// We will continue to dispatch the key to the policy but we will no
// longer dispatch a fallback key to the application.
- if (fallbackKeyCode != AKEYCODE_UNKNOWN &&
- (!fallback || fallbackKeyCode != event.getKeyCode())) {
+ if (*fallbackKeyCode != AKEYCODE_UNKNOWN &&
+ (!fallback || *fallbackKeyCode != event.getKeyCode())) {
if (DEBUG_OUTBOUND_EVENT_DETAILS) {
if (fallback) {
ALOGD("Unhandled key event: Policy requested to send key %d"
"as a fallback for %d, but on the DOWN it had requested "
"to send %d instead. Fallback canceled.",
- event.getKeyCode(), originalKeyCode, fallbackKeyCode);
+ event.getKeyCode(), originalKeyCode, *fallbackKeyCode);
} else {
ALOGD("Unhandled key event: Policy did not request fallback for %d, "
"but on the DOWN it had requested to send %d. "
"Fallback canceled.",
- originalKeyCode, fallbackKeyCode);
+ originalKeyCode, *fallbackKeyCode);
}
}
CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS,
"canceling fallback, policy no longer desires it");
- options.keyCode = fallbackKeyCode;
+ options.keyCode = *fallbackKeyCode;
synthesizeCancelationEventsForConnectionLocked(connection, options);
fallback = false;
- fallbackKeyCode = AKEYCODE_UNKNOWN;
+ *fallbackKeyCode = AKEYCODE_UNKNOWN;
if (keyEntry.action != AKEY_EVENT_ACTION_UP) {
- connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
+ connection->inputState.setFallbackKey(originalKeyCode, *fallbackKeyCode);
}
}
if (DEBUG_OUTBOUND_EVENT_DETAILS) {
{
std::string msg;
- const KeyedVector<int32_t, int32_t>& fallbackKeys =
+ const std::map<int32_t, int32_t>& fallbackKeys =
connection->inputState.getFallbackKeys();
- for (size_t i = 0; i < fallbackKeys.size(); i++) {
- msg += StringPrintf(", %d->%d", fallbackKeys.keyAt(i), fallbackKeys.valueAt(i));
+ for (const auto& [key, value] : fallbackKeys) {
+ msg += StringPrintf(", %d->%d", key, value);
}
ALOGD("Unhandled key event: %zu currently tracked fallback keys%s.",
fallbackKeys.size(), msg.c_str());
@@ -6337,7 +6331,7 @@
keyEntry.source = event.getSource();
keyEntry.displayId = event.getDisplayId();
keyEntry.flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
- keyEntry.keyCode = fallbackKeyCode;
+ keyEntry.keyCode = *fallbackKeyCode;
keyEntry.scanCode = event.getScanCode();
keyEntry.metaState = event.getMetaState();
keyEntry.repeatCount = event.getRepeatCount();
@@ -6347,7 +6341,7 @@
if (DEBUG_OUTBOUND_EVENT_DETAILS) {
ALOGD("Unhandled key event: Dispatching fallback key. "
"originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
- originalKeyCode, fallbackKeyCode, keyEntry.metaState);
+ originalKeyCode, *fallbackKeyCode, keyEntry.metaState);
}
return true; // restart the event
} else {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 2246d47..4aba24c 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -93,14 +93,15 @@
status_t start() override;
status_t stop() override;
- void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
- void notifyKey(const NotifyKeyArgs* args) override;
- void notifyMotion(const NotifyMotionArgs* args) override;
- void notifySwitch(const NotifySwitchArgs* args) override;
- void notifySensor(const NotifySensorArgs* args) override;
- void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
- void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
- void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
+ void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override{};
+ void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
+ void notifyKey(const NotifyKeyArgs& args) override;
+ void notifyMotion(const NotifyMotionArgs& args) override;
+ void notifySwitch(const NotifySwitchArgs& args) override;
+ void notifySensor(const NotifySensorArgs& args) override;
+ void notifyVibratorState(const NotifyVibratorStateArgs& args) override;
+ void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
+ void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
android::os::InputEventInjectionResult injectInputEvent(
const InputEvent* event, std::optional<int32_t> targetUid,
@@ -331,8 +332,8 @@
REQUIRES(mLock);
// Input filter processing.
- bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) REQUIRES(mLock);
- bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) REQUIRES(mLock);
+ bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs& args) REQUIRES(mLock);
+ bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
// Inbound event processing.
void drainInboundQueueLocked() REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
index 94f3813..4652c2d 100644
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ b/services/inputflinger/dispatcher/InputState.cpp
@@ -42,13 +42,8 @@
switch (action) {
case AKEY_EVENT_ACTION_UP: {
if (entry.flags & AKEY_EVENT_FLAG_FALLBACK) {
- for (size_t i = 0; i < mFallbackKeys.size();) {
- if (mFallbackKeys.valueAt(i) == entry.keyCode) {
- mFallbackKeys.removeItemsAt(i);
- } else {
- i += 1;
- }
- }
+ std::erase_if(mFallbackKeys,
+ [&entry](const auto& item) { return item.second == entry.keyCode; });
}
ssize_t index = findKeyMemento(entry);
if (index >= 0) {
@@ -481,22 +476,20 @@
}
}
-int32_t InputState::getFallbackKey(int32_t originalKeyCode) {
- ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
- return index >= 0 ? mFallbackKeys.valueAt(index) : -1;
+std::optional<int32_t> InputState::getFallbackKey(int32_t originalKeyCode) {
+ auto it = mFallbackKeys.find(originalKeyCode);
+ if (it == mFallbackKeys.end()) {
+ return {};
+ }
+ return it->second;
}
void InputState::setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode) {
- ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
- if (index >= 0) {
- mFallbackKeys.replaceValueAt(index, fallbackKeyCode);
- } else {
- mFallbackKeys.add(originalKeyCode, fallbackKeyCode);
- }
+ mFallbackKeys.insert_or_assign(originalKeyCode, fallbackKeyCode);
}
void InputState::removeFallbackKey(int32_t originalKeyCode) {
- mFallbackKeys.removeItem(originalKeyCode);
+ mFallbackKeys.erase(originalKeyCode);
}
bool InputState::shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options) {
diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h
index d788e47..af2a3cb 100644
--- a/services/inputflinger/dispatcher/InputState.h
+++ b/services/inputflinger/dispatcher/InputState.h
@@ -62,9 +62,9 @@
void mergePointerStateTo(InputState& other);
// Gets the fallback key associated with a keycode.
- // Returns -1 if none.
+ // Returns std::nullopt if none.
// Returns AKEYCODE_UNKNOWN if we are only dispatching the unhandled key to the policy.
- int32_t getFallbackKey(int32_t originalKeyCode);
+ std::optional<int32_t> getFallbackKey(int32_t originalKeyCode);
// Sets the fallback key for a particular keycode.
void setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode);
@@ -72,7 +72,7 @@
// Removes the fallback key for a particular keycode.
void removeFallbackKey(int32_t originalKeyCode);
- inline const KeyedVector<int32_t, int32_t>& getFallbackKeys() const { return mFallbackKeys; }
+ inline const std::map<int32_t, int32_t>& getFallbackKeys() const { return mFallbackKeys; }
private:
struct KeyMemento {
@@ -113,7 +113,7 @@
std::vector<KeyMemento> mKeyMementos;
std::vector<MotionMemento> mMotionMementos;
- KeyedVector<int32_t, int32_t> mFallbackKeys;
+ std::map</*originalKeyCode*/int32_t, /*fallbackKeyCode*/int32_t> mFallbackKeys;
ssize_t findKeyMemento(const KeyEntry& entry) const;
ssize_t findMotionMemento(const MotionEntry& entry, bool hovering) const;
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index 1bb1968..4f78f03 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -37,14 +37,15 @@
InputListenerInterface& operator=(const InputListenerInterface&) = delete;
virtual ~InputListenerInterface() { }
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) = 0;
- virtual void notifyKey(const NotifyKeyArgs* args) = 0;
- virtual void notifyMotion(const NotifyMotionArgs* args) = 0;
- virtual void notifySwitch(const NotifySwitchArgs* args) = 0;
- virtual void notifySensor(const NotifySensorArgs* args) = 0;
- virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) = 0;
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;
- virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) = 0;
+ virtual void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) = 0;
+ virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) = 0;
+ virtual void notifyKey(const NotifyKeyArgs& args) = 0;
+ virtual void notifyMotion(const NotifyMotionArgs& args) = 0;
+ virtual void notifySwitch(const NotifySwitchArgs& args) = 0;
+ virtual void notifySensor(const NotifySensorArgs& args) = 0;
+ virtual void notifyVibratorState(const NotifyVibratorStateArgs& args) = 0;
+ virtual void notifyDeviceReset(const NotifyDeviceResetArgs& args) = 0;
+ virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) = 0;
void notify(const NotifyArgs& args);
};
@@ -58,14 +59,15 @@
public:
explicit QueuedInputListener(InputListenerInterface& innerListener);
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
- virtual void notifyKey(const NotifyKeyArgs* args) override;
- virtual void notifyMotion(const NotifyMotionArgs* args) override;
- virtual void notifySwitch(const NotifySwitchArgs* args) override;
- virtual void notifySensor(const NotifySensorArgs* args) override;
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
- void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
- void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
+ virtual void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
+ virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
+ virtual void notifyKey(const NotifyKeyArgs& args) override;
+ virtual void notifyMotion(const NotifyMotionArgs& args) override;
+ virtual void notifySwitch(const NotifySwitchArgs& args) override;
+ virtual void notifySensor(const NotifySensorArgs& args) override;
+ virtual void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
+ void notifyVibratorState(const NotifyVibratorStateArgs& args) override;
+ void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
void flush();
diff --git a/services/inputflinger/include/NotifyArgs.h b/services/inputflinger/include/NotifyArgs.h
index c46f905..7d29dd9 100644
--- a/services/inputflinger/include/NotifyArgs.h
+++ b/services/inputflinger/include/NotifyArgs.h
@@ -24,6 +24,21 @@
namespace android {
+/* Describes a change in any of the connected input devices. */
+struct NotifyInputDevicesChangedArgs {
+ int32_t id;
+ std::vector<InputDeviceInfo> inputDeviceInfos;
+
+ inline NotifyInputDevicesChangedArgs() {}
+
+ NotifyInputDevicesChangedArgs(int32_t id, std::vector<InputDeviceInfo> infos);
+
+ bool operator==(const NotifyInputDevicesChangedArgs& rhs) const = default;
+
+ NotifyInputDevicesChangedArgs(const NotifyInputDevicesChangedArgs& other) = default;
+ NotifyInputDevicesChangedArgs& operator=(const NotifyInputDevicesChangedArgs&) = default;
+};
+
/* Describes a configuration change event. */
struct NotifyConfigurationChangedArgs {
int32_t id;
@@ -36,6 +51,7 @@
bool operator==(const NotifyConfigurationChangedArgs& rhs) const = default;
NotifyConfigurationChangedArgs(const NotifyConfigurationChangedArgs& other) = default;
+ NotifyConfigurationChangedArgs& operator=(const NotifyConfigurationChangedArgs&) = default;
};
/* Describes a key event. */
@@ -65,6 +81,7 @@
bool operator==(const NotifyKeyArgs& rhs) const = default;
NotifyKeyArgs(const NotifyKeyArgs& other) = default;
+ NotifyKeyArgs& operator=(const NotifyKeyArgs&) = default;
};
/* Describes a motion event. */
@@ -115,7 +132,6 @@
const std::vector<TouchVideoFrame>& videoFrames);
NotifyMotionArgs(const NotifyMotionArgs& other);
-
NotifyMotionArgs& operator=(const android::NotifyMotionArgs&) = default;
bool operator==(const NotifyMotionArgs& rhs) const;
@@ -143,6 +159,7 @@
bool accuracyChanged, nsecs_t hwTimestamp, std::vector<float> values);
NotifySensorArgs(const NotifySensorArgs& other) = default;
+ NotifySensorArgs& operator=(const NotifySensorArgs&) = default;
};
/* Describes a switch event. */
@@ -160,6 +177,7 @@
uint32_t switchMask);
NotifySwitchArgs(const NotifySwitchArgs& other) = default;
+ NotifySwitchArgs& operator=(const NotifySwitchArgs&) = default;
bool operator==(const NotifySwitchArgs& rhs) const = default;
};
@@ -177,13 +195,13 @@
NotifyDeviceResetArgs(int32_t id, nsecs_t eventTime, int32_t deviceId);
NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other) = default;
+ NotifyDeviceResetArgs& operator=(const NotifyDeviceResetArgs&) = default;
bool operator==(const NotifyDeviceResetArgs& rhs) const = default;
};
/* Describes a change in the state of Pointer Capture. */
struct NotifyPointerCaptureChangedArgs {
- // The sequence number of the Pointer Capture request, if enabled.
int32_t id;
nsecs_t eventTime;
@@ -194,6 +212,7 @@
NotifyPointerCaptureChangedArgs(int32_t id, nsecs_t eventTime, const PointerCaptureRequest&);
NotifyPointerCaptureChangedArgs(const NotifyPointerCaptureChangedArgs& other) = default;
+ NotifyPointerCaptureChangedArgs& operator=(const NotifyPointerCaptureChangedArgs&) = default;
};
/* Describes a vibrator state event. */
@@ -209,11 +228,13 @@
NotifyVibratorStateArgs(int32_t id, nsecs_t eventTIme, int32_t deviceId, bool isOn);
NotifyVibratorStateArgs(const NotifyVibratorStateArgs& other) = default;
+ NotifyVibratorStateArgs& operator=(const NotifyVibratorStateArgs&) = default;
};
-using NotifyArgs = std::variant<NotifyConfigurationChangedArgs, NotifyKeyArgs, NotifyMotionArgs,
- NotifySensorArgs, NotifySwitchArgs, NotifyDeviceResetArgs,
- NotifyPointerCaptureChangedArgs, NotifyVibratorStateArgs>;
+using NotifyArgs =
+ std::variant<NotifyInputDevicesChangedArgs, NotifyConfigurationChangedArgs, NotifyKeyArgs,
+ NotifyMotionArgs, NotifySensorArgs, NotifySwitchArgs, NotifyDeviceResetArgs,
+ NotifyPointerCaptureChangedArgs, NotifyVibratorStateArgs>;
const char* toString(const NotifyArgs& args);
diff --git a/services/inputflinger/include/UnwantedInteractionBlockerInterface.h b/services/inputflinger/include/UnwantedInteractionBlockerInterface.h
index 1a6f847..64c6114 100644
--- a/services/inputflinger/include/UnwantedInteractionBlockerInterface.h
+++ b/services/inputflinger/include/UnwantedInteractionBlockerInterface.h
@@ -27,23 +27,13 @@
*/
class UnwantedInteractionBlockerInterface : public InputListenerInterface {
public:
- /* Notifies the input reader policy that some input devices have changed
- * and provides information about all current input devices.
- * Important! This call should happen on the same thread as the calls to the
- * InputListenerInterface methods.
- * That is, same thread should call 'notifyMotion' and 'notifyInputDevicesChanged' and
- * 'notifyDeviceReset'. If this architecture changes, we will need to make the implementation
- * of this interface thread-safe.
- */
- virtual void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) = 0;
-
/**
* Dump the state of the interaction blocker.
* This method may be called on any thread (usually by the input manager on a binder thread).
*/
virtual void dump(std::string& dump) = 0;
- /* Called by the heatbeat to ensures that the blocker has not deadlocked. */
+ /* Called by the heartbeat to ensures that the blocker has not deadlocked. */
virtual void monitor() = 0;
UnwantedInteractionBlockerInterface() {}
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index eaed987..b5ee044 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -146,98 +146,23 @@
}
}
-void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
+void InputDevice::addEmptyEventHubDevice(int32_t eventHubId) {
if (mDevices.find(eventHubId) != mDevices.end()) {
return;
}
std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
- ftl::Flags<InputDeviceClass> classes = contextPtr->getDeviceClasses();
std::vector<std::unique_ptr<InputMapper>> mappers;
- // Check if we should skip population
- if (!populateMappers) {
- mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
+ mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
+}
+
+void InputDevice::addEventHubDevice(int32_t eventHubId,
+ const InputReaderConfiguration& readerConfig) {
+ if (mDevices.find(eventHubId) != mDevices.end()) {
return;
}
-
- // Switch-like devices.
- if (classes.test(InputDeviceClass::SWITCH)) {
- mappers.push_back(std::make_unique<SwitchInputMapper>(*contextPtr));
- }
-
- // Scroll wheel-like devices.
- if (classes.test(InputDeviceClass::ROTARY_ENCODER)) {
- mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(*contextPtr));
- }
-
- // Vibrator-like devices.
- if (classes.test(InputDeviceClass::VIBRATOR)) {
- mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
- }
-
- // Battery-like devices or light-containing devices.
- // PeripheralController will be created with associated EventHub device.
- if (classes.test(InputDeviceClass::BATTERY) || classes.test(InputDeviceClass::LIGHT)) {
- mController = std::make_unique<PeripheralController>(*contextPtr);
- }
-
- // Keyboard-like devices.
- uint32_t keyboardSource = 0;
- int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
- if (classes.test(InputDeviceClass::KEYBOARD)) {
- keyboardSource |= AINPUT_SOURCE_KEYBOARD;
- }
- if (classes.test(InputDeviceClass::ALPHAKEY)) {
- keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
- }
- if (classes.test(InputDeviceClass::DPAD)) {
- keyboardSource |= AINPUT_SOURCE_DPAD;
- }
- if (classes.test(InputDeviceClass::GAMEPAD)) {
- keyboardSource |= AINPUT_SOURCE_GAMEPAD;
- }
-
- if (keyboardSource != 0) {
- mappers.push_back(
- std::make_unique<KeyboardInputMapper>(*contextPtr, keyboardSource, keyboardType));
- }
-
- // Cursor-like devices.
- if (classes.test(InputDeviceClass::CURSOR)) {
- mappers.push_back(std::make_unique<CursorInputMapper>(*contextPtr));
- }
-
- // Touchscreens and touchpad devices.
- static const bool ENABLE_TOUCHPAD_GESTURES_LIBRARY =
- sysprop::InputProperties::enable_touchpad_gestures_library().value_or(true);
- // TODO(b/272518665): Fix the new touchpad stack for Sony DualShock 4 (5c4, 9cc) touchpads, or
- // at least load this setting from the IDC file.
- const InputDeviceIdentifier identifier = contextPtr->getDeviceIdentifier();
- const bool isSonyDualShock4Touchpad = identifier.vendor == 0x054c &&
- (identifier.product == 0x05c4 || identifier.product == 0x09cc);
- if (ENABLE_TOUCHPAD_GESTURES_LIBRARY && classes.test(InputDeviceClass::TOUCHPAD) &&
- classes.test(InputDeviceClass::TOUCH_MT) && !isSonyDualShock4Touchpad) {
- mappers.push_back(std::make_unique<TouchpadInputMapper>(*contextPtr));
- } else if (classes.test(InputDeviceClass::TOUCH_MT)) {
- mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
- } else if (classes.test(InputDeviceClass::TOUCH)) {
- mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
- }
-
- // Joystick-like devices.
- if (classes.test(InputDeviceClass::JOYSTICK)) {
- mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr));
- }
-
- // Motion sensor enabled devices.
- if (classes.test(InputDeviceClass::SENSOR)) {
- mappers.push_back(std::make_unique<SensorInputMapper>(*contextPtr));
- }
-
- // External stylus-like devices.
- if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) {
- mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr));
- }
+ std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
+ std::vector<std::unique_ptr<InputMapper>> mappers = createMappers(*contextPtr, readerConfig);
// insert the context into the devices set
mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
@@ -253,7 +178,8 @@
mDevices.erase(eventHubId);
}
-std::list<NotifyArgs> InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config,
+std::list<NotifyArgs> InputDevice::configure(nsecs_t when,
+ const InputReaderConfiguration& readerConfig,
uint32_t changes) {
std::list<NotifyArgs> out;
mSources = 0;
@@ -291,7 +217,7 @@
});
mAssociatedDeviceType =
- getValueByKey(config->deviceTypeAssociations, mIdentifier.location);
+ getValueByKey(readerConfig.deviceTypeAssociations, mIdentifier.location);
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
@@ -325,8 +251,8 @@
// Do not execute this code on the first configure, because 'setEnabled' would call
// InputMapper::reset, and you can't reset a mapper before it has been configured.
// The mappers are configured for the first time at the bottom of this function.
- auto it = config->disabledDevices.find(mId);
- bool enabled = it == config->disabledDevices.end();
+ auto it = readerConfig.disabledDevices.find(mId);
+ bool enabled = it == readerConfig.disabledDevices.end();
out += setEnabled(enabled, when);
}
@@ -338,13 +264,14 @@
// Find the display port that corresponds to the current input port.
const std::string& inputPort = mIdentifier.location;
if (!inputPort.empty()) {
- const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations;
+ const std::unordered_map<std::string, uint8_t>& ports =
+ readerConfig.portAssociations;
const auto& displayPort = ports.find(inputPort);
if (displayPort != ports.end()) {
mAssociatedDisplayPort = std::make_optional(displayPort->second);
} else {
const std::unordered_map<std::string, std::string>& displayUniqueIds =
- config->uniqueIdAssociations;
+ readerConfig.uniqueIdAssociations;
const auto& displayUniqueId = displayUniqueIds.find(inputPort);
if (displayUniqueId != displayUniqueIds.end()) {
mAssociatedDisplayUniqueId = displayUniqueId->second;
@@ -356,9 +283,11 @@
// "disabledDevices" list. If it is associated with a specific display, and it was not
// explicitly disabled, then enable/disable the device based on whether we can find the
// corresponding viewport.
- bool enabled = (config->disabledDevices.find(mId) == config->disabledDevices.end());
+ bool enabled =
+ (readerConfig.disabledDevices.find(mId) == readerConfig.disabledDevices.end());
if (mAssociatedDisplayPort) {
- mAssociatedViewport = config->getDisplayViewportByPort(*mAssociatedDisplayPort);
+ mAssociatedViewport =
+ readerConfig.getDisplayViewportByPort(*mAssociatedDisplayPort);
if (!mAssociatedViewport) {
ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
"but the corresponding viewport is not found.",
@@ -367,7 +296,7 @@
}
} else if (mAssociatedDisplayUniqueId != std::nullopt) {
mAssociatedViewport =
- config->getDisplayViewportByUniqueId(*mAssociatedDisplayUniqueId);
+ readerConfig.getDisplayViewportByUniqueId(*mAssociatedDisplayUniqueId);
if (!mAssociatedViewport) {
ALOGW("Input device %s should be associated with display %s but the "
"corresponding viewport cannot be found",
@@ -384,15 +313,16 @@
}
}
- for_each_mapper([this, when, &config, changes, &out](InputMapper& mapper) {
- out += mapper.reconfigure(when, config, changes);
+ for_each_mapper([this, when, &readerConfig, changes, &out](InputMapper& mapper) {
+ out += mapper.reconfigure(when, readerConfig, changes);
mSources |= mapper.getSources();
});
// If a device is just plugged but it might be disabled, we need to update some info like
// axis range of touch from each InputMapper first, then disable it.
if (!changes) {
- out += setEnabled(config->disabledDevices.find(mId) == config->disabledDevices.end(),
+ out += setEnabled(readerConfig.disabledDevices.find(mId) ==
+ readerConfig.disabledDevices.end(),
when);
}
}
@@ -507,6 +437,92 @@
return result;
}
+std::vector<std::unique_ptr<InputMapper>> InputDevice::createMappers(
+ InputDeviceContext& contextPtr, const InputReaderConfiguration& readerConfig) {
+ ftl::Flags<InputDeviceClass> classes = contextPtr.getDeviceClasses();
+ std::vector<std::unique_ptr<InputMapper>> mappers;
+
+ // Switch-like devices.
+ if (classes.test(InputDeviceClass::SWITCH)) {
+ mappers.push_back(std::make_unique<SwitchInputMapper>(contextPtr, readerConfig));
+ }
+
+ // Scroll wheel-like devices.
+ if (classes.test(InputDeviceClass::ROTARY_ENCODER)) {
+ mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(contextPtr, readerConfig));
+ }
+
+ // Vibrator-like devices.
+ if (classes.test(InputDeviceClass::VIBRATOR)) {
+ mappers.push_back(std::make_unique<VibratorInputMapper>(contextPtr, readerConfig));
+ }
+
+ // Battery-like devices or light-containing devices.
+ // PeripheralController will be created with associated EventHub device.
+ if (classes.test(InputDeviceClass::BATTERY) || classes.test(InputDeviceClass::LIGHT)) {
+ mController = std::make_unique<PeripheralController>(contextPtr);
+ }
+
+ // Keyboard-like devices.
+ uint32_t keyboardSource = 0;
+ int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
+ if (classes.test(InputDeviceClass::KEYBOARD)) {
+ keyboardSource |= AINPUT_SOURCE_KEYBOARD;
+ }
+ if (classes.test(InputDeviceClass::ALPHAKEY)) {
+ keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
+ }
+ if (classes.test(InputDeviceClass::DPAD)) {
+ keyboardSource |= AINPUT_SOURCE_DPAD;
+ }
+ if (classes.test(InputDeviceClass::GAMEPAD)) {
+ keyboardSource |= AINPUT_SOURCE_GAMEPAD;
+ }
+
+ if (keyboardSource != 0) {
+ mappers.push_back(std::make_unique<KeyboardInputMapper>(contextPtr, readerConfig,
+ keyboardSource, keyboardType));
+ }
+
+ // Cursor-like devices.
+ if (classes.test(InputDeviceClass::CURSOR)) {
+ mappers.push_back(std::make_unique<CursorInputMapper>(contextPtr, readerConfig));
+ }
+
+ // Touchscreens and touchpad devices.
+ static const bool ENABLE_TOUCHPAD_GESTURES_LIBRARY =
+ sysprop::InputProperties::enable_touchpad_gestures_library().value_or(true);
+ // TODO(b/272518665): Fix the new touchpad stack for Sony DualShock 4 (5c4, 9cc) touchpads, or
+ // at least load this setting from the IDC file.
+ const InputDeviceIdentifier identifier = contextPtr.getDeviceIdentifier();
+ const bool isSonyDualShock4Touchpad = identifier.vendor == 0x054c &&
+ (identifier.product == 0x05c4 || identifier.product == 0x09cc);
+ if (ENABLE_TOUCHPAD_GESTURES_LIBRARY && classes.test(InputDeviceClass::TOUCHPAD) &&
+ classes.test(InputDeviceClass::TOUCH_MT) && !isSonyDualShock4Touchpad) {
+ mappers.push_back(std::make_unique<TouchpadInputMapper>(contextPtr, readerConfig));
+ } else if (classes.test(InputDeviceClass::TOUCH_MT)) {
+ mappers.push_back(std::make_unique<MultiTouchInputMapper>(contextPtr, readerConfig));
+ } else if (classes.test(InputDeviceClass::TOUCH)) {
+ mappers.push_back(std::make_unique<SingleTouchInputMapper>(contextPtr, readerConfig));
+ }
+
+ // Joystick-like devices.
+ if (classes.test(InputDeviceClass::JOYSTICK)) {
+ mappers.push_back(std::make_unique<JoystickInputMapper>(contextPtr, readerConfig));
+ }
+
+ // Motion sensor enabled devices.
+ if (classes.test(InputDeviceClass::SENSOR)) {
+ mappers.push_back(std::make_unique<SensorInputMapper>(contextPtr, readerConfig));
+ }
+
+ // External stylus-like devices.
+ if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) {
+ mappers.push_back(std::make_unique<ExternalStylusInputMapper>(contextPtr, readerConfig));
+ }
+ return mappers;
+}
+
bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) {
bool result = false;
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 81ac03b..0afe79d 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -157,6 +157,8 @@
if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
inputDevices = getInputDevicesLocked();
+ notifyArgs.emplace_back(
+ NotifyInputDevicesChangedArgs{mContext.getNextId(), inputDevices});
}
} // release lock
@@ -234,7 +236,7 @@
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
- notifyAll(device->configure(when, &mConfig, 0));
+ notifyAll(device->configure(when, mConfig, 0));
notifyAll(device->reset(when));
if (device->isIgnored()) {
@@ -310,7 +312,7 @@
std::list<NotifyArgs> resetEvents;
if (device->hasEventHubDevices()) {
- resetEvents += device->configure(when, &mConfig, 0);
+ resetEvents += device->configure(when, mConfig, 0);
}
resetEvents += device->reset(when);
notifyAll(std::move(resetEvents));
@@ -332,7 +334,7 @@
device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),
identifier);
}
- device->addEventHubDevice(eventHubId);
+ device->addEventHubDevice(eventHubId, mConfig);
return device;
}
@@ -385,8 +387,7 @@
updateGlobalMetaStateLocked();
// Enqueue configuration changed.
- NotifyConfigurationChangedArgs args(mContext.getNextId(), when);
- mQueuedListener.notifyConfigurationChanged(&args);
+ mQueuedListener.notifyConfigurationChanged({mContext.getNextId(), when});
}
void InputReader::refreshConfigurationLocked(uint32_t changes) {
@@ -408,7 +409,7 @@
} else {
for (auto& devicePair : mDevices) {
std::shared_ptr<InputDevice>& device = devicePair.second;
- notifyAll(device->configure(now, &mConfig, changes));
+ notifyAll(device->configure(now, mConfig, changes));
}
}
@@ -418,9 +419,8 @@
"There was no change in the pointer capture state.");
} else {
mCurrentPointerCaptureRequest = mConfig.pointerCaptureRequest;
- const NotifyPointerCaptureChangedArgs args(mContext.getNextId(), now,
- mCurrentPointerCaptureRequest);
- mQueuedListener.notifyPointerCaptureChanged(&args);
+ mQueuedListener.notifyPointerCaptureChanged(
+ {mContext.getNextId(), now, mCurrentPointerCaptureRequest});
}
}
}
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 4ae06fe..2091e16 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -80,10 +80,11 @@
[[nodiscard]] std::list<NotifyArgs> setEnabled(bool enabled, nsecs_t when);
void dump(std::string& dump, const std::string& eventHubDevStr);
- void addEventHubDevice(int32_t eventHubId, bool populateMappers = true);
+ void addEmptyEventHubDevice(int32_t eventHubId);
+ void addEventHubDevice(int32_t eventHubId, const InputReaderConfiguration& readerConfig);
void removeEventHubDevice(int32_t eventHubId);
[[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& readerConfig,
uint32_t changes);
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when);
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvents, size_t count);
@@ -137,7 +138,7 @@
template <class T, typename... Args>
T& addMapper(int32_t eventHubId, Args... args) {
// ensure a device entry exists for this eventHubId
- addEventHubDevice(eventHubId, false);
+ addEmptyEventHubDevice(eventHubId);
// create mapper
auto& devicePair = mDevices[eventHubId];
@@ -152,7 +153,7 @@
template <class T>
T& addController(int32_t eventHubId) {
// ensure a device entry exists for this eventHubId
- addEventHubDevice(eventHubId, false);
+ addEmptyEventHubDevice(eventHubId);
// create controller
auto& devicePair = mDevices[eventHubId];
@@ -191,6 +192,9 @@
typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
+ std::vector<std::unique_ptr<InputMapper>> createMappers(
+ InputDeviceContext& contextPtr, const InputReaderConfiguration& readerConfig);
+
PropertyMap mConfiguration;
// helpers to interate over the devices collection
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index d7dc2ae..adc893b 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -68,8 +68,12 @@
// --- CursorInputMapper ---
-CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext)
- : InputMapper(deviceContext), mLastEventTime(std::numeric_limits<nsecs_t>::min()) {}
+CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : InputMapper(deviceContext, readerConfig),
+ mLastEventTime(std::numeric_limits<nsecs_t>::min()) {
+ configureWithZeroChanges(readerConfig);
+}
CursorInputMapper::~CursorInputMapper() {
if (mPointerController != nullptr) {
@@ -134,119 +138,28 @@
}
std::list<NotifyArgs> CursorInputMapper::reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& readerConfig,
uint32_t changes) {
- std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
+ std::list<NotifyArgs> out = InputMapper::reconfigure(when, readerConfig, changes);
- if (!changes) { // first time only
- mCursorScrollAccumulator.configure(getDeviceContext());
-
- // Configure basic parameters.
- configureParameters();
-
- // Configure device mode.
- switch (mParameters.mode) {
- case Parameters::Mode::POINTER_RELATIVE:
- // Should not happen during first time configuration.
- ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
- mParameters.mode = Parameters::Mode::POINTER;
- [[fallthrough]];
- case Parameters::Mode::POINTER:
- mSource = AINPUT_SOURCE_MOUSE;
- mXPrecision = 1.0f;
- mYPrecision = 1.0f;
- mXScale = 1.0f;
- mYScale = 1.0f;
- mPointerController = getContext()->getPointerController(getDeviceId());
- break;
- case Parameters::Mode::NAVIGATION:
- mSource = AINPUT_SOURCE_TRACKBALL;
- mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
- mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
- mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
- mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
- break;
- }
-
- mVWheelScale = 1.0f;
- mHWheelScale = 1.0f;
+ if (!changes) {
+ configureWithZeroChanges(readerConfig);
+ return out;
}
const bool configurePointerCapture = mParameters.mode != Parameters::Mode::NAVIGATION &&
- ((!changes && config->pointerCaptureRequest.enable) ||
- (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE));
+ (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
if (configurePointerCapture) {
- if (config->pointerCaptureRequest.enable) {
- if (mParameters.mode == Parameters::Mode::POINTER) {
- mParameters.mode = Parameters::Mode::POINTER_RELATIVE;
- mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
- // Keep PointerController around in order to preserve the pointer position.
- mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
- } else {
- ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
- }
- } else {
- if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) {
- mParameters.mode = Parameters::Mode::POINTER;
- mSource = AINPUT_SOURCE_MOUSE;
- } else {
- ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
- }
- }
- bumpGeneration();
- if (changes) {
- out.push_back(NotifyDeviceResetArgs(getContext()->getNextId(), when, getDeviceId()));
- }
+ configureOnPointerCapture(readerConfig);
+ out.push_back(NotifyDeviceResetArgs(getContext()->getNextId(), when, getDeviceId()));
}
- if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED) ||
- configurePointerCapture) {
- if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) {
- // Disable any acceleration or scaling for the pointer when Pointer Capture is enabled.
- mPointerVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
- mWheelXVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
- mWheelYVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
- } else {
- mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
- mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
- mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
- }
+ if ((changes & InputReaderConfiguration::CHANGE_POINTER_SPEED) || configurePointerCapture) {
+ configureOnChangePointerSpeed(readerConfig);
}
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO) ||
- configurePointerCapture) {
- const bool isPointer = mParameters.mode == Parameters::Mode::POINTER;
-
- mDisplayId = ADISPLAY_ID_NONE;
- if (auto viewport = mDeviceContext.getAssociatedViewport(); viewport) {
- // This InputDevice is associated with a viewport.
- // Only generate events for the associated display.
- const bool mismatchedPointerDisplay =
- isPointer && (viewport->displayId != mPointerController->getDisplayId());
- mDisplayId = mismatchedPointerDisplay ? std::nullopt
- : std::make_optional(viewport->displayId);
- } else if (isPointer) {
- // The InputDevice is not associated with a viewport, but it controls the mouse pointer.
- mDisplayId = mPointerController->getDisplayId();
- }
-
- mOrientation = ui::ROTATION_0;
- const bool isOrientedDevice =
- (mParameters.orientationAware && mParameters.hasAssociatedDisplay);
- // InputReader works in the un-rotated display coordinate space, so we don't need to do
- // anything if the device is already orientation-aware. If the device is not
- // orientation-aware, then we need to apply the inverse rotation of the display so that
- // when the display rotation is applied later as a part of the per-window transform, we
- // get the expected screen coordinates. When pointer capture is enabled, we do not apply any
- // rotations and report values directly from the input device.
- if (!isOrientedDevice && mDisplayId &&
- mParameters.mode != Parameters::Mode::POINTER_RELATIVE) {
- if (auto viewport = config->getDisplayViewportById(*mDisplayId); viewport) {
- mOrientation = getInverseRotation(viewport->orientation);
- }
- }
-
- bumpGeneration();
+ if ((changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO) || configurePointerCapture) {
+ configureOnChangeDisplayInfo(readerConfig);
}
return out;
}
@@ -511,4 +424,117 @@
return mDisplayId;
}
+void CursorInputMapper::configureWithZeroChanges(const InputReaderConfiguration& readerConfig) {
+ // Configuration with zero changes
+ configureBasicParams();
+ if (mParameters.mode != Parameters::Mode::NAVIGATION &&
+ readerConfig.pointerCaptureRequest.enable) {
+ configureOnPointerCapture(readerConfig);
+ }
+ configureOnChangePointerSpeed(readerConfig);
+ configureOnChangeDisplayInfo(readerConfig);
+}
+
+void CursorInputMapper::configureBasicParams() {
+ mCursorScrollAccumulator.configure(getDeviceContext());
+
+ // Configure basic parameters.
+ configureParameters();
+
+ // Configure device mode.
+ switch (mParameters.mode) {
+ case Parameters::Mode::POINTER_RELATIVE:
+ // Should not happen during first time configuration.
+ ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
+ mParameters.mode = Parameters::Mode::POINTER;
+ [[fallthrough]];
+ case Parameters::Mode::POINTER:
+ mSource = AINPUT_SOURCE_MOUSE;
+ mXPrecision = 1.0f;
+ mYPrecision = 1.0f;
+ mXScale = 1.0f;
+ mYScale = 1.0f;
+ mPointerController = getContext()->getPointerController(getDeviceId());
+ break;
+ case Parameters::Mode::NAVIGATION:
+ mSource = AINPUT_SOURCE_TRACKBALL;
+ mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
+ mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
+ mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
+ mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
+ break;
+ }
+
+ mVWheelScale = 1.0f;
+ mHWheelScale = 1.0f;
+}
+
+void CursorInputMapper::configureOnPointerCapture(const InputReaderConfiguration& config) {
+ if (config.pointerCaptureRequest.enable) {
+ if (mParameters.mode == Parameters::Mode::POINTER) {
+ mParameters.mode = Parameters::Mode::POINTER_RELATIVE;
+ mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
+ // Keep PointerController around in order to preserve the pointer position.
+ mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
+ } else {
+ ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
+ }
+ } else {
+ if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) {
+ mParameters.mode = Parameters::Mode::POINTER;
+ mSource = AINPUT_SOURCE_MOUSE;
+ } else {
+ ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
+ }
+ }
+ bumpGeneration();
+}
+
+void CursorInputMapper::configureOnChangePointerSpeed(const InputReaderConfiguration& config) {
+ if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) {
+ // Disable any acceleration or scaling for the pointer when Pointer Capture is enabled.
+ mPointerVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
+ mWheelXVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
+ mWheelYVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
+ } else {
+ mPointerVelocityControl.setParameters(config.pointerVelocityControlParameters);
+ mWheelXVelocityControl.setParameters(config.wheelVelocityControlParameters);
+ mWheelYVelocityControl.setParameters(config.wheelVelocityControlParameters);
+ }
+}
+
+void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfiguration& config) {
+ const bool isPointer = mParameters.mode == Parameters::Mode::POINTER;
+
+ mDisplayId = ADISPLAY_ID_NONE;
+ if (auto viewport = mDeviceContext.getAssociatedViewport(); viewport) {
+ // This InputDevice is associated with a viewport.
+ // Only generate events for the associated display.
+ const bool mismatchedPointerDisplay =
+ isPointer && (viewport->displayId != mPointerController->getDisplayId());
+ mDisplayId =
+ mismatchedPointerDisplay ? std::nullopt : std::make_optional(viewport->displayId);
+ } else if (isPointer) {
+ // The InputDevice is not associated with a viewport, but it controls the mouse pointer.
+ mDisplayId = mPointerController->getDisplayId();
+ }
+
+ mOrientation = ui::ROTATION_0;
+ const bool isOrientedDevice =
+ (mParameters.orientationAware && mParameters.hasAssociatedDisplay);
+ // InputReader works in the un-rotated display coordinate space, so we don't need to do
+ // anything if the device is already orientation-aware. If the device is not
+ // orientation-aware, then we need to apply the inverse rotation of the display so that
+ // when the display rotation is applied later as a part of the per-window transform, we
+ // get the expected screen coordinates. When pointer capture is enabled, we do not apply any
+ // rotations and report values directly from the input device.
+ if (!isOrientedDevice && mDisplayId && mParameters.mode != Parameters::Mode::POINTER_RELATIVE) {
+ if (auto viewport = config.getDisplayViewportById(*mDisplayId); viewport) {
+ mOrientation = getInverseRotation(viewport->orientation);
+ }
+ }
+
+ bumpGeneration();
+}
+
} // namespace android
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index 987b9de..a7cdd51 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -53,14 +53,15 @@
class CursorInputMapper : public InputMapper {
public:
- explicit CursorInputMapper(InputDeviceContext& deviceContext);
+ explicit CursorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
virtual ~CursorInputMapper();
virtual uint32_t getSources() const override;
virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
virtual void dump(std::string& dump) override;
[[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& readerConfig,
uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
@@ -126,6 +127,11 @@
void configureParameters();
void dumpParameters(std::string& dump);
+ void configureWithZeroChanges(const InputReaderConfiguration& readerConfig);
+ void configureBasicParams();
+ void configureOnPointerCapture(const InputReaderConfiguration& config);
+ void configureOnChangePointerSpeed(const InputReaderConfiguration& config);
+ void configureOnChangeDisplayInfo(const InputReaderConfiguration& config);
[[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when, nsecs_t readTime);
};
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
index c5a3075..7100f88 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
@@ -23,8 +23,9 @@
namespace android {
-ExternalStylusInputMapper::ExternalStylusInputMapper(InputDeviceContext& deviceContext)
- : InputMapper(deviceContext), mTouchButtonAccumulator(deviceContext) {}
+ExternalStylusInputMapper::ExternalStylusInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : InputMapper(deviceContext, readerConfig), mTouchButtonAccumulator(deviceContext) {}
uint32_t ExternalStylusInputMapper::getSources() const {
return AINPUT_SOURCE_STYLUS;
@@ -47,7 +48,7 @@
}
std::list<NotifyArgs> ExternalStylusInputMapper::reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) {
getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
mTouchButtonAccumulator.configure();
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
index 0df8cf7..7f926a7 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
@@ -26,14 +26,15 @@
class ExternalStylusInputMapper : public InputMapper {
public:
- explicit ExternalStylusInputMapper(InputDeviceContext& deviceContext);
+ explicit ExternalStylusInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
virtual ~ExternalStylusInputMapper() = default;
uint32_t getSources() const override;
void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
void dump(std::string& dump) override;
[[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp
index 9d1e9ce..bd86a5a 100644
--- a/services/inputflinger/reader/mapper/InputMapper.cpp
+++ b/services/inputflinger/reader/mapper/InputMapper.cpp
@@ -25,7 +25,9 @@
namespace android {
-InputMapper::InputMapper(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {}
+InputMapper::InputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : mDeviceContext(deviceContext) {}
InputMapper::~InputMapper() {}
@@ -35,7 +37,7 @@
void InputMapper::dump(std::string& dump) {}
-std::list<NotifyArgs> InputMapper::reconfigure(nsecs_t when, const InputReaderConfiguration* config,
+std::list<NotifyArgs> InputMapper::reconfigure(nsecs_t when, const InputReaderConfiguration& config,
uint32_t changes) {
return {};
}
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index bb15e4d..211be9f 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -31,16 +31,16 @@
* different classes of events.
*
* InputMapper lifecycle:
- * - create
- * - configure with 0 changes
+ * - create and configure with 0 changes
* - reset
- * - process, process, process (may occasionally reconfigure with non-zero changes or reset)
+ * - process, process, process (may occasionally reconfigure or reset)
* - reset
* - destroy
*/
class InputMapper {
public:
- explicit InputMapper(InputDeviceContext& deviceContext);
+ explicit InputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
virtual ~InputMapper();
inline int32_t getDeviceId() { return mDeviceContext.getId(); }
@@ -54,7 +54,7 @@
virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo);
virtual void dump(std::string& dump);
[[nodiscard]] virtual std::list<NotifyArgs> reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes);
[[nodiscard]] virtual std::list<NotifyArgs> reset(nsecs_t when);
[[nodiscard]] virtual std::list<NotifyArgs> process(const RawEvent* rawEvent) = 0;
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
index f60035b..3450f86 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
@@ -20,8 +20,9 @@
namespace android {
-JoystickInputMapper::JoystickInputMapper(InputDeviceContext& deviceContext)
- : InputMapper(deviceContext) {}
+JoystickInputMapper::JoystickInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : InputMapper(deviceContext, readerConfig) {}
JoystickInputMapper::~JoystickInputMapper() {}
@@ -104,7 +105,7 @@
}
std::list<NotifyArgs> JoystickInputMapper::reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) {
std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.h b/services/inputflinger/reader/mapper/JoystickInputMapper.h
index 9adb07f..c9e92de 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.h
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.h
@@ -22,14 +22,15 @@
class JoystickInputMapper : public InputMapper {
public:
- explicit JoystickInputMapper(InputDeviceContext& deviceContext);
+ explicit JoystickInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
virtual ~JoystickInputMapper();
virtual uint32_t getSources() const override;
virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
virtual void dump(std::string& dump) override;
[[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index fc00c48..63ea3a8 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -63,9 +63,10 @@
// --- KeyboardInputMapper ---
-KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext, uint32_t source,
- int32_t keyboardType)
- : InputMapper(deviceContext), mSource(source), mKeyboardType(keyboardType) {}
+KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ uint32_t source, int32_t keyboardType)
+ : InputMapper(deviceContext, readerConfig), mSource(source), mKeyboardType(keyboardType) {}
uint32_t KeyboardInputMapper::getSources() const {
return mSource;
@@ -118,21 +119,21 @@
}
std::optional<DisplayViewport> KeyboardInputMapper::findViewport(
- const InputReaderConfiguration* config) {
+ const InputReaderConfiguration& readerConfig) {
if (getDeviceContext().getAssociatedViewport()) {
return getDeviceContext().getAssociatedViewport();
}
// No associated display defined, try to find default display if orientationAware.
if (mParameters.orientationAware) {
- return config->getDisplayViewportByType(ViewportType::INTERNAL);
+ return readerConfig.getDisplayViewportByType(ViewportType::INTERNAL);
}
return std::nullopt;
}
std::list<NotifyArgs> KeyboardInputMapper::reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) {
std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
@@ -147,7 +148,7 @@
if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUT_ASSOCIATION)) {
mKeyboardLayoutInfo =
- getValueByKey(config->keyboardLayoutAssociations, getDeviceContext().getLocation());
+ getValueByKey(config.keyboardLayoutAssociations, getDeviceContext().getLocation());
}
return out;
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
index 52576c3..25fad57 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
@@ -23,14 +23,16 @@
class KeyboardInputMapper : public InputMapper {
public:
- KeyboardInputMapper(InputDeviceContext& deviceContext, uint32_t source, int32_t keyboardType);
+ KeyboardInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig, uint32_t source,
+ int32_t keyboardType);
~KeyboardInputMapper() override = default;
uint32_t getSources() const override;
void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
void dump(std::string& dump) override;
[[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
@@ -96,7 +98,7 @@
void resetLedState();
void initializeLedState(LedState& ledState, int32_t led);
void updateLedStateForModifier(LedState& ledState, int32_t led, int32_t modifier, bool reset);
- std::optional<DisplayViewport> findViewport(const InputReaderConfiguration* config);
+ std::optional<DisplayViewport> findViewport(const InputReaderConfiguration& readerConfig);
[[nodiscard]] std::list<NotifyArgs> cancelAllDownKeys(nsecs_t when);
};
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index e871288..9c87c62 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -28,8 +28,9 @@
// --- MultiTouchInputMapper ---
-MultiTouchInputMapper::MultiTouchInputMapper(InputDeviceContext& deviceContext)
- : TouchInputMapper(deviceContext) {}
+MultiTouchInputMapper::MultiTouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : TouchInputMapper(deviceContext, readerConfig) {}
MultiTouchInputMapper::~MultiTouchInputMapper() {}
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
index 5f8bccf..a617420 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
@@ -23,7 +23,8 @@
class MultiTouchInputMapper : public TouchInputMapper {
public:
- explicit MultiTouchInputMapper(InputDeviceContext& deviceContext);
+ explicit MultiTouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
~MultiTouchInputMapper() override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index 5b7b295..2ffa5cd 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -26,8 +26,9 @@
namespace android {
-RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDeviceContext& deviceContext)
- : InputMapper(deviceContext), mOrientation(ui::ROTATION_0) {
+RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : InputMapper(deviceContext, readerConfig), mOrientation(ui::ROTATION_0) {
mSource = AINPUT_SOURCE_ROTARY_ENCODER;
}
@@ -64,7 +65,7 @@
}
std::list<NotifyArgs> RotaryEncoderInputMapper::reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) {
std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
if (!changes) {
@@ -72,7 +73,7 @@
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
std::optional<DisplayViewport> internalViewport =
- config->getDisplayViewportByType(ViewportType::INTERNAL);
+ config.getDisplayViewportByType(ViewportType::INTERNAL);
if (internalViewport) {
mOrientation = internalViewport->orientation;
} else {
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
index 639a987..8feaf8e 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
@@ -25,14 +25,15 @@
class RotaryEncoderInputMapper : public InputMapper {
public:
- explicit RotaryEncoderInputMapper(InputDeviceContext& deviceContext);
+ explicit RotaryEncoderInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
virtual ~RotaryEncoderInputMapper();
virtual uint32_t getSources() const override;
virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
virtual void dump(std::string& dump) override;
[[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
index 720fc69..f7f23a4 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
@@ -52,8 +52,9 @@
}
}
-SensorInputMapper::SensorInputMapper(InputDeviceContext& deviceContext)
- : InputMapper(deviceContext) {}
+SensorInputMapper::SensorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : InputMapper(deviceContext, readerConfig) {}
SensorInputMapper::~SensorInputMapper() {}
@@ -117,7 +118,7 @@
}
std::list<NotifyArgs> SensorInputMapper::reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) {
std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.h b/services/inputflinger/reader/mapper/SensorInputMapper.h
index 93cc244..2f3a396 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.h
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.h
@@ -27,14 +27,15 @@
class SensorInputMapper : public InputMapper {
public:
- explicit SensorInputMapper(InputDeviceContext& deviceContext);
+ explicit SensorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
~SensorInputMapper() override;
uint32_t getSources() const override;
void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
void dump(std::string& dump) override;
[[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
index f13417a..ed0e270 100644
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
@@ -18,8 +18,9 @@
namespace android {
-SingleTouchInputMapper::SingleTouchInputMapper(InputDeviceContext& deviceContext)
- : TouchInputMapper(deviceContext) {}
+SingleTouchInputMapper::SingleTouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : TouchInputMapper(deviceContext, readerConfig) {}
SingleTouchInputMapper::~SingleTouchInputMapper() {}
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
index 662e6bc..9341007 100644
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
@@ -23,7 +23,8 @@
class SingleTouchInputMapper : public TouchInputMapper {
public:
- explicit SingleTouchInputMapper(InputDeviceContext& deviceContext);
+ explicit SingleTouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
~SingleTouchInputMapper() override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
index c4564a4..05338da 100644
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
@@ -20,8 +20,9 @@
namespace android {
-SwitchInputMapper::SwitchInputMapper(InputDeviceContext& deviceContext)
- : InputMapper(deviceContext), mSwitchValues(0), mUpdatedSwitchMask(0) {}
+SwitchInputMapper::SwitchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : InputMapper(deviceContext, readerConfig), mSwitchValues(0), mUpdatedSwitchMask(0) {}
SwitchInputMapper::~SwitchInputMapper() {}
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.h b/services/inputflinger/reader/mapper/SwitchInputMapper.h
index 06d6504..7ec282b 100644
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.h
+++ b/services/inputflinger/reader/mapper/SwitchInputMapper.h
@@ -22,7 +22,8 @@
class SwitchInputMapper : public InputMapper {
public:
- explicit SwitchInputMapper(InputDeviceContext& deviceContext);
+ explicit SwitchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
virtual ~SwitchInputMapper();
virtual uint32_t getSources() const override;
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index eb99438..60bf857 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -121,8 +121,9 @@
// --- TouchInputMapper ---
-TouchInputMapper::TouchInputMapper(InputDeviceContext& deviceContext)
- : InputMapper(deviceContext),
+TouchInputMapper::TouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : InputMapper(deviceContext, readerConfig),
mTouchButtonAccumulator(deviceContext),
mSource(0),
mDeviceMode(DeviceMode::DISABLED),
@@ -288,11 +289,11 @@
}
std::list<NotifyArgs> TouchInputMapper::reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) {
std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
- mConfig = *config;
+ mConfig = config;
// Full configuration should happen the first time configure is called and
// when the device type is changed. Changing a device type can affect
@@ -1855,6 +1856,27 @@
}
}
+ if (!mCurrentRawState.rawPointerData.hoveringIdBits.isEmpty() &&
+ mCurrentRawState.rawPointerData.touchingIdBits.isEmpty() &&
+ mDeviceMode != DeviceMode::UNSCALED) {
+ // We have hovering pointers, and there are no touching pointers.
+ bool hoveringPointersInFrame = false;
+ auto hoveringIds = mCurrentRawState.rawPointerData.hoveringIdBits;
+ while (!hoveringIds.isEmpty()) {
+ uint32_t id = hoveringIds.clearFirstMarkedBit();
+ const auto& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
+ if (isPointInsidePhysicalFrame(pointer.x, pointer.y)) {
+ hoveringPointersInFrame = true;
+ break;
+ }
+ }
+ if (!hoveringPointersInFrame) {
+ // All hovering pointers are outside the physical frame.
+ outConsumed = true;
+ return out;
+ }
+ }
+
if (mLastRawState.rawPointerData.touchingIdBits.isEmpty() &&
!mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
// Pointer just went down. Check for virtual key press or off-screen touches.
@@ -1865,7 +1887,7 @@
if (!isPointInsidePhysicalFrame(pointer.x, pointer.y) &&
mDeviceMode != DeviceMode::UNSCALED) {
// If exactly one pointer went down, check for virtual key hit.
- // Otherwise we will drop the entire stroke.
+ // Otherwise, we will drop the entire stroke.
if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
if (virtualKey) {
@@ -3579,17 +3601,19 @@
"%s cannot be used when the device is not in POINTER mode.", __func__);
std::list<NotifyArgs> out;
int32_t metaState = getContext()->getGlobalMetaState();
+ auto cursorPosition = mPointerSimple.currentCoords.getXYValue();
- if (down || hovering) {
- mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
- mPointerController->clearSpots();
- mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
- } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
- mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
+ if (displayId == mPointerController->getDisplayId()) {
+ std::tie(cursorPosition.x, cursorPosition.y) = mPointerController->getPosition();
+ if (down || hovering) {
+ mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
+ mPointerController->clearSpots();
+ mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
+ } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
+ mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
+ }
}
- const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
-
if (mPointerSimple.down && !down) {
mPointerSimple.down = false;
@@ -3599,8 +3623,9 @@
0, metaState, mLastRawState.buttonState,
MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
&mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
- mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
- yCursorPosition, mPointerSimple.downTime,
+ mOrientedXPrecision, mOrientedYPrecision,
+ mPointerSimple.lastCursorX, mPointerSimple.lastCursorY,
+ mPointerSimple.downTime,
/* videoFrames */ {}));
}
@@ -3608,15 +3633,15 @@
mPointerSimple.hovering = false;
// Send hover exit.
- out.push_back(NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
- mSource, displayId, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState,
- mLastRawState.buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, 1,
- &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
- mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
- yCursorPosition, mPointerSimple.downTime,
- /* videoFrames */ {}));
+ out.push_back(
+ NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
+ displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0,
+ metaState, mLastRawState.buttonState, MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
+ &mPointerSimple.lastCoords, mOrientedXPrecision,
+ mOrientedYPrecision, mPointerSimple.lastCursorX,
+ mPointerSimple.lastCursorY, mPointerSimple.downTime,
+ /* videoFrames */ {}));
}
if (down) {
@@ -3632,7 +3657,7 @@
AMOTION_EVENT_EDGE_FLAG_NONE, 1,
&mPointerSimple.currentProperties,
&mPointerSimple.currentCoords, mOrientedXPrecision,
- mOrientedYPrecision, xCursorPosition, yCursorPosition,
+ mOrientedYPrecision, cursorPosition.x, cursorPosition.y,
mPointerSimple.downTime, /* videoFrames */ {}));
}
@@ -3643,7 +3668,7 @@
MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
&mPointerSimple.currentProperties,
&mPointerSimple.currentCoords, mOrientedXPrecision,
- mOrientedYPrecision, xCursorPosition, yCursorPosition,
+ mOrientedYPrecision, cursorPosition.x, cursorPosition.y,
mPointerSimple.downTime, /* videoFrames */ {}));
}
@@ -3659,7 +3684,7 @@
AMOTION_EVENT_EDGE_FLAG_NONE, 1,
&mPointerSimple.currentProperties,
&mPointerSimple.currentCoords, mOrientedXPrecision,
- mOrientedYPrecision, xCursorPosition, yCursorPosition,
+ mOrientedYPrecision, cursorPosition.x, cursorPosition.y,
mPointerSimple.downTime, /* videoFrames */ {}));
}
@@ -3670,8 +3695,8 @@
metaState, mCurrentRawState.buttonState,
MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
&mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
- yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {}));
+ mOrientedXPrecision, mOrientedYPrecision, cursorPosition.x,
+ cursorPosition.y, mPointerSimple.downTime, /* videoFrames */ {}));
}
if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
@@ -3691,8 +3716,8 @@
0, 0, metaState, mCurrentRawState.buttonState,
MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
&mPointerSimple.currentProperties, &pointerCoords,
- mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
- yCursorPosition, mPointerSimple.downTime,
+ mOrientedXPrecision, mOrientedYPrecision, cursorPosition.x,
+ cursorPosition.y, mPointerSimple.downTime,
/* videoFrames */ {}));
}
@@ -3702,8 +3727,8 @@
mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
mPointerSimple.displayId = displayId;
mPointerSimple.source = mSource;
- mPointerSimple.lastCursorX = xCursorPosition;
- mPointerSimple.lastCursorY = yCursorPosition;
+ mPointerSimple.lastCursorX = cursorPosition.x;
+ mPointerSimple.lastCursorY = cursorPosition.y;
} else {
mPointerSimple.reset();
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index d98ae60..e7d66a1 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -146,14 +146,15 @@
class TouchInputMapper : public InputMapper {
public:
- explicit TouchInputMapper(InputDeviceContext& deviceContext);
+ explicit TouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
~TouchInputMapper() override;
uint32_t getSources() const override;
void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
void dump(std::string& dump) override;
[[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index 33f368e..5a1ced4 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -57,7 +57,7 @@
{std::numeric_limits<double>::infinity(), 15.04, -857.758},
};
-const std::vector<double> sensitivityFactors = {1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20};
+const std::vector<double> sensitivityFactors = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18};
std::vector<double> createAccelerationCurveForSensitivity(int32_t sensitivity,
size_t propertySize) {
@@ -169,8 +169,9 @@
} // namespace
-TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext)
- : InputMapper(deviceContext),
+TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : InputMapper(deviceContext, readerConfig),
mGestureInterpreter(NewGestureInterpreter(), DeleteGestureInterpreter),
mPointerController(getContext()->getPointerController(getDeviceId())),
mStateConverter(deviceContext),
@@ -220,7 +221,7 @@
}
std::list<NotifyArgs> TouchpadInputMapper::reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) {
if (!changes) {
// First time configuration
@@ -231,7 +232,7 @@
std::optional<int32_t> displayId = mPointerController->getDisplayId();
ui::Rotation orientation = ui::ROTATION_0;
if (displayId.has_value()) {
- if (auto viewport = config->getDisplayViewportById(*displayId); viewport) {
+ if (auto viewport = config.getDisplayViewportById(*displayId); viewport) {
orientation = getInverseRotation(viewport->orientation);
}
}
@@ -242,14 +243,14 @@
.setBoolValues({true});
GesturesProp accelCurveProp = mPropertyProvider.getProperty("Pointer Accel Curve");
accelCurveProp.setRealValues(
- createAccelerationCurveForSensitivity(config->touchpadPointerSpeed,
+ createAccelerationCurveForSensitivity(config.touchpadPointerSpeed,
accelCurveProp.getCount()));
mPropertyProvider.getProperty("Invert Scrolling")
- .setBoolValues({config->touchpadNaturalScrollingEnabled});
+ .setBoolValues({config.touchpadNaturalScrollingEnabled});
mPropertyProvider.getProperty("Tap Enable")
- .setBoolValues({config->touchpadTapToClickEnabled});
+ .setBoolValues({config.touchpadTapToClickEnabled});
mPropertyProvider.getProperty("Button Right Click Zone Enable")
- .setBoolValues({config->touchpadRightClickZoneEnabled});
+ .setBoolValues({config.touchpadRightClickZoneEnabled});
}
return {};
}
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
index 6f152fa..e051097 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -37,7 +37,8 @@
class TouchpadInputMapper : public InputMapper {
public:
- explicit TouchpadInputMapper(InputDeviceContext& deviceContext);
+ explicit TouchpadInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
~TouchpadInputMapper();
uint32_t getSources() const override;
@@ -45,7 +46,7 @@
void dump(std::string& dump) override;
[[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
- const InputReaderConfiguration* config,
+ const InputReaderConfiguration& config,
uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
index 2c77fc4..8d78d0f 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
@@ -20,8 +20,9 @@
namespace android {
-VibratorInputMapper::VibratorInputMapper(InputDeviceContext& deviceContext)
- : InputMapper(deviceContext), mVibrating(false), mSequence(0) {}
+VibratorInputMapper::VibratorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig)
+ : InputMapper(deviceContext, readerConfig), mVibrating(false), mSequence(0) {}
VibratorInputMapper::~VibratorInputMapper() {}
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.h b/services/inputflinger/reader/mapper/VibratorInputMapper.h
index e665973..384c075 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.h
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.h
@@ -22,7 +22,8 @@
class VibratorInputMapper : public InputMapper {
public:
- explicit VibratorInputMapper(InputDeviceContext& deviceContext);
+ explicit VibratorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
virtual ~VibratorInputMapper();
virtual uint32_t getSources() const override;
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
index c5fd5f5..e829692 100644
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
@@ -41,6 +41,12 @@
bool isHovering() const;
bool hasStylus() const;
bool hasButtonTouch() const;
+
+ /*
+ * Returns the number of touches reported by the device through its BTN_TOOL_FINGER and
+ * BTN_TOOL_*TAP "buttons". Note that this count includes touches reported with their
+ * ABS_MT_TOOL_TYPE set to MT_TOOL_PALM.
+ */
int getTouchCount() const;
private:
diff --git a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
index e89262a..8841b6e 100644
--- a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
@@ -81,11 +81,16 @@
}
schs.fingers.clear();
+ size_t numPalms = 0;
for (size_t i = 0; i < mMotionAccumulator.getSlotCount(); i++) {
MultiTouchMotionAccumulator::Slot slot = mMotionAccumulator.getSlot(i);
+ if (!slot.isInUse()) {
+ continue;
+ }
// Some touchpads continue to report contacts even after they've identified them as palms.
// We want to exclude these contacts from the HardwareStates.
- if (!slot.isInUse() || slot.getToolType() == ToolType::PALM) {
+ if (slot.getToolType() == ToolType::PALM) {
+ numPalms++;
continue;
}
@@ -103,7 +108,7 @@
}
schs.state.fingers = schs.fingers.data();
schs.state.finger_cnt = schs.fingers.size();
- schs.state.touch_cnt = mTouchButtonAccumulator.getTouchCount();
+ schs.state.touch_cnt = mTouchButtonAccumulator.getTouchCount() - numPalms;
return schs;
}
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
index 30c1719..3486d0f 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
@@ -154,8 +154,8 @@
mPointerController = std::move(controller);
}
-const InputReaderConfiguration* FakeInputReaderPolicy::getReaderConfiguration() const {
- return &mConfig;
+const InputReaderConfiguration& FakeInputReaderPolicy::getReaderConfiguration() const {
+ return mConfig;
}
const std::vector<InputDeviceInfo>& FakeInputReaderPolicy::getInputDevices() const {
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.h b/services/inputflinger/tests/FakeInputReaderPolicy.h
index 28ac505..85ff01a 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.h
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.h
@@ -63,7 +63,7 @@
void addDisabledDevice(int32_t deviceId);
void removeDisabledDevice(int32_t deviceId);
void setPointerController(std::shared_ptr<FakePointerController> controller);
- const InputReaderConfiguration* getReaderConfiguration() const;
+ const InputReaderConfiguration& getReaderConfiguration() const;
const std::vector<InputDeviceInfo>& getInputDevices() const;
TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
ui::Rotation surfaceRotation);
diff --git a/services/inputflinger/tests/HardwareStateConverter_test.cpp b/services/inputflinger/tests/HardwareStateConverter_test.cpp
index 3e97241..19d46c8 100644
--- a/services/inputflinger/tests/HardwareStateConverter_test.cpp
+++ b/services/inputflinger/tests/HardwareStateConverter_test.cpp
@@ -13,11 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <gestures/HardwareStateConverter.h>
+
+#include <memory>
#include <EventHub.h>
-#include <gestures/HardwareStateConverter.h>
#include <gtest/gtest.h>
#include <linux/input-event-codes.h>
+#include <utils/StrongPointer.h>
#include "FakeEventHub.h"
#include "FakeInputReaderPolicy.h"
@@ -28,38 +31,37 @@
namespace android {
class HardwareStateConverterTest : public testing::Test {
+public:
+ HardwareStateConverterTest()
+ : mFakeEventHub(std::make_shared<FakeEventHub>()),
+ mFakePolicy(sp<FakeInputReaderPolicy>::make()),
+ mReader(mFakeEventHub, mFakePolicy, mFakeListener),
+ mDevice(newDevice()),
+ mDeviceContext(*mDevice, EVENTHUB_ID) {
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, 0, 7, 0, 0, 0);
+ mConverter = std::make_unique<HardwareStateConverter>(mDeviceContext);
+ }
+
protected:
static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
static constexpr int32_t EVENTHUB_ID = 1;
- void SetUp() {
- mFakeEventHub = std::make_unique<FakeEventHub>();
- mFakePolicy = sp<FakeInputReaderPolicy>::make();
- mFakeListener = std::make_unique<TestInputListener>();
- mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
- *mFakeListener);
- mDevice = newDevice();
-
- mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, 0, 7, 0, 0, 0);
- }
-
std::shared_ptr<InputDevice> newDevice() {
InputDeviceIdentifier identifier;
identifier.name = "device";
identifier.location = "USB1";
identifier.bus = 0;
std::shared_ptr<InputDevice> device =
- std::make_shared<InputDevice>(mReader->getContext(), DEVICE_ID, /* generation= */ 2,
+ std::make_shared<InputDevice>(mReader.getContext(), DEVICE_ID, /*generation=*/2,
identifier);
- mReader->pushNextDevice(device);
+ mReader.pushNextDevice(device);
mFakeEventHub->addDevice(EVENTHUB_ID, identifier.name, InputDeviceClass::TOUCHPAD,
identifier.bus);
- mReader->loopOnce();
+ mReader.loopOnce();
return device;
}
- void processAxis(HardwareStateConverter& conv, nsecs_t when, int32_t type, int32_t code,
- int32_t value) {
+ void processAxis(nsecs_t when, int32_t type, int32_t code, int32_t value) {
RawEvent event;
event.when = when;
event.readTime = READ_TIME;
@@ -67,12 +69,11 @@
event.type = type;
event.code = code;
event.value = value;
- std::optional<SelfContainedHardwareState> schs = conv.processRawEvent(&event);
+ std::optional<SelfContainedHardwareState> schs = mConverter->processRawEvent(&event);
EXPECT_FALSE(schs.has_value());
}
- std::optional<SelfContainedHardwareState> processSync(HardwareStateConverter& conv,
- nsecs_t when) {
+ std::optional<SelfContainedHardwareState> processSync(nsecs_t when) {
RawEvent event;
event.when = when;
event.readTime = READ_TIME;
@@ -80,37 +81,37 @@
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
- return conv.processRawEvent(&event);
+ return mConverter->processRawEvent(&event);
}
std::shared_ptr<FakeEventHub> mFakeEventHub;
sp<FakeInputReaderPolicy> mFakePolicy;
- std::unique_ptr<TestInputListener> mFakeListener;
- std::unique_ptr<InstrumentedInputReader> mReader;
+ TestInputListener mFakeListener;
+ InstrumentedInputReader mReader;
std::shared_ptr<InputDevice> mDevice;
+ InputDeviceContext mDeviceContext;
+ std::unique_ptr<HardwareStateConverter> mConverter;
};
TEST_F(HardwareStateConverterTest, OneFinger) {
const nsecs_t time = 1500000000;
- InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
- HardwareStateConverter conv(deviceContext);
- processAxis(conv, time, EV_ABS, ABS_MT_SLOT, 0);
- processAxis(conv, time, EV_ABS, ABS_MT_TRACKING_ID, 123);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 50);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 100);
- processAxis(conv, time, EV_ABS, ABS_MT_TOUCH_MAJOR, 5);
- processAxis(conv, time, EV_ABS, ABS_MT_TOUCH_MINOR, 4);
- processAxis(conv, time, EV_ABS, ABS_MT_PRESSURE, 42);
- processAxis(conv, time, EV_ABS, ABS_MT_ORIENTATION, 2);
+ processAxis(time, EV_ABS, ABS_MT_SLOT, 0);
+ processAxis(time, EV_ABS, ABS_MT_TRACKING_ID, 123);
+ processAxis(time, EV_ABS, ABS_MT_POSITION_X, 50);
+ processAxis(time, EV_ABS, ABS_MT_POSITION_Y, 100);
+ processAxis(time, EV_ABS, ABS_MT_TOUCH_MAJOR, 5);
+ processAxis(time, EV_ABS, ABS_MT_TOUCH_MINOR, 4);
+ processAxis(time, EV_ABS, ABS_MT_PRESSURE, 42);
+ processAxis(time, EV_ABS, ABS_MT_ORIENTATION, 2);
- processAxis(conv, time, EV_ABS, ABS_X, 50);
- processAxis(conv, time, EV_ABS, ABS_Y, 100);
- processAxis(conv, time, EV_ABS, ABS_PRESSURE, 42);
+ processAxis(time, EV_ABS, ABS_X, 50);
+ processAxis(time, EV_ABS, ABS_Y, 100);
+ processAxis(time, EV_ABS, ABS_PRESSURE, 42);
- processAxis(conv, time, EV_KEY, BTN_TOUCH, 1);
- processAxis(conv, time, EV_KEY, BTN_TOOL_FINGER, 1);
- std::optional<SelfContainedHardwareState> schs = processSync(conv, time);
+ processAxis(time, EV_KEY, BTN_TOUCH, 1);
+ processAxis(time, EV_KEY, BTN_TOOL_FINGER, 1);
+ std::optional<SelfContainedHardwareState> schs = processSync(time);
ASSERT_TRUE(schs.has_value());
const HardwareState& state = schs->state;
@@ -138,35 +139,31 @@
}
TEST_F(HardwareStateConverterTest, TwoFingers) {
- const nsecs_t time = ARBITRARY_TIME;
- InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
- HardwareStateConverter conv(deviceContext);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_SLOT, 0);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TRACKING_ID, 123);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, 50);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 100);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, 5);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, 4);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_PRESSURE, 42);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_ORIENTATION, 2);
- processAxis(conv, time, EV_ABS, ABS_MT_SLOT, 0);
- processAxis(conv, time, EV_ABS, ABS_MT_TRACKING_ID, 123);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 50);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 100);
- processAxis(conv, time, EV_ABS, ABS_MT_TOUCH_MAJOR, 5);
- processAxis(conv, time, EV_ABS, ABS_MT_TOUCH_MINOR, 4);
- processAxis(conv, time, EV_ABS, ABS_MT_PRESSURE, 42);
- processAxis(conv, time, EV_ABS, ABS_MT_ORIENTATION, 2);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_SLOT, 1);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TRACKING_ID, 456);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, -20);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 40);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, 8);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, 7);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_PRESSURE, 21);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_ORIENTATION, 1);
- processAxis(conv, time, EV_ABS, ABS_MT_SLOT, 1);
- processAxis(conv, time, EV_ABS, ABS_MT_TRACKING_ID, 456);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, -20);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 40);
- processAxis(conv, time, EV_ABS, ABS_MT_TOUCH_MAJOR, 8);
- processAxis(conv, time, EV_ABS, ABS_MT_TOUCH_MINOR, 7);
- processAxis(conv, time, EV_ABS, ABS_MT_PRESSURE, 21);
- processAxis(conv, time, EV_ABS, ABS_MT_ORIENTATION, 1);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_X, 50);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_Y, 100);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_PRESSURE, 42);
- processAxis(conv, time, EV_ABS, ABS_X, 50);
- processAxis(conv, time, EV_ABS, ABS_Y, 100);
- processAxis(conv, time, EV_ABS, ABS_PRESSURE, 42);
-
- processAxis(conv, time, EV_KEY, BTN_TOUCH, 1);
- processAxis(conv, time, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
- std::optional<SelfContainedHardwareState> schs = processSync(conv, time);
+ processAxis(ARBITRARY_TIME, EV_KEY, BTN_TOUCH, 1);
+ processAxis(ARBITRARY_TIME, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
+ std::optional<SelfContainedHardwareState> schs = processSync(ARBITRARY_TIME);
ASSERT_TRUE(schs.has_value());
ASSERT_EQ(2, schs->state.finger_cnt);
@@ -192,59 +189,58 @@
}
TEST_F(HardwareStateConverterTest, OnePalm) {
- const nsecs_t time = ARBITRARY_TIME;
- InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
- HardwareStateConverter conv(deviceContext);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_SLOT, 0);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TRACKING_ID, 123);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, 50);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 100);
- processAxis(conv, time, EV_ABS, ABS_MT_SLOT, 0);
- processAxis(conv, time, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
- processAxis(conv, time, EV_ABS, ABS_MT_TRACKING_ID, 123);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 50);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 100);
-
- processAxis(conv, time, EV_KEY, BTN_TOUCH, 1);
- std::optional<SelfContainedHardwareState> schs = processSync(conv, time);
+ processAxis(ARBITRARY_TIME, EV_KEY, BTN_TOUCH, 1);
+ processAxis(ARBITRARY_TIME, EV_KEY, BTN_TOOL_FINGER, 1);
+ std::optional<SelfContainedHardwareState> schs = processSync(ARBITRARY_TIME);
ASSERT_TRUE(schs.has_value());
+ EXPECT_EQ(0, schs->state.touch_cnt);
EXPECT_EQ(0, schs->state.finger_cnt);
}
TEST_F(HardwareStateConverterTest, OneFingerTurningIntoAPalm) {
- const nsecs_t time = ARBITRARY_TIME;
- InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
- HardwareStateConverter conv(deviceContext);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_SLOT, 0);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TRACKING_ID, 123);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, 50);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 100);
- processAxis(conv, time, EV_ABS, ABS_MT_SLOT, 0);
- processAxis(conv, time, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
- processAxis(conv, time, EV_ABS, ABS_MT_TRACKING_ID, 123);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 50);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 100);
+ processAxis(ARBITRARY_TIME, EV_KEY, BTN_TOUCH, 1);
+ processAxis(ARBITRARY_TIME, EV_KEY, BTN_TOOL_FINGER, 1);
- processAxis(conv, time, EV_KEY, BTN_TOUCH, 1);
-
- std::optional<SelfContainedHardwareState> schs = processSync(conv, time);
+ std::optional<SelfContainedHardwareState> schs = processSync(ARBITRARY_TIME);
ASSERT_TRUE(schs.has_value());
+ EXPECT_EQ(1, schs->state.touch_cnt);
EXPECT_EQ(1, schs->state.finger_cnt);
- processAxis(conv, time, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 51);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 99);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, 51);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 99);
- schs = processSync(conv, time);
+ schs = processSync(ARBITRARY_TIME);
ASSERT_TRUE(schs.has_value());
+ EXPECT_EQ(0, schs->state.touch_cnt);
ASSERT_EQ(0, schs->state.finger_cnt);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 53);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 97);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, 53);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 97);
- schs = processSync(conv, time);
+ schs = processSync(ARBITRARY_TIME);
ASSERT_TRUE(schs.has_value());
+ EXPECT_EQ(0, schs->state.touch_cnt);
EXPECT_EQ(0, schs->state.finger_cnt);
- processAxis(conv, time, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 55);
- processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 95);
- schs = processSync(conv, time);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, 55);
+ processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 95);
+ schs = processSync(ARBITRARY_TIME);
ASSERT_TRUE(schs.has_value());
+ EXPECT_EQ(1, schs->state.touch_cnt);
ASSERT_EQ(1, schs->state.finger_cnt);
const FingerState& newFinger = schs->state.fingers[0];
EXPECT_EQ(123, newFinger.tracking_id);
@@ -253,25 +249,16 @@
}
TEST_F(HardwareStateConverterTest, ButtonPressed) {
- const nsecs_t time = ARBITRARY_TIME;
- InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
- HardwareStateConverter conv(deviceContext);
-
- processAxis(conv, time, EV_KEY, BTN_LEFT, 1);
- std::optional<SelfContainedHardwareState> schs = processSync(conv, time);
+ processAxis(ARBITRARY_TIME, EV_KEY, BTN_LEFT, 1);
+ std::optional<SelfContainedHardwareState> schs = processSync(ARBITRARY_TIME);
ASSERT_TRUE(schs.has_value());
EXPECT_EQ(GESTURES_BUTTON_LEFT, schs->state.buttons_down);
}
TEST_F(HardwareStateConverterTest, MscTimestamp) {
- const nsecs_t time = ARBITRARY_TIME;
- mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
- InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
- HardwareStateConverter conv(deviceContext);
-
- processAxis(conv, time, EV_MSC, MSC_TIMESTAMP, 1200000);
- std::optional<SelfContainedHardwareState> schs = processSync(conv, time);
+ processAxis(ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, 1200000);
+ std::optional<SelfContainedHardwareState> schs = processSync(ARBITRARY_TIME);
ASSERT_TRUE(schs.has_value());
EXPECT_NEAR(1.2, schs->state.msc_timestamp, EPSILON);
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index fb808eb..27d7b9c 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -213,7 +213,7 @@
void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
- ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_KEY);
+ ASSERT_EQ(event.getType(), InputEventType::KEY);
EXPECT_EQ(event.getDisplayId(), args.displayId);
const auto& keyEvent = static_cast<const KeyEvent&>(event);
@@ -224,7 +224,7 @@
void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
- ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_MOTION);
+ ASSERT_EQ(event.getType(), InputEventType::MOTION);
EXPECT_EQ(event.getDisplayId(), args.displayId);
const auto& motionEvent = static_cast<const MotionEvent&>(event);
@@ -530,17 +530,21 @@
bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
std::scoped_lock lock(mLock);
switch (inputEvent->getType()) {
- case AINPUT_EVENT_TYPE_KEY: {
+ case InputEventType::KEY: {
const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
break;
}
- case AINPUT_EVENT_TYPE_MOTION: {
+ case InputEventType::MOTION: {
const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
break;
}
+ default: {
+ ADD_FAILURE() << "Should only filter keys or motions";
+ break;
+ }
}
return true;
}
@@ -814,8 +818,7 @@
TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
constexpr nsecs_t eventTime = 20;
- NotifyConfigurationChangedArgs args(/*id=*/10, eventTime);
- mDispatcher->notifyConfigurationChanged(&args);
+ mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
ASSERT_TRUE(mDispatcher->waitForIdle());
mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
@@ -824,7 +827,7 @@
TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
/*switchMask=*/2);
- mDispatcher->notifySwitch(&args);
+ mDispatcher->notifySwitch(args);
// InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
args.policyFlags |= POLICY_FLAG_TRUSTED;
@@ -924,7 +927,7 @@
ASSERT_EQ(OK, status);
}
- void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
+ void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
std::optional<int32_t> expectedDisplayId,
std::optional<int32_t> expectedFlags) {
InputEvent* event = consume();
@@ -932,15 +935,15 @@
ASSERT_NE(nullptr, event) << mName.c_str()
<< ": consumer should have returned non-NULL event.";
ASSERT_EQ(expectedEventType, event->getType())
- << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
- << " event, got " << inputEventTypeToString(event->getType()) << " event";
+ << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
+ << " event, got " << *event;
if (expectedDisplayId.has_value()) {
EXPECT_EQ(expectedDisplayId, event->getDisplayId());
}
switch (expectedEventType) {
- case AINPUT_EVENT_TYPE_KEY: {
+ case InputEventType::KEY: {
const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
EXPECT_EQ(expectedAction, keyEvent.getAction());
if (expectedFlags.has_value()) {
@@ -948,7 +951,7 @@
}
break;
}
- case AINPUT_EVENT_TYPE_MOTION: {
+ case InputEventType::MOTION: {
const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
assertMotionAction(expectedAction, motionEvent.getAction());
@@ -957,21 +960,18 @@
}
break;
}
- case AINPUT_EVENT_TYPE_FOCUS: {
+ case InputEventType::FOCUS: {
FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
}
- case AINPUT_EVENT_TYPE_CAPTURE: {
+ case InputEventType::CAPTURE: {
FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
}
- case AINPUT_EVENT_TYPE_TOUCH_MODE: {
+ case InputEventType::TOUCH_MODE: {
FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
}
- case AINPUT_EVENT_TYPE_DRAG: {
+ case InputEventType::DRAG: {
FAIL() << "Use 'consumeDragEvent' for DRAG events";
}
- default: {
- FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
- }
}
}
@@ -983,9 +983,8 @@
return nullptr;
}
- if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
- ADD_FAILURE() << mName << " expected a MotionEvent, got "
- << inputEventTypeToString(event->getType()) << " event";
+ if (event->getType() != InputEventType::MOTION) {
+ ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
return nullptr;
}
return static_cast<MotionEvent*>(event);
@@ -1001,9 +1000,8 @@
InputEvent* event = consume();
ASSERT_NE(nullptr, event) << mName.c_str()
<< ": consumer should have returned non-NULL event.";
- ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
- << "Got " << inputEventTypeToString(event->getType())
- << " event instead of FOCUS event";
+ ASSERT_EQ(InputEventType::FOCUS, event->getType())
+ << "Instead of FocusEvent, got " << *event;
ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
<< mName.c_str() << ": event displayId should always be NONE.";
@@ -1016,9 +1014,8 @@
const InputEvent* event = consume();
ASSERT_NE(nullptr, event) << mName.c_str()
<< ": consumer should have returned non-NULL event.";
- ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
- << "Got " << inputEventTypeToString(event->getType())
- << " event instead of CAPTURE event";
+ ASSERT_EQ(InputEventType::CAPTURE, event->getType())
+ << "Instead of CaptureEvent, got " << *event;
ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
<< mName.c_str() << ": event displayId should always be NONE.";
@@ -1031,9 +1028,7 @@
const InputEvent* event = consume();
ASSERT_NE(nullptr, event) << mName.c_str()
<< ": consumer should have returned non-NULL event.";
- ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
- << "Got " << inputEventTypeToString(event->getType())
- << " event instead of DRAG event";
+ ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
<< mName.c_str() << ": event displayId should always be NONE.";
@@ -1048,9 +1043,8 @@
const InputEvent* event = consume();
ASSERT_NE(nullptr, event) << mName.c_str()
<< ": consumer should have returned non-NULL event.";
- ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType())
- << "Got " << inputEventTypeToString(event->getType())
- << " event instead of TOUCH_MODE event";
+ ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
+ << "Instead of TouchModeEvent, got " << *event;
ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
<< mName.c_str() << ": event displayId should always be NONE.";
@@ -1063,23 +1057,23 @@
if (event == nullptr) {
return;
}
- if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
+ if (event->getType() == InputEventType::KEY) {
KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
ADD_FAILURE() << "Received key event "
<< KeyEvent::actionToString(keyEvent.getAction());
- } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
+ } else if (event->getType() == InputEventType::MOTION) {
MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
ADD_FAILURE() << "Received motion event "
<< MotionEvent::actionToString(motionEvent.getAction());
- } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
+ } else if (event->getType() == InputEventType::FOCUS) {
FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
ADD_FAILURE() << "Received focus event, hasFocus = "
<< (focusEvent.getHasFocus() ? "true" : "false");
- } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
+ } else if (event->getType() == InputEventType::CAPTURE) {
const auto& captureEvent = static_cast<CaptureEvent&>(*event);
ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
<< (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
- } else if (event->getType() == AINPUT_EVENT_TYPE_TOUCH_MODE) {
+ } else if (event->getType() == InputEventType::TOUCH_MODE) {
const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
ADD_FAILURE() << "Received touch mode event, inTouchMode = "
<< (touchModeEvent.isInTouchMode() ? "true" : "false");
@@ -1239,12 +1233,11 @@
void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
- consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
- expectedFlags);
+ consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
}
void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
- consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
+ consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
}
void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
@@ -1266,7 +1259,7 @@
void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
std::optional<int32_t> expectedFlags = std::nullopt) {
- consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
+ consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
expectedFlags);
}
@@ -1275,25 +1268,25 @@
int32_t expectedFlags = 0) {
int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
(pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
+ consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
}
void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
int32_t expectedFlags = 0) {
int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
(pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
+ consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
}
void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
int32_t expectedFlags = 0) {
- consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
+ consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
expectedFlags);
}
void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
int32_t expectedFlags = 0) {
- consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
+ consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
expectedFlags);
}
@@ -1301,7 +1294,7 @@
int32_t expectedFlags = 0) {
InputEvent* event = consume();
ASSERT_NE(nullptr, event);
- ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
+ ASSERT_EQ(InputEventType::MOTION, event->getType());
const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
@@ -1326,7 +1319,7 @@
ASSERT_THAT(*motionEvent, matcher);
}
- void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
+ void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
std::optional<int32_t> expectedDisplayId,
std::optional<int32_t> expectedFlags) {
ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
@@ -1375,9 +1368,8 @@
ADD_FAILURE() << "Consume failed : no event";
return nullptr;
}
- if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
- ADD_FAILURE() << "Instead of motion event, got "
- << inputEventTypeToString(event->getType());
+ if (event->getType() != InputEventType::MOTION) {
+ ADD_FAILURE() << "Instead of motion event, got " << *event;
return nullptr;
}
return static_cast<MotionEvent*>(event);
@@ -1750,8 +1742,9 @@
return args;
}
-static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
- const std::vector<PointF>& points) {
+[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
+ int32_t displayId,
+ const std::vector<PointF>& points) {
size_t pointerCount = points.size();
if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
@@ -1953,26 +1946,20 @@
sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
- NotifyMotionArgs args;
// First touch pointer down on right window
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
+ .build());
// Second touch pointer down
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
-
- .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
- .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
+ .build());
// First touch pointer lifts. The second one remains down
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
-
- .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
- .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
+ .build());
window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
@@ -2263,54 +2250,48 @@
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
const int32_t touchDeviceId = 4;
- NotifyMotionArgs args;
// Two pointers down
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .policyFlags(DEFAULT_POLICY_FLAGS)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
- .build()));
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .policyFlags(DEFAULT_POLICY_FLAGS)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
+ .build());
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .policyFlags(DEFAULT_POLICY_FLAGS)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
- .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .policyFlags(DEFAULT_POLICY_FLAGS)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
// Cancel the current gesture. Send the cancel without the default policy flags.
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .policyFlags(0)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
- .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
- .build()));
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .policyFlags(0)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
// We don't need to reset the device to reproduce the issue, but the reset event typically
// follows, so we keep it here to model the actual listener behaviour more closely.
- NotifyDeviceResetArgs resetArgs;
- resetArgs.id = 1; // arbitrary id
- resetArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
- resetArgs.deviceId = touchDeviceId;
- mDispatcher->notifyDeviceReset(&resetArgs);
+ mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
// Start new gesture
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .policyFlags(DEFAULT_POLICY_FLAGS)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
- .build()));
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .policyFlags(DEFAULT_POLICY_FLAGS)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
@@ -2460,53 +2441,49 @@
NotifyMotionArgs args;
// Start hovering over the left window
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
+ .build());
leftWindow->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
// Mouse down on left window
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
+ .build());
leftWindow->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
leftWindow->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
- .build()));
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
+ .build());
leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
// First touch pointer down on right window
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
+ .build());
leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
// Second touch pointer down on left window
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
- .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
+ .build());
leftWindow->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
// This MOVE event is not necessary (doesn't carry any new information), but it's there in the
@@ -2540,57 +2517,52 @@
NotifyMotionArgs args;
// First touch pointer down
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
+ .build());
// Second touch pointer down
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
- .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
+ .build());
// First touch pointer lifts. The second one remains down
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
- .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
+ .build());
window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
// Mouse down. The touch should be canceled
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
+ .build());
window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
WithPointerCount(1u)));
window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
- .build()));
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
+ .build());
window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
// Second touch pointer down.
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
- .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
+ .build());
// The pointer_down event should be ignored
window->assertNoEvents();
}
@@ -2624,11 +2596,10 @@
// Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
// should be canceled and the new gesture should take over.
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
+ .build());
window->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
@@ -2830,46 +2801,38 @@
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
- NotifyMotionArgs args;
-
// Start hovering with stylus
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
- .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
// Stop hovering
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
- .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
// Stylus touches down
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
- .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
// Stylus goes up
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
- .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
// Again hover
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
- .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
// Stop hovering
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
- .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
// No more events
@@ -2898,35 +2861,31 @@
const int32_t mouseDeviceId = 7;
const int32_t touchDeviceId = 4;
- NotifyMotionArgs args;
// Hover a bit with mouse first
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
+ .build());
spyWindow->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
window->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
// Start touching
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
@@ -2934,20 +2893,18 @@
EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
// Mouse down
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
+ .build());
spyWindow->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
@@ -2955,32 +2912,30 @@
AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
- .build()));
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
// Mouse move!
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
+ .build());
spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
// Touch move!
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
+ .build());
// No more events
spyWindow->assertNoEvents();
@@ -2998,16 +2953,15 @@
sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
- NotifyMotionArgs args;
// Touch down on the empty space
- mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}})));
+ mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
mDispatcher->waitForIdle();
window->assertNoEvents();
// Now touch down on the window with another pointer
- mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}})));
+ mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
mDispatcher->waitForIdle();
window->consumeMotionDown();
}
@@ -3028,16 +2982,15 @@
mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
- NotifyMotionArgs args;
// Touch down on the non-touchable window
- mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
+ mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
mDispatcher->waitForIdle();
window1->assertNoEvents();
window2->assertNoEvents();
// Now touch down on the window with another pointer
- mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
+ mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
mDispatcher->waitForIdle();
window2->consumeMotionDown();
}
@@ -3057,9 +3010,8 @@
mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
- NotifyMotionArgs args;
// Touch down on the first window
- mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
+ mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
mDispatcher->waitForIdle();
InputEvent* inputEvent1 = window1->consume();
@@ -3070,7 +3022,7 @@
ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
// Now touch down on the window with another pointer
- mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
+ mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
mDispatcher->waitForIdle();
InputEvent* inputEvent2 = window2->consume();
ASSERT_NE(inputEvent2, nullptr);
@@ -3080,14 +3032,12 @@
ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
// Now move the pointer on the second window
- mDispatcher->notifyMotion(
- &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})));
+ mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
mDispatcher->waitForIdle();
window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
// Now add new touch down on the second window
- mDispatcher->notifyMotion(
- &(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})));
+ mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
mDispatcher->waitForIdle();
window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
@@ -3096,13 +3046,13 @@
window1->assertNoEvents();
// Now move the pointer on the first window
- mDispatcher->notifyMotion(&(
- args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}})));
+ mDispatcher->notifyMotion(
+ generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
mDispatcher->waitForIdle();
window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
- mDispatcher->notifyMotion(&(
- args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})));
+ mDispatcher->notifyMotion(
+ generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
mDispatcher->waitForIdle();
window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
}
@@ -3206,52 +3156,47 @@
const int32_t touchDeviceId = 4;
const int32_t mouseDeviceId = 6;
- NotifyMotionArgs args;
// Two pointers down
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
+ .build());
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
- .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
+ .build());
window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
// Inject a series of mouse events for a mouse click
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
+ .build());
window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
WithPointerCount(2u)));
window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
- .build()));
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
+ .build());
window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
// Try to send more touch events while the mouse is down. Since it's a continuation of an
// already canceled gesture, it should be ignored.
- mDispatcher->notifyMotion(&(
- args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
- .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
+ .build());
window->assertNoEvents();
}
@@ -3515,23 +3460,20 @@
const int32_t mouseDeviceId = 7;
const int32_t touchDeviceId = 4;
- NotifyMotionArgs args;
// Start hovering with the mouse
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
- .deviceId(mouseDeviceId)
- .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
+ .build());
window->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
// Touch goes down
- mDispatcher->notifyMotion(
- &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .deviceId(touchDeviceId)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
- .build()));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .build());
window->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
@@ -3557,15 +3499,15 @@
ADISPLAY_ID_DEFAULT, {{50, 50}});
motionArgs.xCursorPosition = 50;
motionArgs.yCursorPosition = 50;
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(motionArgs);
ASSERT_NO_FATAL_FAILURE(
window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
WithSource(AINPUT_SOURCE_MOUSE))));
// Tap on the window
- motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {{10, 10}});
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {{10, 10}}));
ASSERT_NO_FATAL_FAILURE(
window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
WithSource(AINPUT_SOURCE_MOUSE))));
@@ -3574,9 +3516,8 @@
window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
- motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {{10, 10}});
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {{10, 10}}));
ASSERT_NO_FATAL_FAILURE(
window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
@@ -3668,17 +3609,15 @@
window->consumeFocusEvent(true);
- NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
// Window should receive key down event.
window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
// When device reset happens, that key stream should be terminated with FLAG_CANCELED
// on the app side.
- NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
- mDispatcher->notifyDeviceReset(&args);
- window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
+ mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
+ window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
AKEY_EVENT_FLAG_CANCELED);
}
@@ -3689,18 +3628,15 @@
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
// Window should receive motion down event.
window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
// When device reset happens, that motion stream should be terminated with ACTION_CANCEL
// on the app side.
- NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
- mDispatcher->notifyDeviceReset(&args);
+ mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
window->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
}
@@ -3716,11 +3652,11 @@
window->consumeFocusEvent(true);
- NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
+ const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
const std::chrono::milliseconds interceptKeyTimeout = 50ms;
const nsecs_t injectTime = keyArgs.eventTime;
mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(keyArgs);
// The dispatching time should be always greater than or equal to intercept key timeout.
window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
@@ -3738,11 +3674,9 @@
window->consumeFocusEvent(true);
- NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
- NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
mFakePolicy->setInterceptKeyTimeout(150ms);
- mDispatcher->notifyKey(&keyDown);
- mDispatcher->notifyKey(&keyUp);
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
// Window should receive key event immediately when same key up.
window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
@@ -3771,10 +3705,9 @@
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
// Tap on first window.
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {PointF{50, 50}}));
window->consumeMotionDown();
// The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
// Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
@@ -3805,18 +3738,17 @@
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
// First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {PointF{-10, -10}});
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {PointF{-10, -10}}));
window->assertNoEvents();
secondWindow->assertNoEvents();
// The second pointer lands inside `secondWindow`, which should receive a DOWN event.
// Now, `window` should get ACTION_OUTSIDE.
- motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- {PointF{-10, -10}, PointF{105, 105}});
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT,
+ {PointF{-10, -10}, PointF{105, 105}}));
const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
window->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
@@ -3825,9 +3757,9 @@
// The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
// no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
- motionArgs = generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}});
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(
+ generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
window->assertNoEvents();
secondWindow->consumeMotionMove();
thirdWindow->consumeMotionDown();
@@ -3844,10 +3776,10 @@
window->consumeFocusEvent(true);
- NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
- NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyKey(&keyDown);
- mDispatcher->notifyKey(&keyUp);
+ const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
+ const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyKey(keyDown);
+ mDispatcher->notifyKey(keyUp);
window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
@@ -3857,8 +3789,8 @@
window->consumeFocusEvent(false);
- mDispatcher->notifyKey(&keyDown);
- mDispatcher->notifyKey(&keyUp);
+ mDispatcher->notifyKey(keyDown);
+ mDispatcher->notifyKey(keyUp);
window->assertNoEvents();
}
@@ -3966,10 +3898,9 @@
// Send down to the first window. The point is represented in the display space. The point is
// selected so that if the hit test was performed with the point and the bounds being in
// different coordinate spaces, the event would end up in the incorrect window.
- NotifyMotionArgs downMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {PointF{75, 55}});
- mDispatcher->notifyMotion(&downMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {PointF{75, 55}}));
firstWindow->consumeMotionDown();
secondWindow->assertNoEvents();
@@ -4020,10 +3951,9 @@
auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
// Send down to the second window.
- NotifyMotionArgs downMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {PointF{150, 220}});
- mDispatcher->notifyMotion(&downMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {PointF{150, 220}}));
firstWindow->assertNoEvents();
const MotionEvent* event = secondWindow->consumeMotion();
@@ -4078,14 +4008,14 @@
for (const auto pointInsideWindow : insidePoints) {
const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
const PointF pointInDisplaySpace{p.x, p.y};
- const auto down = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
- mDispatcher->notifyMotion(&down);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {pointInDisplaySpace}));
window->consumeMotionDown();
- const auto up = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
- mDispatcher->notifyMotion(&up);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {pointInDisplaySpace}));
window->consumeMotionUp();
}
@@ -4095,13 +4025,13 @@
for (const auto pointOutsideWindow : outsidePoints) {
const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
const PointF pointInDisplaySpace{p.x, p.y};
- const auto down = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
- mDispatcher->notifyMotion(&down);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {pointInDisplaySpace}));
- const auto up = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
- mDispatcher->notifyMotion(&up);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {pointInDisplaySpace}));
}
window->assertNoEvents();
}
@@ -4139,10 +4069,8 @@
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
// Send down to the first window
- NotifyMotionArgs downMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&downMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
// Only the first window should get the down event
firstWindow->consumeMotionDown();
@@ -4159,10 +4087,8 @@
wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
// Send up event to the second window
- NotifyMotionArgs upMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&upMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT));
// The first window gets no events and the second gets up
firstWindow->assertNoEvents();
secondWindow->consumeMotionUp();
@@ -4198,10 +4124,8 @@
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
// Send down to the first window
- NotifyMotionArgs downMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&downMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
// Only the first window and spy should get the down event
spyWindow->consumeMotionDown();
firstWindow->consumeMotionDown();
@@ -4216,10 +4140,8 @@
secondWindow->consumeMotionDown();
// Send up event to the second window
- NotifyMotionArgs upMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&upMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT));
// The first window gets no events and the second+spy get up
firstWindow->assertNoEvents();
spyWindow->consumeMotionUp();
@@ -4245,19 +4167,16 @@
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
// Send down to the first window
- NotifyMotionArgs downMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {touchPoint});
- mDispatcher->notifyMotion(&downMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {touchPoint}));
// Only the first window should get the down event
firstWindow->consumeMotionDown();
secondWindow->assertNoEvents();
// Send pointer down to the first window
- NotifyMotionArgs pointerDownMotionArgs =
- generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- {touchPoint, touchPoint});
- mDispatcher->notifyMotion(&pointerDownMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
// Only the first window should get the pointer down event
firstWindow->consumeMotionPointerDown(1);
secondWindow->assertNoEvents();
@@ -4272,19 +4191,15 @@
secondWindow->consumeMotionPointerDown(1);
// Send pointer up to the second window
- NotifyMotionArgs pointerUpMotionArgs =
- generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- {touchPoint, touchPoint});
- mDispatcher->notifyMotion(&pointerUpMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
// The first window gets nothing and the second gets pointer up
firstWindow->assertNoEvents();
secondWindow->consumeMotionPointerUp(1);
// Send up event to the second window
- NotifyMotionArgs upMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&upMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT));
// The first window gets nothing and the second gets up
firstWindow->assertNoEvents();
secondWindow->consumeMotionUp();
@@ -4315,10 +4230,8 @@
{{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
// Send down to the first window
- NotifyMotionArgs downMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&downMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
// Only the first window should get the down event
firstWindow->consumeMotionDown();
@@ -4338,10 +4251,8 @@
wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
// Send up event to the second window
- NotifyMotionArgs upMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&upMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT));
// The first window gets no events and the second gets up
firstWindow->assertNoEvents();
secondWindow->consumeMotionUp();
@@ -4385,19 +4296,17 @@
PointF pointInSecond = {300, 600};
// Send down to the first window
- NotifyMotionArgs firstDownMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {pointInFirst});
- mDispatcher->notifyMotion(&firstDownMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {pointInFirst}));
// Only the first window should get the down event
firstWindow->consumeMotionDown();
secondWindow->assertNoEvents();
// Send down to the second window
- NotifyMotionArgs secondDownMotionArgs =
- generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- {pointInFirst, pointInSecond});
- mDispatcher->notifyMotion(&secondDownMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT,
+ {pointInFirst, pointInSecond}));
// The first window gets a move and the second a down
firstWindow->consumeMotionMove();
secondWindow->consumeMotionDown();
@@ -4409,19 +4318,16 @@
secondWindow->consumeMotionPointerDown(1);
// Send pointer up to the second window
- NotifyMotionArgs pointerUpMotionArgs =
- generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- {pointInFirst, pointInSecond});
- mDispatcher->notifyMotion(&pointerUpMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT,
+ {pointInFirst, pointInSecond}));
// The first window gets nothing and the second gets pointer up
firstWindow->assertNoEvents();
secondWindow->consumeMotionPointerUp(1);
// Send up event to the second window
- NotifyMotionArgs upMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&upMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT));
// The first window gets nothing and the second gets up
firstWindow->assertNoEvents();
secondWindow->consumeMotionUp();
@@ -4451,19 +4357,17 @@
PointF pointInSecond = {300, 600};
// Send down to the first window
- NotifyMotionArgs firstDownMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {pointInFirst});
- mDispatcher->notifyMotion(&firstDownMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {pointInFirst}));
// Only the first window should get the down event
firstWindow->consumeMotionDown();
secondWindow->assertNoEvents();
// Send down to the second window
- NotifyMotionArgs secondDownMotionArgs =
- generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- {pointInFirst, pointInSecond});
- mDispatcher->notifyMotion(&secondDownMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT,
+ {pointInFirst, pointInSecond}));
// The first window gets a move and the second a down
firstWindow->consumeMotionMove();
secondWindow->consumeMotionDown();
@@ -4478,19 +4382,16 @@
// The rest of the dispatch should proceed as normal
// Send pointer up to the second window
- NotifyMotionArgs pointerUpMotionArgs =
- generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- {pointInFirst, pointInSecond});
- mDispatcher->notifyMotion(&pointerUpMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT,
+ {pointInFirst, pointInSecond}));
// The first window gets MOVE and the second gets pointer up
firstWindow->consumeMotionMove();
secondWindow->consumeMotionUp();
// Send up event to the first window
- NotifyMotionArgs upMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&upMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT));
// The first window gets nothing and the second gets up
firstWindow->consumeMotionUp();
secondWindow->assertNoEvents();
@@ -4625,8 +4526,7 @@
window->consumeFocusEvent(true);
- NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
// Window should receive key down event.
window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
@@ -4639,8 +4539,7 @@
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
- NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
mDispatcher->waitForIdle();
window->assertNoEvents();
@@ -4655,13 +4554,10 @@
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
// Send key
- NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
// Send motion
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
// Window should receive only the motion event
window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
@@ -4688,19 +4584,17 @@
PointF pointInSecond = {300, 600};
// Send down to the first window
- NotifyMotionArgs firstDownMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {pointInFirst});
- mDispatcher->notifyMotion(&firstDownMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {pointInFirst}));
// Only the first window should get the down event
firstWindow->consumeMotionDown();
secondWindow->assertNoEvents();
// Send down to the second window
- NotifyMotionArgs secondDownMotionArgs =
- generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- {pointInFirst, pointInSecond});
- mDispatcher->notifyMotion(&secondDownMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT,
+ {pointInFirst, pointInSecond}));
// The first window gets a move and the second a down
firstWindow->consumeMotionMove();
secondWindow->consumeMotionDown();
@@ -4710,16 +4604,14 @@
generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
{pointInFirst, pointInSecond});
pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
- mDispatcher->notifyMotion(&pointerUpMotionArgs);
+ mDispatcher->notifyMotion(pointerUpMotionArgs);
// The first window gets move and the second gets cancel.
firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
// Send up event.
- NotifyMotionArgs upMotionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&upMotionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT));
// The first window gets up and the second gets nothing.
firstWindow->consumeMotionUp();
secondWindow->assertNoEvents();
@@ -4752,8 +4644,8 @@
sp<IBinder> getToken() { return mInputReceiver->getToken(); }
void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
- mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
- expectedDisplayId, expectedFlags);
+ mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
+ expectedFlags);
}
std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
@@ -4761,17 +4653,17 @@
void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
- mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
+ mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
expectedDisplayId, expectedFlags);
}
void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
- mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE,
+ mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
expectedDisplayId, expectedFlags);
}
void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
- mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
+ mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
expectedDisplayId, expectedFlags);
}
@@ -4785,7 +4677,7 @@
void consumeMotionPointerDown(int32_t pointerIdx) {
int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
(pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, ADISPLAY_ID_DEFAULT,
+ mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
/*expectedFlags=*/0);
}
@@ -4795,8 +4687,8 @@
ADD_FAILURE() << "No event was produced";
return nullptr;
}
- if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
- ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
+ if (event->getType() != InputEventType::MOTION) {
+ ADD_FAILURE() << "Expected MotionEvent, got " << *event;
return nullptr;
}
return static_cast<MotionEvent*>(event);
@@ -4941,7 +4833,7 @@
generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(motionArgs);
// Window should receive motion down event.
window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
@@ -4951,8 +4843,8 @@
motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
motionArgs.pointerCoords[0].getX() - 10);
- mDispatcher->notifyMotion(&motionArgs);
- window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
+ mDispatcher->notifyMotion(motionArgs);
+ window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
/*expectedFlags=*/0);
}
@@ -5020,8 +4912,8 @@
window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
- NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
- mDispatcher->notifyKey(&keyArgs);
+ const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
+ mDispatcher->notifyKey(keyArgs);
InputEvent* event = window->consume();
ASSERT_NE(event, nullptr);
@@ -5062,10 +4954,10 @@
mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
- NotifyMotionArgs motionArgs =
+ const NotifyMotionArgs motionArgs =
generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(motionArgs);
InputEvent* event = window->consume();
ASSERT_NE(event, nullptr);
@@ -5362,17 +5254,17 @@
{{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
// Use notifyMotion instead of injecting to avoid dealing with injection permissions
- NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {{50, 50}});
- mDispatcher->notifyMotion(&args);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {{50, 50}}));
slipperyExitWindow->consumeMotionDown();
slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
mDispatcher->setInputWindows(
{{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
- args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {{51, 51}});
- mDispatcher->notifyMotion(&args);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {{51, 51}}));
slipperyExitWindow->consumeMotionCancel();
@@ -5412,7 +5304,7 @@
NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
keyArgs.deviceId = deviceId;
keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(keyArgs);
// Window should receive key down event.
mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
@@ -5423,8 +5315,7 @@
InputEvent* repeatEvent = mWindow->consume();
ASSERT_NE(nullptr, repeatEvent);
- uint32_t eventType = repeatEvent->getType();
- ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
+ ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
uint32_t eventAction = repeatKeyEvent->getAction();
@@ -5436,10 +5327,10 @@
NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
keyArgs.deviceId = deviceId;
keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(keyArgs);
// Window should receive key down event.
- mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
+ mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
/*expectedFlags=*/0);
}
};
@@ -5499,8 +5390,7 @@
TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
sendAndConsumeKeyDown(DEVICE_ID);
expectKeyRepeatOnce(/*repeatCount=*/1);
- NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
- mDispatcher->notifyDeviceReset(&args);
+ mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
mWindow->assertNoEvents();
@@ -5612,7 +5502,7 @@
mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
// Old focus should receive a cancel event.
- windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
+ windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
AKEY_EVENT_FLAG_CANCELED);
// Test inject a key down, should timeout because of no target window.
@@ -5752,10 +5642,10 @@
motionArgs =
generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(motionArgs);
motionArgs =
generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(motionArgs);
ASSERT_TRUE(mDispatcher->waitForIdle());
if (expectToBeFiltered) {
const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
@@ -5769,9 +5659,9 @@
NotifyKeyArgs keyArgs;
keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(keyArgs);
keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(keyArgs);
ASSERT_TRUE(mDispatcher->waitForIdle());
if (expectToBeFiltered) {
@@ -5883,7 +5773,7 @@
InputEvent* received = mWindow->consume();
ASSERT_NE(nullptr, received);
ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
- ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
+ ASSERT_EQ(received->getType(), InputEventType::KEY);
KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
ASSERT_EQ(flags, keyEvent.getFlags());
}
@@ -5918,7 +5808,7 @@
InputEvent* received = mWindow->consume();
ASSERT_NE(nullptr, received);
ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
- ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
+ ASSERT_EQ(received->getType(), InputEventType::MOTION);
MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
ASSERT_EQ(flags, motionEvent.getFlags());
}
@@ -6099,9 +5989,8 @@
ASSERT_NE(nullptr, event) << name.c_str()
<< ": consumer should have returned non-NULL event.";
- ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
- << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
- << " event, got " << inputEventTypeToString(event->getType()) << " event";
+ ASSERT_EQ(InputEventType::MOTION, event->getType())
+ << name.c_str() << ": expected MotionEvent, got " << *event;
const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
assertMotionAction(expectedAction, motionEvent.getAction());
@@ -6122,9 +6011,8 @@
void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
std::vector<PointF> expectedPoints) {
- NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, touchedPoints);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, touchedPoints));
// Always consume from window1 since it's the window that has the InputReceiver
consumeMotionEvent(mWindow1, action, expectedPoints);
@@ -6798,7 +6686,7 @@
FOCUSED_WINDOW_LOCATION))
<< "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
mFocusedWindow->consumeMotionDown();
- mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
+ mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
ADISPLAY_ID_DEFAULT, /*flags=*/0);
// We consumed all events, so no ANR
ASSERT_TRUE(mDispatcher->waitForIdle());
@@ -6872,7 +6760,7 @@
// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
tapOnFocusedWindow();
- mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
+ mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
ADISPLAY_ID_DEFAULT, /*flags=*/0);
// Receive the events, but don't respond
std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
@@ -6997,17 +6885,16 @@
// The other window should not be affected by that.
TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
// Touch Window 1
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
- mDispatcher->notifyMotion(&motionArgs);
- mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {FOCUSED_WINDOW_LOCATION}));
+ mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
ADISPLAY_ID_DEFAULT, /*flags=*/0);
// Touch Window 2
- motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(
+ generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
const std::chrono::duration timeout =
mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
@@ -7022,7 +6909,7 @@
ASSERT_TRUE(moveOrCancelSequenceNum);
mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
ASSERT_NE(nullptr, event);
- ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
+ ASSERT_EQ(event->getType(), InputEventType::MOTION);
MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
mFocusedWindow->consumeMotionCancel();
@@ -7079,10 +6966,9 @@
std::this_thread::sleep_for(10ms);
// Touch unfocused window. This should force the pending key to get dropped.
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {UNFOCUSED_WINDOW_LOCATION}));
// We do not consume the motion right away, because that would require dispatcher to first
// process (== drop) the key event, and by that time, ANR will be raised.
@@ -7137,10 +7023,9 @@
TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
PointF touchedPoint = {10, 10};
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {touchedPoint});
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {touchedPoint}));
mNoInputWindow->assertNoEvents();
// Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
@@ -7165,10 +7050,9 @@
PointF touchedPoint = {10, 10};
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {touchedPoint});
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {touchedPoint}));
mNoInputWindow->assertNoEvents();
mBottomWindow->assertNoEvents();
@@ -7341,8 +7225,7 @@
}
void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
- const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
- mDispatcher->notifyPointerCaptureChanged(&args);
+ mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
}
PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
@@ -7518,10 +7401,9 @@
}
void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
- NotifyMotionArgs args =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, points);
- mDispatcher->notifyMotion(&args);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ points));
}
};
@@ -8234,7 +8116,7 @@
.displayId(SECOND_DISPLAY_ID)
.pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
.build()));
- windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
+ windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
SECOND_DISPLAY_ID, /*expectedFlag=*/0);
// Update window again.
mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
@@ -8331,27 +8213,22 @@
window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
// With the flag set, window should not get any input
- NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
window->assertNoEvents();
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
window->assertNoEvents();
// With the flag cleared, the window should get input
window->setDropInput(false);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
- keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
- motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
window->assertNoEvents();
}
@@ -8377,27 +8254,22 @@
window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
// With the flag set, window should not get any input
- NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
window->assertNoEvents();
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
window->assertNoEvents();
// With the flag cleared, the window should get input
window->setDropInputIfObscured(false);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
- keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
- motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
window->assertNoEvents();
}
@@ -8423,26 +8295,21 @@
window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
// With the flag set, window should not get any input
- NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
window->assertNoEvents();
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
window->assertNoEvents();
// When the window is no longer obscured because it went on top, it should get input
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
- keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyKey(&keyArgs);
+ mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
- motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT);
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
window->assertNoEvents();
}
@@ -9176,10 +9043,9 @@
}
void sendFingerEvent(int32_t action) {
- NotifyMotionArgs motionArgs =
+ mDispatcher->notifyMotion(
generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
- ADISPLAY_ID_DEFAULT, {PointF{20, 20}});
- mDispatcher->notifyMotion(&motionArgs);
+ ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
}
void sendStylusEvent(int32_t action) {
@@ -9187,7 +9053,7 @@
generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
- mDispatcher->notifyMotion(&motionArgs);
+ mDispatcher->notifyMotion(motionArgs);
}
};
diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h
index 63ca44c..df601ea 100644
--- a/services/inputflinger/tests/InputMapperTest.h
+++ b/services/inputflinger/tests/InputMapperTest.h
@@ -60,7 +60,8 @@
ftl::Flags<InputDeviceClass> classes, int bus = 0);
template <class T, typename... Args>
T& addMapperAndConfigure(Args... args) {
- T& mapper = mDevice->addMapper<T>(EVENTHUB_ID, args...);
+ T& mapper =
+ mDevice->addMapper<T>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), args...);
configureDevice(0);
std::list<NotifyArgs> resetArgList = mDevice->reset(ARBITRARY_TIME);
resetArgList += mapper.reset(ARBITRARY_TIME);
diff --git a/services/inputflinger/tests/InputProcessor_test.cpp b/services/inputflinger/tests/InputProcessor_test.cpp
index 0ffdef9..3b7cbfa 100644
--- a/services/inputflinger/tests/InputProcessor_test.cpp
+++ b/services/inputflinger/tests/InputProcessor_test.cpp
@@ -72,7 +72,7 @@
// Create a basic configuration change and send to processor
NotifyConfigurationChangedArgs args(/*sequenceNum=*/1, /*eventTime=*/2);
- mProcessor->notifyConfigurationChanged(&args);
+ mProcessor->notifyConfigurationChanged(args);
NotifyConfigurationChangedArgs outArgs;
ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyConfigurationChangedWasCalled(&outArgs));
ASSERT_EQ(args, outArgs);
@@ -85,10 +85,8 @@
AKEY_EVENT_ACTION_DOWN, /*flags=*/4, AKEYCODE_HOME, /*scanCode=*/5,
AMETA_NONE, /*downTime=*/6);
- mProcessor->notifyKey(&args);
- NotifyKeyArgs outArgs;
- ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyKeyWasCalled(&outArgs));
- ASSERT_EQ(args, outArgs);
+ mProcessor->notifyKey(args);
+ ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyKeyWasCalled(testing::Eq(args)));
}
/**
@@ -97,10 +95,8 @@
*/
TEST_F(InputProcessorTest, SendToNextStage_NotifyMotionArgs) {
NotifyMotionArgs motionArgs = generateBasicMotionArgs();
- mProcessor->notifyMotion(&motionArgs);
- NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(motionArgs, args);
+ mProcessor->notifyMotion(motionArgs);
+ ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyMotionWasCalled(testing::Eq(motionArgs)));
}
/**
@@ -111,7 +107,7 @@
NotifySwitchArgs args(/*sequenceNum=*/1, /*eventTime=*/2, /*policyFlags=*/3,
/*switchValues=*/4, /*switchMask=*/5);
- mProcessor->notifySwitch(&args);
+ mProcessor->notifySwitch(args);
NotifySwitchArgs outArgs;
ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifySwitchWasCalled(&outArgs));
ASSERT_EQ(args, outArgs);
@@ -124,7 +120,7 @@
TEST_F(InputProcessorTest, SendToNextStage_NotifyDeviceResetArgs) {
NotifyDeviceResetArgs args(/*sequenceNum=*/1, /*eventTime=*/2, /*deviceId=*/3);
- mProcessor->notifyDeviceReset(&args);
+ mProcessor->notifyDeviceReset(args);
NotifyDeviceResetArgs outArgs;
ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyDeviceResetWasCalled(&outArgs));
ASSERT_EQ(args, outArgs);
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 2223b35..da3fe5b 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -171,8 +171,9 @@
std::optional<DisplayViewport> mViewport;
public:
- FakeInputMapper(InputDeviceContext& deviceContext, uint32_t sources)
- : InputMapper(deviceContext),
+ FakeInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig,
+ uint32_t sources)
+ : InputMapper(deviceContext, readerConfig),
mSources(sources),
mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
mMetaState(0),
@@ -263,7 +264,7 @@
}
}
- std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration* config,
+ std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration& config,
uint32_t changes) override {
std::scoped_lock<std::mutex> lock(mLock);
mConfigureWasCalled = true;
@@ -271,7 +272,7 @@
// Find the associated viewport if exist.
const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
if (displayPort && (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- mViewport = config->getDisplayViewportByPort(*displayPort);
+ mViewport = config.getDisplayViewportByPort(*displayPort);
}
mStateChangedCondition.notify_all();
@@ -603,6 +604,7 @@
mReader->loopOnce();
mReader->loopOnce();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyInputDevicesChangedWasCalled());
ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
}
@@ -622,7 +624,9 @@
uint32_t sources,
const PropertyMap* configuration) {
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name);
- FakeInputMapper& mapper = device->addMapper<FakeInputMapper>(eventHubId, sources);
+ FakeInputMapper& mapper =
+ device->addMapper<FakeInputMapper>(eventHubId,
+ mFakePolicy->getReaderConfiguration(), sources);
mReader->pushNextDevice(device);
addDevice(eventHubId, name, classes, configuration);
return mapper;
@@ -674,8 +678,10 @@
// Add two subdevices to device
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
- device->addMapper<FakeInputMapper>(eventHubIds[0], AINPUT_SOURCE_KEYBOARD);
- device->addMapper<FakeInputMapper>(eventHubIds[1], AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
// Push same device instance for next device to be added, so they'll have same identifier.
mReader->pushNextDevice(device);
@@ -695,8 +701,10 @@
// Add two subdevices to device
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
- device->addMapper<FakeInputMapper>(eventHubIds[0], AINPUT_SOURCE_KEYBOARD);
- device->addMapper<FakeInputMapper>(eventHubIds[1], AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
// Push same device instance for next device to be added, so they'll have same identifier.
mReader->pushNextDevice(device);
@@ -721,7 +729,8 @@
constexpr int32_t eventHubId = 1;
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
- device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
mReader->pushNextDevice(device);
ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
@@ -967,7 +976,8 @@
constexpr int32_t eventHubId = 1;
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
- device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
mReader->pushNextDevice(device);
ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
@@ -1000,7 +1010,8 @@
constexpr int32_t eventHubId = 1;
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
- device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
mReader->pushNextDevice(device);
ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
@@ -1016,7 +1027,8 @@
const char* DEVICE_LOCATION = "USB1";
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
FakeInputMapper& mapper =
- device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_TOUCHSCREEN);
+ device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_TOUCHSCREEN);
mReader->pushNextDevice(device);
const uint8_t hdmi1 = 1;
@@ -1059,8 +1071,10 @@
constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
- device->addMapper<FakeInputMapper>(eventHubIds[0], AINPUT_SOURCE_KEYBOARD);
- device->addMapper<FakeInputMapper>(eventHubIds[1], AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
mReader->pushNextDevice(device);
mReader->pushNextDevice(device);
ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
@@ -1101,9 +1115,13 @@
// Add two subdevices to device
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
FakeInputMapper& mapperDevice1 =
- device->addMapper<FakeInputMapper>(eventHubIds[0], AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubIds[0],
+ mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
FakeInputMapper& mapperDevice2 =
- device->addMapper<FakeInputMapper>(eventHubIds[1], AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubIds[1],
+ mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
mReader->pushNextDevice(device);
mReader->pushNextDevice(device);
ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
@@ -1145,8 +1163,9 @@
class FakeVibratorInputMapper : public FakeInputMapper {
public:
- FakeVibratorInputMapper(InputDeviceContext& deviceContext, uint32_t sources)
- : FakeInputMapper(deviceContext, sources) {}
+ FakeVibratorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig, uint32_t sources)
+ : FakeInputMapper(deviceContext, readerConfig, sources) {}
std::vector<int32_t> getVibratorIds() override { return getDeviceContext().getVibratorIds(); }
};
@@ -1159,7 +1178,9 @@
const char* DEVICE_LOCATION = "BLUETOOTH";
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
FakeVibratorInputMapper& mapper =
- device->addMapper<FakeVibratorInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeVibratorInputMapper>(eventHubId,
+ mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
mReader->pushNextDevice(device);
ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
@@ -1324,6 +1345,7 @@
// to the test device will show up in mReader. We wait for those input devices to
// show up before beginning the tests.
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled());
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
}
@@ -2319,7 +2341,7 @@
TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
// Configuration.
InputReaderConfiguration config;
- std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, &config, 0);
+ std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, 0);
// Reset.
unused += mDevice->reset(ARBITRARY_TIME);
@@ -2362,7 +2384,8 @@
mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "key", "value");
FakeInputMapper& mapper1 =
- mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD);
+ mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
mapper1.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
mapper1.setMetaState(AMETA_ALT_ON);
mapper1.addSupportedKeyCode(AKEYCODE_A);
@@ -2374,11 +2397,12 @@
mapper1.setSwitchState(4, AKEY_STATE_DOWN);
FakeInputMapper& mapper2 =
- mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_TOUCHSCREEN);
+ mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_TOUCHSCREEN);
mapper2.setMetaState(AMETA_SHIFT_ON);
InputReaderConfiguration config;
- std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, &config, 0);
+ std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, 0);
std::optional<std::string> propertyValue = mDevice->getConfiguration().getString("key");
ASSERT_TRUE(propertyValue.has_value())
@@ -2455,7 +2479,8 @@
// 1. Device is disabled if the viewport corresponding to the associated display is not found
// 2. Device is disabled when setEnabled API is called
TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) {
- mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_TOUCHSCREEN);
+ mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_TOUCHSCREEN);
// First Configuration.
std::list<NotifyArgs> unused =
@@ -2498,7 +2523,8 @@
TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) {
// Device should be enabled by default.
mFakePolicy->clearViewports();
- mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD);
+ mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
std::list<NotifyArgs> unused =
mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0);
ASSERT_TRUE(mDevice->isEnabled());
@@ -2532,7 +2558,8 @@
TEST_F(InputDeviceTest, Configure_UniqueId_CorrectlyMatches) {
mFakePolicy->clearViewports();
- mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD);
+ mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
std::list<NotifyArgs> unused =
mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0);
@@ -2554,7 +2581,7 @@
mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY);
InputDevice device(mReader->getContext(), /*id=*/1, /*generation=*/2, /*identifier=*/{});
- device.addEventHubDevice(TEST_EVENTHUB_ID, /*populateMappers=*/true);
+ device.addEventHubDevice(TEST_EVENTHUB_ID, mFakePolicy->getReaderConfiguration());
device.removeEventHubDevice(TEST_EVENTHUB_ID);
std::string dumpStr, eventHubDevStr;
device.dump(dumpStr, eventHubDevStr);
@@ -3390,7 +3417,9 @@
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
KeyboardInputMapper& mapper2 =
- device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD,
+ device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
+ mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
std::list<NotifyArgs> unused =
device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
@@ -3500,7 +3529,9 @@
mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
KeyboardInputMapper& mapper2 =
- device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD,
+ device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
+ mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
std::list<NotifyArgs> unused =
device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
@@ -3561,7 +3592,9 @@
mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
KeyboardInputMapper& mapper2 =
- device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD,
+ device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
+ mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
std::list<NotifyArgs> unused =
device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
@@ -3644,7 +3677,8 @@
}
TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) {
- mDevice->addMapper<KeyboardInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD,
+ mDevice->addMapper<KeyboardInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
std::list<NotifyArgs> unused =
mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0);
@@ -3669,7 +3703,7 @@
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
InputReaderConfiguration config;
- std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, &config, 0);
+ std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, 0);
ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
@@ -6735,6 +6769,54 @@
ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mDevice->getSources());
}
+TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) {
+ // Initialize the device without setting device source to touch navigation.
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(ui::ROTATION_0);
+ prepareButtons();
+ prepareAxes(POSITION);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
+
+ // Set a physical frame in the display viewport.
+ auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
+ viewport->physicalLeft = 0;
+ viewport->physicalTop = 0;
+ viewport->physicalRight = DISPLAY_WIDTH / 2;
+ viewport->physicalBottom = DISPLAY_HEIGHT / 2;
+ mFakePolicy->updateViewport(*viewport);
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
+ SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+
+ // Hovering inside the physical frame produces events.
+ processKey(mapper, BTN_TOOL_PEN, 1);
+ processMove(mapper, RAW_X_MIN + 1, RAW_Y_MIN + 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
+
+ // Leaving the physical frame ends the hovering gesture.
+ processMove(mapper, RAW_X_MAX - 1, RAW_Y_MAX - 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)));
+
+ // Moving outside the physical frame does not produce events.
+ processMove(mapper, RAW_X_MAX - 2, RAW_Y_MAX - 2);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
+
+ // Re-entering the physical frame produces events.
+ processMove(mapper, RAW_X_MIN, RAW_Y_MIN);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
+}
+
// --- TouchDisplayProjectionTest ---
class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {
@@ -9318,7 +9400,9 @@
String8("touchScreen"));
// Setup the second touch screen device.
- MultiTouchInputMapper& mapper2 = device2->addMapper<MultiTouchInputMapper>(SECOND_EVENTHUB_ID);
+ MultiTouchInputMapper& mapper2 =
+ device2->addMapper<MultiTouchInputMapper>(SECOND_EVENTHUB_ID,
+ mFakePolicy->getReaderConfiguration());
std::list<NotifyArgs> unused =
device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
/*changes=*/0);
diff --git a/services/inputflinger/tests/TestInputListener.cpp b/services/inputflinger/tests/TestInputListener.cpp
index 2801072..fc917dd 100644
--- a/services/inputflinger/tests/TestInputListener.cpp
+++ b/services/inputflinger/tests/TestInputListener.cpp
@@ -29,6 +29,14 @@
TestInputListener::~TestInputListener() {}
+void TestInputListener::assertNotifyInputDevicesChangedWasCalled(
+ NotifyInputDevicesChangedArgs* outEventArgs) {
+ ASSERT_NO_FATAL_FAILURE(
+ assertCalled<NotifyInputDevicesChangedArgs>(outEventArgs,
+ "Expected notifyInputDevicesChanged() "
+ "to have been called."));
+}
+
void TestInputListener::assertNotifyConfigurationChangedWasCalled(
NotifyConfigurationChangedArgs* outEventArgs) {
ASSERT_NO_FATAL_FAILURE(
@@ -160,43 +168,47 @@
}
template <class NotifyArgsType>
-void TestInputListener::addToQueue(const NotifyArgsType* args) {
+void TestInputListener::addToQueue(const NotifyArgsType& args) {
std::scoped_lock<std::mutex> lock(mLock);
std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
- queue.push_back(*args);
+ queue.push_back(args);
mCondition.notify_all();
}
-void TestInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
+void TestInputListener::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
+ addToQueue<NotifyInputDevicesChangedArgs>(args);
+}
+
+void TestInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
addToQueue<NotifyConfigurationChangedArgs>(args);
}
-void TestInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
+void TestInputListener::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
addToQueue<NotifyDeviceResetArgs>(args);
}
-void TestInputListener::notifyKey(const NotifyKeyArgs* args) {
+void TestInputListener::notifyKey(const NotifyKeyArgs& args) {
addToQueue<NotifyKeyArgs>(args);
}
-void TestInputListener::notifyMotion(const NotifyMotionArgs* args) {
+void TestInputListener::notifyMotion(const NotifyMotionArgs& args) {
addToQueue<NotifyMotionArgs>(args);
}
-void TestInputListener::notifySwitch(const NotifySwitchArgs* args) {
+void TestInputListener::notifySwitch(const NotifySwitchArgs& args) {
addToQueue<NotifySwitchArgs>(args);
}
-void TestInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
+void TestInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) {
addToQueue<NotifyPointerCaptureChangedArgs>(args);
}
-void TestInputListener::notifySensor(const NotifySensorArgs* args) {
+void TestInputListener::notifySensor(const NotifySensorArgs& args) {
addToQueue<NotifySensorArgs>(args);
}
-void TestInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) {
+void TestInputListener::notifyVibratorState(const NotifyVibratorStateArgs& args) {
addToQueue<NotifyVibratorStateArgs>(args);
}
diff --git a/services/inputflinger/tests/TestInputListener.h b/services/inputflinger/tests/TestInputListener.h
index 9665f70..deb6048 100644
--- a/services/inputflinger/tests/TestInputListener.h
+++ b/services/inputflinger/tests/TestInputListener.h
@@ -35,6 +35,9 @@
using TimePoint = std::chrono::time_point<std::chrono::system_clock>;
+ void assertNotifyInputDevicesChangedWasCalled(
+ NotifyInputDevicesChangedArgs* outEventArgs = nullptr);
+
void assertNotifyConfigurationChangedWasCalled(
NotifyConfigurationChangedArgs* outEventArgs = nullptr);
@@ -74,30 +77,33 @@
void assertNotCalled(std::string message, std::optional<TimePoint> timeout = {});
template <class NotifyArgsType>
- void addToQueue(const NotifyArgsType* args);
+ void addToQueue(const NotifyArgsType& args);
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
+ virtual void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
+ virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
- virtual void notifyKey(const NotifyKeyArgs* args) override;
+ virtual void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
- virtual void notifyMotion(const NotifyMotionArgs* args) override;
+ virtual void notifyKey(const NotifyKeyArgs& args) override;
- virtual void notifySwitch(const NotifySwitchArgs* args) override;
+ virtual void notifyMotion(const NotifyMotionArgs& args) override;
- virtual void notifySensor(const NotifySensorArgs* args) override;
+ virtual void notifySwitch(const NotifySwitchArgs& args) override;
- virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
+ virtual void notifySensor(const NotifySensorArgs& args) override;
- virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
+ virtual void notifyVibratorState(const NotifyVibratorStateArgs& args) override;
+
+ virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
std::mutex mLock;
std::condition_variable mCondition;
const std::chrono::milliseconds mEventHappenedTimeout;
const std::chrono::milliseconds mEventDidNotHappenTimeout;
- std::tuple<std::vector<NotifyConfigurationChangedArgs>, //
+ std::tuple<std::vector<NotifyInputDevicesChangedArgs>, //
+ std::vector<NotifyConfigurationChangedArgs>, //
std::vector<NotifyDeviceResetArgs>, //
std::vector<NotifyKeyArgs>, //
std::vector<NotifyMotionArgs>, //
diff --git a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
index 2a9ace0..1fff2c7 100644
--- a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
+++ b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
@@ -421,7 +421,7 @@
// Create a basic configuration change and send to blocker
NotifyConfigurationChangedArgs args(/*sequenceNum=*/1, /*eventTime=*/2);
- mBlocker->notifyConfigurationChanged(&args);
+ mBlocker->notifyConfigurationChanged(args);
NotifyConfigurationChangedArgs outArgs;
ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyConfigurationChangedWasCalled(&outArgs));
ASSERT_EQ(args, outArgs);
@@ -438,10 +438,8 @@
AKEY_EVENT_ACTION_DOWN, /*flags=*/4, AKEYCODE_HOME, /*scanCode=*/5,
AMETA_NONE, /*downTime=*/6);
- mBlocker->notifyKey(&args);
- NotifyKeyArgs outArgs;
- ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyKeyWasCalled(&outArgs));
- ASSERT_EQ(args, outArgs);
+ mBlocker->notifyKey(args);
+ ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyKeyWasCalled(testing::Eq(args)));
}
/**
@@ -452,10 +450,8 @@
TEST_F(UnwantedInteractionBlockerTest, DownEventIsPassedToNextListener) {
NotifyMotionArgs motionArgs =
generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}});
- mBlocker->notifyMotion(&motionArgs);
- NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(motionArgs, args);
+ mBlocker->notifyMotion(motionArgs);
+ ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyMotionWasCalled(testing::Eq(motionArgs)));
}
/**
@@ -466,7 +462,7 @@
NotifySwitchArgs args(/*sequenceNum=*/1, /*eventTime=*/2, /*policyFlags=*/3,
/*switchValues=*/4, /*switchMask=*/5);
- mBlocker->notifySwitch(&args);
+ mBlocker->notifySwitch(args);
NotifySwitchArgs outArgs;
ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifySwitchWasCalled(&outArgs));
ASSERT_EQ(args, outArgs);
@@ -479,7 +475,7 @@
TEST_F(UnwantedInteractionBlockerTest, DeviceResetIsPassedToNextListener) {
NotifyDeviceResetArgs args(/*sequenceNum=*/1, /*eventTime=*/2, DEVICE_ID);
- mBlocker->notifyDeviceReset(&args);
+ mBlocker->notifyDeviceReset(args);
NotifyDeviceResetArgs outArgs;
ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyDeviceResetWasCalled(&outArgs));
ASSERT_EQ(args, outArgs);
@@ -491,25 +487,20 @@
* a crash due to inconsistent event stream could have occurred.
*/
TEST_F(UnwantedInteractionBlockerTest, NoCrashWhenResetHappens) {
- NotifyMotionArgs args;
- mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
- mBlocker->notifyMotion(
- &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}})));
- mBlocker->notifyMotion(
- &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}})));
- NotifyDeviceResetArgs resetArgs(/*sequenceNum=*/1, /*eventTime=*/3, DEVICE_ID);
- mBlocker->notifyDeviceReset(&resetArgs);
+ mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}});
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}}));
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}}));
+ mBlocker->notifyDeviceReset({/*sequenceNum=*/1, /*eventTime=*/3, DEVICE_ID});
// Start a new gesture with a DOWN event, even though the previous event stream was incomplete.
- mBlocker->notifyMotion(
- &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/4, DOWN, {{7, 8, 9}})));
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/4, DOWN, {{7, 8, 9}}));
}
TEST_F(UnwantedInteractionBlockerTest, NoCrashWhenStylusSourceWithFingerToolIsReceived) {
- mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
+ mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}});
NotifyMotionArgs args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}});
args.pointerProperties[0].toolType = ToolType::FINGER;
args.source = AINPUT_SOURCE_STYLUS;
- mBlocker->notifyMotion(&args);
+ mBlocker->notifyMotion(args);
}
/**
@@ -517,48 +508,41 @@
* UnwantedInteractionBlocker has not changed, there should not be a reset.
*/
TEST_F(UnwantedInteractionBlockerTest, NoResetIfDeviceInfoChanges) {
- NotifyMotionArgs args;
- mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
- mBlocker->notifyMotion(
- &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}})));
- mBlocker->notifyMotion(
- &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}})));
+ mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}});
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}}));
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}}));
// Now pretend the device changed, even though nothing is different for DEVICE_ID in practice.
- mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
+ mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}});
// The MOVE event continues the gesture that started before 'devices changed', so it should not
// cause a crash.
- mBlocker->notifyMotion(
- &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/4, MOVE, {{7, 8, 9}})));
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/4, MOVE, {{7, 8, 9}}));
}
/**
* Send a touch event, and then a stylus event. Make sure that both work.
*/
TEST_F(UnwantedInteractionBlockerTest, StylusAfterTouchWorks) {
- NotifyMotionArgs args;
- mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
- args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}});
- mBlocker->notifyMotion(&args);
- args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{4, 5, 6}});
- mBlocker->notifyMotion(&args);
- args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, UP, {{4, 5, 6}});
- mBlocker->notifyMotion(&args);
+ mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}});
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}}));
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{4, 5, 6}}));
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, UP, {{4, 5, 6}}));
// Now touch down stylus
+ NotifyMotionArgs args;
args = generateMotionArgs(/*downTime=*/3, /*eventTime=*/3, DOWN, {{10, 20, 30}});
args.pointerProperties[0].toolType = ToolType::STYLUS;
args.source |= AINPUT_SOURCE_STYLUS;
- mBlocker->notifyMotion(&args);
+ mBlocker->notifyMotion(args);
args = generateMotionArgs(/*downTime=*/3, /*eventTime=*/4, MOVE, {{40, 50, 60}});
args.pointerProperties[0].toolType = ToolType::STYLUS;
args.source |= AINPUT_SOURCE_STYLUS;
- mBlocker->notifyMotion(&args);
+ mBlocker->notifyMotion(args);
args = generateMotionArgs(/*downTime=*/3, /*eventTime=*/5, UP, {{40, 50, 60}});
args.pointerProperties[0].toolType = ToolType::STYLUS;
args.source |= AINPUT_SOURCE_STYLUS;
- mBlocker->notifyMotion(&args);
+ mBlocker->notifyMotion(args);
}
/**
@@ -568,17 +552,14 @@
* options
*/
TEST_F(UnwantedInteractionBlockerTest, DumpCanBeAccessedOnAnotherThread) {
- mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
- NotifyMotionArgs args1 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}});
- mBlocker->notifyMotion(&args1);
+ mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}});
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}}));
std::thread dumpThread([this]() {
std::string dump;
mBlocker->dump(dump);
});
- NotifyMotionArgs args2 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{4, 5, 6}});
- mBlocker->notifyMotion(&args2);
- NotifyMotionArgs args3 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, UP, {{4, 5, 6}});
- mBlocker->notifyMotion(&args3);
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{4, 5, 6}}));
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, UP, {{4, 5, 6}}));
dumpThread.join();
}
@@ -587,22 +568,19 @@
* of the touch is large. This is an integration test that checks that this filter kicks in.
*/
TEST_F(UnwantedInteractionBlockerTest, HeuristicFilterWorks) {
- mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
+ mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}});
// Small touch down
- NotifyMotionArgs args1 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}});
- mBlocker->notifyMotion(&args1);
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}}));
mTestListener.assertNotifyMotionWasCalled(WithMotionAction(DOWN));
// Large touch oval on the next move
- NotifyMotionArgs args2 =
- generateMotionArgs(/*downTime=*/0, RESAMPLE_PERIOD, MOVE, {{4, 5, 200}});
- mBlocker->notifyMotion(&args2);
+ mBlocker->notifyMotion(
+ generateMotionArgs(/*downTime=*/0, RESAMPLE_PERIOD, MOVE, {{4, 5, 200}}));
mTestListener.assertNotifyMotionWasCalled(WithMotionAction(MOVE));
// Lift up the touch to force the model to decide on whether it's a palm
- NotifyMotionArgs args3 =
- generateMotionArgs(/*downTime=*/0, 2 * RESAMPLE_PERIOD, UP, {{4, 5, 200}});
- mBlocker->notifyMotion(&args3);
+ mBlocker->notifyMotion(
+ generateMotionArgs(/*downTime=*/0, 2 * RESAMPLE_PERIOD, UP, {{4, 5, 200}}));
mTestListener.assertNotifyMotionWasCalled(WithMotionAction(CANCEL));
}
@@ -613,19 +591,19 @@
* This is similar to `HeuristicFilterWorks` test, but for stylus tool.
*/
TEST_F(UnwantedInteractionBlockerTest, StylusIsNotBlocked) {
- InputDeviceInfo info = generateTestDeviceInfo();
- info.addSource(AINPUT_SOURCE_STYLUS);
- mBlocker->notifyInputDevicesChanged({info});
+ NotifyInputDevicesChangedArgs deviceChangedArgs = {/*id=*/0, {generateTestDeviceInfo()}};
+ deviceChangedArgs.inputDeviceInfos[0].addSource(AINPUT_SOURCE_STYLUS);
+ mBlocker->notifyInputDevicesChanged(deviceChangedArgs);
NotifyMotionArgs args1 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}});
args1.pointerProperties[0].toolType = ToolType::STYLUS;
- mBlocker->notifyMotion(&args1);
+ mBlocker->notifyMotion(args1);
mTestListener.assertNotifyMotionWasCalled(WithMotionAction(DOWN));
// Move the stylus, setting large TOUCH_MAJOR/TOUCH_MINOR dimensions
NotifyMotionArgs args2 =
generateMotionArgs(/*downTime=*/0, RESAMPLE_PERIOD, MOVE, {{4, 5, 200}});
args2.pointerProperties[0].toolType = ToolType::STYLUS;
- mBlocker->notifyMotion(&args2);
+ mBlocker->notifyMotion(args2);
mTestListener.assertNotifyMotionWasCalled(WithMotionAction(MOVE));
// Lift up the stylus. If it were a touch event, this would force the model to decide on whether
@@ -633,7 +611,7 @@
NotifyMotionArgs args3 =
generateMotionArgs(/*downTime=*/0, 2 * RESAMPLE_PERIOD, UP, {{4, 5, 200}});
args3.pointerProperties[0].toolType = ToolType::STYLUS;
- mBlocker->notifyMotion(&args3);
+ mBlocker->notifyMotion(args3);
mTestListener.assertNotifyMotionWasCalled(WithMotionAction(UP));
}
@@ -643,34 +621,34 @@
* Stylus event should continue to work even after touch is detected as a palm.
*/
TEST_F(UnwantedInteractionBlockerTest, TouchIsBlockedWhenMixedWithStylus) {
- InputDeviceInfo info = generateTestDeviceInfo();
- info.addSource(AINPUT_SOURCE_STYLUS);
- mBlocker->notifyInputDevicesChanged({info});
+ NotifyInputDevicesChangedArgs deviceChangedArgs = {/*id=*/0, {generateTestDeviceInfo()}};
+ deviceChangedArgs.inputDeviceInfos[0].addSource(AINPUT_SOURCE_STYLUS);
+ mBlocker->notifyInputDevicesChanged(deviceChangedArgs);
// Touch down
NotifyMotionArgs args1 = generateMotionArgs(/*downTime=*/0, /*eventTime=*/0, DOWN, {{1, 2, 3}});
- mBlocker->notifyMotion(&args1);
+ mBlocker->notifyMotion(args1);
mTestListener.assertNotifyMotionWasCalled(WithMotionAction(DOWN));
// Stylus pointer down
NotifyMotionArgs args2 = generateMotionArgs(/*downTime=*/0, RESAMPLE_PERIOD, POINTER_1_DOWN,
{{1, 2, 3}, {10, 20, 30}});
args2.pointerProperties[1].toolType = ToolType::STYLUS;
- mBlocker->notifyMotion(&args2);
+ mBlocker->notifyMotion(args2);
mTestListener.assertNotifyMotionWasCalled(WithMotionAction(POINTER_1_DOWN));
// Large touch oval on the next finger move
NotifyMotionArgs args3 = generateMotionArgs(/*downTime=*/0, 2 * RESAMPLE_PERIOD, MOVE,
{{1, 2, 300}, {11, 21, 30}});
args3.pointerProperties[1].toolType = ToolType::STYLUS;
- mBlocker->notifyMotion(&args3);
+ mBlocker->notifyMotion(args3);
mTestListener.assertNotifyMotionWasCalled(WithMotionAction(MOVE));
// Lift up the finger pointer. It should be canceled due to the heuristic filter.
NotifyMotionArgs args4 = generateMotionArgs(/*downTime=*/0, 3 * RESAMPLE_PERIOD, POINTER_0_UP,
{{1, 2, 300}, {11, 21, 30}});
args4.pointerProperties[1].toolType = ToolType::STYLUS;
- mBlocker->notifyMotion(&args4);
+ mBlocker->notifyMotion(args4);
mTestListener.assertNotifyMotionWasCalled(
AllOf(WithMotionAction(POINTER_0_UP), WithFlags(FLAG_CANCELED)));
@@ -678,7 +656,7 @@
generateMotionArgs(/*downTime=*/0, 4 * RESAMPLE_PERIOD, MOVE, {{12, 22, 30}});
args5.pointerProperties[0].id = args4.pointerProperties[1].id;
args5.pointerProperties[0].toolType = ToolType::STYLUS;
- mBlocker->notifyMotion(&args5);
+ mBlocker->notifyMotion(args5);
mTestListener.assertNotifyMotionWasCalled(WithMotionAction(MOVE));
// Lift up the stylus pointer
@@ -686,7 +664,7 @@
generateMotionArgs(/*downTime=*/0, 5 * RESAMPLE_PERIOD, UP, {{4, 5, 200}});
args6.pointerProperties[0].id = args4.pointerProperties[1].id;
args6.pointerProperties[0].toolType = ToolType::STYLUS;
- mBlocker->notifyMotion(&args6);
+ mBlocker->notifyMotion(args6);
mTestListener.assertNotifyMotionWasCalled(WithMotionAction(UP));
}
@@ -699,18 +677,16 @@
TEST_F(UnwantedInteractionBlockerTestDeathTest, InconsistentEventAfterResetCausesACrash) {
ScopedSilentDeath _silentDeath;
NotifyMotionArgs args;
- mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
- mBlocker->notifyMotion(
- &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}})));
- mBlocker->notifyMotion(
- &(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}})));
+ mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}});
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, DOWN, {{1, 2, 3}}));
+ mBlocker->notifyMotion(generateMotionArgs(/*downTime=*/0, /*eventTime=*/2, MOVE, {{4, 5, 6}}));
NotifyDeviceResetArgs resetArgs(/*sequenceNum=*/1, /*eventTime=*/3, DEVICE_ID);
- mBlocker->notifyDeviceReset(&resetArgs);
+ mBlocker->notifyDeviceReset(resetArgs);
// Sending MOVE without a DOWN -> should crash!
ASSERT_DEATH(
{
- mBlocker->notifyMotion(&(args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/4,
- MOVE, {{7, 8, 9}})));
+ mBlocker->notifyMotion(
+ generateMotionArgs(/*downTime=*/0, /*eventTime=*/4, MOVE, {{7, 8, 9}}));
},
"Could not find slot");
}
@@ -720,9 +696,13 @@
*/
TEST_F(UnwantedInteractionBlockerTestDeathTest, WhenMoveWithoutDownCausesACrash) {
ScopedSilentDeath _silentDeath;
- NotifyMotionArgs args = generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{1, 2, 3}});
- mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
- ASSERT_DEATH({ mBlocker->notifyMotion(&args); }, "Could not find slot");
+ mBlocker->notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}});
+ ASSERT_DEATH(
+ {
+ mBlocker->notifyMotion(
+ generateMotionArgs(/*downTime=*/0, /*eventTime=*/1, MOVE, {{1, 2, 3}}));
+ },
+ "Could not find slot");
}
class PalmRejectorTest : public testing::Test {
diff --git a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
index 0d5f30c..8ed1f31 100644
--- a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
@@ -38,8 +38,8 @@
std::make_shared<ThreadSafeFuzzedDataProvider>(data, size);
FuzzContainer fuzzer(fdp);
- CursorInputMapper& mapper = fuzzer.getMapper<CursorInputMapper>();
auto policyConfig = fuzzer.getPolicyConfig();
+ CursorInputMapper& mapper = fuzzer.getMapper<CursorInputMapper>(policyConfig);
// Loop through mapper operations until randomness is exhausted.
while (fdp->remaining_bytes() > 0) {
@@ -52,13 +52,13 @@
[&]() -> void { mapper.getSources(); },
[&]() -> void {
std::list<NotifyArgs> unused =
- mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig,
fdp->ConsumeIntegral<int32_t>());
},
[&]() -> void {
// Need to reconfigure with 0 or you risk a NPE.
std::list<NotifyArgs> unused =
- mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig, 0);
InputDeviceInfo info;
mapper.populateDeviceInfo(info);
},
@@ -71,7 +71,7 @@
// Need to reconfigure with 0 or you risk a NPE.
std::list<NotifyArgs> unused =
- mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig, 0);
RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(),
fdp->ConsumeIntegral<nsecs_t>(),
fdp->ConsumeIntegral<int32_t>(),
@@ -90,7 +90,7 @@
[&]() -> void {
// Need to reconfigure with 0 or you risk a NPE.
std::list<NotifyArgs> unused =
- mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig, 0);
mapper.getAssociatedDisplayId();
},
})();
diff --git a/services/inputflinger/tests/fuzzers/FuzzContainer.h b/services/inputflinger/tests/fuzzers/FuzzContainer.h
index 76d2bcd..d42d11c 100644
--- a/services/inputflinger/tests/fuzzers/FuzzContainer.h
+++ b/services/inputflinger/tests/fuzzers/FuzzContainer.h
@@ -59,7 +59,7 @@
void configureDevice() {
nsecs_t arbitraryTime = mFdp->ConsumeIntegral<nsecs_t>();
std::list<NotifyArgs> out;
- out += mFuzzDevice->configure(arbitraryTime, &mPolicyConfig, 0);
+ out += mFuzzDevice->configure(arbitraryTime, mPolicyConfig, 0);
out += mFuzzDevice->reset(arbitraryTime);
for (const NotifyArgs& args : out) {
mFuzzListener.notify(args);
diff --git a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
index 6617f65..f8ebc97 100644
--- a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
@@ -67,51 +67,42 @@
fdp.PickValueInArray<std::function<void()>>({
[&]() -> void {
// SendToNextStage_NotifyConfigurationChangedArgs
- NotifyConfigurationChangedArgs
- args(/*sequenceNum=*/fdp.ConsumeIntegral<uint32_t>(),
- /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>());
- mClassifier->notifyConfigurationChanged(&args);
+ mClassifier->notifyConfigurationChanged(
+ {/*sequenceNum=*/fdp.ConsumeIntegral<int32_t>(),
+ /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>()});
},
[&]() -> void {
// SendToNextStage_NotifyKeyArgs
const nsecs_t eventTime = fdp.ConsumeIntegral<nsecs_t>();
const nsecs_t readTime =
eventTime + fdp.ConsumeIntegralInRange<nsecs_t>(0, 1E8);
- NotifyKeyArgs keyArgs(/*sequenceNum=*/fdp.ConsumeIntegral<uint32_t>(),
- eventTime, readTime,
- /*deviceId=*/fdp.ConsumeIntegral<int32_t>(),
- AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT,
- /*policyFlags=*/fdp.ConsumeIntegral<uint32_t>(),
- AKEY_EVENT_ACTION_DOWN,
- /*flags=*/fdp.ConsumeIntegral<int32_t>(), AKEYCODE_HOME,
- /*scanCode=*/fdp.ConsumeIntegral<int32_t>(), AMETA_NONE,
- /*downTime=*/fdp.ConsumeIntegral<nsecs_t>());
-
- mClassifier->notifyKey(&keyArgs);
+ mClassifier->notifyKey({/*sequenceNum=*/fdp.ConsumeIntegral<int32_t>(),
+ eventTime, readTime,
+ /*deviceId=*/fdp.ConsumeIntegral<int32_t>(),
+ AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT,
+ /*policyFlags=*/fdp.ConsumeIntegral<uint32_t>(),
+ AKEY_EVENT_ACTION_DOWN,
+ /*flags=*/fdp.ConsumeIntegral<int32_t>(), AKEYCODE_HOME,
+ /*scanCode=*/fdp.ConsumeIntegral<int32_t>(), AMETA_NONE,
+ /*downTime=*/fdp.ConsumeIntegral<nsecs_t>()});
},
[&]() -> void {
// SendToNextStage_NotifyMotionArgs
- NotifyMotionArgs motionArgs = generateFuzzedMotionArgs(fdp);
- mClassifier->notifyMotion(&motionArgs);
+ mClassifier->notifyMotion(generateFuzzedMotionArgs(fdp));
},
[&]() -> void {
// SendToNextStage_NotifySwitchArgs
- NotifySwitchArgs switchArgs(/*sequenceNum=*/fdp.ConsumeIntegral<uint32_t>(),
- /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>(),
- /*policyFlags=*/fdp.ConsumeIntegral<uint32_t>(),
- /*switchValues=*/fdp.ConsumeIntegral<uint32_t>(),
- /*switchMask=*/fdp.ConsumeIntegral<uint32_t>());
-
- mClassifier->notifySwitch(&switchArgs);
+ mClassifier->notifySwitch({/*sequenceNum=*/fdp.ConsumeIntegral<int32_t>(),
+ /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>(),
+ /*policyFlags=*/fdp.ConsumeIntegral<uint32_t>(),
+ /*switchValues=*/fdp.ConsumeIntegral<uint32_t>(),
+ /*switchMask=*/fdp.ConsumeIntegral<uint32_t>()});
},
[&]() -> void {
// SendToNextStage_NotifyDeviceResetArgs
- NotifyDeviceResetArgs resetArgs(
- /*sequenceNum=*/fdp.ConsumeIntegral<uint32_t>(),
- /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>(),
- /*deviceId=*/fdp.ConsumeIntegral<int32_t>());
-
- mClassifier->notifyDeviceReset(&resetArgs);
+ mClassifier->notifyDeviceReset({/*sequenceNum=*/fdp.ConsumeIntegral<int32_t>(),
+ /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>(),
+ /*deviceId=*/fdp.ConsumeIntegral<int32_t>()});
},
[&]() -> void {
// InputClassifierConverterTest
diff --git a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
index 14cb8a5..0a6327d 100644
--- a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
@@ -44,10 +44,10 @@
std::make_shared<ThreadSafeFuzzedDataProvider>(data, size);
FuzzContainer fuzzer(fdp);
- KeyboardInputMapper& mapper =
- fuzzer.getMapper<KeyboardInputMapper>(fdp->ConsumeIntegral<uint32_t>(),
- fdp->ConsumeIntegral<int32_t>());
auto policyConfig = fuzzer.getPolicyConfig();
+ KeyboardInputMapper& mapper =
+ fuzzer.getMapper<KeyboardInputMapper>(policyConfig, fdp->ConsumeIntegral<uint32_t>(),
+ fdp->ConsumeIntegral<int32_t>());
// Loop through mapper operations until randomness is exhausted.
while (fdp->remaining_bytes() > 0) {
@@ -64,7 +64,7 @@
[&]() -> void { mapper.getSources(); },
[&]() -> void {
std::list<NotifyArgs> unused =
- mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig,
fdp->ConsumeIntegral<uint32_t>());
},
[&]() -> void {
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index 9f4aa5c..1e44e0f 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -293,14 +293,15 @@
class FuzzInputListener : public virtual InputListenerInterface {
public:
- void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override {}
- void notifyKey(const NotifyKeyArgs* args) override {}
- void notifyMotion(const NotifyMotionArgs* args) override {}
- void notifySwitch(const NotifySwitchArgs* args) override {}
- void notifySensor(const NotifySensorArgs* args) override{};
- void notifyVibratorState(const NotifyVibratorStateArgs* args) override{};
- void notifyDeviceReset(const NotifyDeviceResetArgs* args) override {}
- void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override{};
+ void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override {}
+ void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override {}
+ void notifyKey(const NotifyKeyArgs& args) override {}
+ void notifyMotion(const NotifyMotionArgs& args) override {}
+ void notifySwitch(const NotifySwitchArgs& args) override {}
+ void notifySensor(const NotifySensorArgs& args) override{};
+ void notifyVibratorState(const NotifyVibratorStateArgs& args) override{};
+ void notifyDeviceReset(const NotifyDeviceResetArgs& args) override {}
+ void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override{};
};
class FuzzInputReaderContext : public InputReaderContext {
diff --git a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
index 8352a90..fdf9f41 100644
--- a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
@@ -61,8 +61,8 @@
std::make_shared<ThreadSafeFuzzedDataProvider>(data, size);
FuzzContainer fuzzer(fdp);
- MultiTouchInputMapper& mapper = fuzzer.getMapper<MultiTouchInputMapper>();
auto policyConfig = fuzzer.getPolicyConfig();
+ MultiTouchInputMapper& mapper = fuzzer.getMapper<MultiTouchInputMapper>(policyConfig);
// Loop through mapper operations until randomness is exhausted.
while (fdp->remaining_bytes() > 0) {
@@ -79,7 +79,7 @@
[&]() -> void { mapper.getSources(); },
[&]() -> void {
std::list<NotifyArgs> unused =
- mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig,
fdp->ConsumeIntegral<uint32_t>());
},
[&]() -> void {
diff --git a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
index c4938f2..590207e 100644
--- a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
@@ -24,8 +24,8 @@
std::make_shared<ThreadSafeFuzzedDataProvider>(data, size);
FuzzContainer fuzzer(fdp);
- SwitchInputMapper& mapper = fuzzer.getMapper<SwitchInputMapper>();
auto policyConfig = fuzzer.getPolicyConfig();
+ SwitchInputMapper& mapper = fuzzer.getMapper<SwitchInputMapper>(policyConfig);
// Loop through mapper operations until randomness is exhausted.
while (fdp->remaining_bytes() > 0) {
diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index 94de55c..b0fbe5d 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -74,6 +74,14 @@
}
}
+void BatteryService::noteWakeupSensorEventImpl(int64_t elapsedNanos, uid_t uid, int handle) {
+ if (checkService()) {
+ int64_t identity = IPCThreadState::self()->clearCallingIdentity();
+ mBatteryStatService->noteWakeupSensorEvent(elapsedNanos, uid, handle);
+ IPCThreadState::self()->restoreCallingIdentity(identity);
+ }
+}
+
bool BatteryService::checkService() {
if (mBatteryStatService == nullptr) {
const sp<IServiceManager> sm(defaultServiceManager());
diff --git a/services/sensorservice/BatteryService.h b/services/sensorservice/BatteryService.h
index 13fc58a..60ef03f 100644
--- a/services/sensorservice/BatteryService.h
+++ b/services/sensorservice/BatteryService.h
@@ -19,11 +19,14 @@
#include <batterystats/IBatteryStats.h>
#include <utils/Singleton.h>
+#include <utils/SortedVector.h>
+#include <utils/SystemClock.h>
namespace android {
// ---------------------------------------------------------------------------
class BatteryService : public Singleton<BatteryService> {
+ static constexpr int64_t WAKEUP_SENSOR_EVENT_DEBOUNCE_MS = 1000;
friend class Singleton<BatteryService>;
sp<IBatteryStats> mBatteryStatService;
@@ -32,6 +35,7 @@
void enableSensorImpl(uid_t uid, int handle);
void disableSensorImpl(uid_t uid, int handle);
+ void noteWakeupSensorEventImpl(int64_t elapsedNanos, uid_t uid, int handle);
struct Info {
uid_t uid;
@@ -44,6 +48,7 @@
}
};
+ int64_t mLastWakeupSensorEventReportedMs;
Mutex mActivationsLock;
SortedVector<Info> mActivations;
bool addSensor(uid_t uid, int handle);
@@ -57,6 +62,15 @@
static void disableSensor(uid_t uid, int handle) {
BatteryService::getInstance().disableSensorImpl(uid, handle);
}
+ static void noteWakeupSensorEvent(int64_t elapsed, uid_t uid, int handle) {
+ BatteryService& instance = BatteryService::getInstance();
+ const int64_t nowElapsedMs = elapsedRealtime();
+ if (nowElapsedMs >= (instance.mLastWakeupSensorEventReportedMs
+ + WAKEUP_SENSOR_EVENT_DEBOUNCE_MS)) {
+ instance.noteWakeupSensorEventImpl(elapsed, uid, handle);
+ instance.mLastWakeupSensorEventReportedMs = nowElapsedMs;
+ }
+ }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 7a6b31d..dc5070c 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -23,6 +23,7 @@
#include <sensor/SensorEventQueue.h>
#include "vec.h"
+#include "BatteryService.h"
#include "SensorEventConnection.h"
#include "SensorDevice.h"
@@ -391,6 +392,8 @@
if (hasSensorAccess()) {
index_wake_up_event = findWakeUpSensorEventLocked(scratch, count);
if (index_wake_up_event >= 0) {
+ BatteryService::noteWakeupSensorEvent(scratch[index_wake_up_event].timestamp,
+ mUid, scratch[index_wake_up_event].sensor);
scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
++mWakeLockRefCount;
#if DEBUG_CONNECTIONS
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 01db0cd..20f4de1 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -535,8 +535,8 @@
}
void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) {
- using fps_approx_ops::operator==;
- if (mRequestedRefreshRate == 0_Hz) {
+ using fps_approx_ops::operator<=;
+ if (mRequestedRefreshRate <= 0_Hz) {
return;
}
@@ -547,7 +547,12 @@
}
unsigned divisor = static_cast<unsigned>(
- std::round(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue()));
+ std::floor(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue()));
+ if (divisor == 0) {
+ mAdjustedRefreshRate = 0_Hz;
+ return;
+ }
+
mAdjustedRefreshRate = pacesetterDisplayRefreshRate / divisor;
}
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index c30465f..5913d4b 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -30,7 +30,7 @@
auto lhsLayer = lhs.first->getLayer();
auto rhsLayer = rhs.first->getLayer();
if (lhsLayer->layerStack.id != rhsLayer->layerStack.id) {
- return lhsLayer->layerStack.id > rhsLayer->layerStack.id;
+ return lhsLayer->layerStack.id < rhsLayer->layerStack.id;
}
if (lhsLayer->z != rhsLayer->z) {
return lhsLayer->z < rhsLayer->z;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 25cbe7a..ce7d37e 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -817,7 +817,8 @@
snapshot.frameRateSelectionPriority = requested.frameRateSelectionPriority;
}
- if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content)) {
+ if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content) ||
+ snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) {
snapshot.color.rgb = requested.getColor().rgb;
snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic;
snapshot.backgroundBlurRadius = args.supportsBlur
@@ -1069,6 +1070,10 @@
// touches from going outside the cloned area.
if (path.isClone()) {
snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
+ // Cloned layers shouldn't handle watch outside since their z order is not determined by
+ // WM or the client.
+ snapshot.inputInfo.inputConfig.clear(gui::WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH);
+
mNeedsTouchableRegionCrop.insert(path);
}
}
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 1f670c8..b397b82 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -32,10 +32,6 @@
using namespace ftl::flag_operators;
namespace {
-std::string layerIdToString(uint32_t layerId) {
- return layerId == UNASSIGNED_LAYER_ID ? "none" : std::to_string(layerId);
-}
-
std::string layerIdsToString(const std::vector<uint32_t>& layerIds) {
std::stringstream stream;
stream << "{";
@@ -158,12 +154,15 @@
RequestedLayerState::Changes::VisibleRegion |
RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Input;
}
- if (clientState.what & layer_state_t::eBufferChanged) {
- changes |= RequestedLayerState::Changes::Buffer;
- }
- if (clientState.what & layer_state_t::eSidebandStreamChanged) {
- changes |= RequestedLayerState::Changes::SidebandStream;
- }
+ }
+ if (clientState.what & layer_state_t::eBufferChanged) {
+ barrierProducerId = std::max(bufferData->producerId, barrierProducerId);
+ barrierFrameNumber = std::max(bufferData->frameNumber, barrierFrameNumber);
+ // TODO(b/277265947) log and flush transaction trace when we detect out of order updates
+ changes |= RequestedLayerState::Changes::Buffer;
+ }
+ if (clientState.what & layer_state_t::eSidebandStreamChanged) {
+ changes |= RequestedLayerState::Changes::SidebandStream;
}
if (what & (layer_state_t::eAlphaChanged)) {
if (oldAlpha == 0 || color.a == 0) {
@@ -323,9 +322,13 @@
std::string RequestedLayerState::getDebugString() const {
std::stringstream debug;
- debug << "RequestedLayerState{" << name << " parent=" << layerIdToString(parentId)
- << " relativeParent=" << layerIdToString(relativeParentId)
- << " mirrorId=" << layerIdsToString(mirrorIds) << " handle=" << handleAlive << " z=" << z;
+ debug << "RequestedLayerState{" << name;
+ if (parentId != UNASSIGNED_LAYER_ID) debug << " parentId=" << parentId;
+ if (relativeParentId != UNASSIGNED_LAYER_ID) debug << " relativeParentId=" << relativeParentId;
+ if (!mirrorIds.empty()) debug << " mirrorId=" << layerIdsToString(mirrorIds);
+ if (!handleAlive) debug << " !handle";
+ if (z != 0) debug << " z=" << z;
+ if (layerStack.id != 0) debug << " layerStack=" << layerStack.id;
return debug.str();
}
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 216e95f..f15f023 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -111,6 +111,8 @@
ui::LayerStack layerStackToMirror = ui::INVALID_LAYER_STACK;
uint32_t touchCropId = UNASSIGNED_LAYER_ID;
uint32_t bgColorLayerId = UNASSIGNED_LAYER_ID;
+ uint64_t barrierFrameNumber = 0;
+ uint32_t barrierProducerId = 0;
// book keeping states
bool handleAlive = true;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3406e92..9c232b1 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -167,6 +167,9 @@
mDrawingState.sequence = 0;
mDrawingState.transform.set(0, 0);
mDrawingState.frameNumber = 0;
+ mDrawingState.barrierFrameNumber = 0;
+ mDrawingState.producerId = 0;
+ mDrawingState.barrierProducerId = 0;
mDrawingState.bufferTransform = 0;
mDrawingState.transformToDisplayInverse = false;
mDrawingState.crop.makeInvalid();
@@ -2439,16 +2442,7 @@
info.inputConfig |= WindowInfo::InputConfig::NOT_TOUCHABLE;
}
- // For compatibility reasons we let layers which can receive input
- // receive input before they have actually submitted a buffer. Because
- // of this we use canReceiveInput instead of isVisible to check the
- // policy-visibility, ignoring the buffer state. However for layers with
- // hasInputInfo()==false we can use the real visibility state.
- // We are just using these layers for occlusion detection in
- // InputDispatcher, and obviously if they aren't visible they can't occlude
- // anything.
- const bool visible = hasInputInfo() ? canReceiveInput() : isVisible();
- info.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
+ info.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !isVisibleForInput());
info.alpha = getAlpha();
fillTouchOcclusionMode(info);
@@ -3070,7 +3064,13 @@
}
mDrawingState.producerId = bufferData.producerId;
+ mDrawingState.barrierProducerId =
+ std::max(mDrawingState.producerId, mDrawingState.barrierProducerId);
mDrawingState.frameNumber = frameNumber;
+ mDrawingState.barrierFrameNumber =
+ std::max(mDrawingState.frameNumber, mDrawingState.barrierFrameNumber);
+
+ // TODO(b/277265947) log and flush transaction trace when we detect out of order updates
mDrawingState.releaseBufferListener = bufferData.releaseBufferListener;
mDrawingState.buffer = std::move(buffer);
mDrawingState.clientCacheId = bufferData.cachedBuffer;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 70b4e9b..8d7c362 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -139,9 +139,16 @@
ui::Dataspace dataspace;
uint64_t frameNumber;
+ // high watermark framenumber to use to check for barriers to protect ourselves
+ // from out of order transactions
+ uint64_t barrierFrameNumber;
ui::Transform transform;
uint32_t producerId = 0;
+ // high watermark producerId to use to check for barriers to protect ourselves
+ // from out of order transactions
+ uint32_t barrierProducerId = 0;
+
uint32_t bufferTransform;
bool transformToDisplayInverse;
Region transparentRegionHint;
@@ -365,6 +372,21 @@
bool canReceiveInput() const;
/*
+ * Whether or not the layer should be considered visible for input calculations.
+ */
+ virtual bool isVisibleForInput() const {
+ // For compatibility reasons we let layers which can receive input
+ // receive input before they have actually submitted a buffer. Because
+ // of this we use canReceiveInput instead of isVisible to check the
+ // policy-visibility, ignoring the buffer state. However for layers with
+ // hasInputInfo()==false we can use the real visibility state.
+ // We are just using these layers for occlusion detection in
+ // InputDispatcher, and obviously if they aren't visible they can't occlude
+ // anything.
+ return hasInputInfo() ? canReceiveInput() : isVisible();
+ }
+
+ /*
* isProtected - true if the layer may contain protected contents in the
* GRALLOC_USAGE_PROTECTED sense.
*/
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 5a90d58..bae3739 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -78,17 +78,16 @@
.count();
}
-bool LayerInfo::isFrequent(nsecs_t now) const {
- using fps_approx_ops::operator>=;
+LayerInfo::Frequent LayerInfo::isFrequent(nsecs_t now) const {
// If we know nothing about this layer (e.g. after touch event),
// we consider it as frequent as it might be the start of an animation.
if (mFrameTimes.size() < kFrequentLayerWindowSize) {
- return true;
+ return {/* isFrequent */ true, /* clearHistory */ false, /* isConclusive */ true};
}
// Non-active layers are also infrequent
if (mLastUpdatedTime < getActiveLayerThreshold(now)) {
- return false;
+ return {/* isFrequent */ false, /* clearHistory */ false, /* isConclusive */ true};
}
// We check whether we can classify this layer as frequent or infrequent:
@@ -111,12 +110,20 @@
}
if (isFrequent || isInfrequent) {
- return isFrequent;
+ // If the layer was previously inconclusive, we clear
+ // the history as indeterminate layers changed to frequent,
+ // and we should not look at the stale data.
+ return {isFrequent, isFrequent && !mIsFrequencyConclusive, /* isConclusive */ true};
}
// If we can't determine whether the layer is frequent or not, we return
- // the last known classification.
- return !mLastRefreshRate.infrequent;
+ // the last known classification and mark the layer frequency as inconclusive.
+ isFrequent = !mLastRefreshRate.infrequent;
+
+ // If the layer was previously tagged as animating, we clear
+ // the history as it is likely the layer just changed its behavior,
+ // and we should not look at stale data.
+ return {isFrequent, isFrequent && mLastRefreshRate.animating, /* isConclusive */ false};
}
Fps LayerInfo::getFps(nsecs_t now) const {
@@ -273,19 +280,18 @@
return {LayerHistory::LayerVoteType::Max, Fps()};
}
- if (!isFrequent(now)) {
+ const LayerInfo::Frequent frequent = isFrequent(now);
+ mIsFrequencyConclusive = frequent.isConclusive;
+ if (!frequent.isFrequent) {
ATRACE_FORMAT_INSTANT("infrequent");
ALOGV("%s is infrequent", mName.c_str());
mLastRefreshRate.infrequent = true;
- // Infrequent layers vote for mininal refresh rate for
+ // Infrequent layers vote for minimal refresh rate for
// battery saving purposes and also to prevent b/135718869.
return {LayerHistory::LayerVoteType::Min, Fps()};
}
- // If the layer was previously tagged as animating or infrequent, we clear
- // the history as it is likely the layer just changed its behavior
- // and we should not look at stale data
- if (mLastRefreshRate.animating || mLastRefreshRate.infrequent) {
+ if (frequent.clearHistory) {
clearHistory(now);
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index a3523ac..c5a6057 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -181,6 +181,7 @@
mFrameTimeValidSince = std::chrono::time_point<std::chrono::steady_clock>(timePoint);
mLastRefreshRate = {};
mRefreshRateHistory.clear();
+ mIsFrequencyConclusive = true;
}
void clearHistory(nsecs_t now) {
@@ -251,7 +252,15 @@
static constexpr float MARGIN_CONSISTENT_FPS = 1.0;
};
- bool isFrequent(nsecs_t now) const;
+ // Represents whether we were able to determine either layer is frequent or infrequent
+ bool mIsFrequencyConclusive = true;
+ struct Frequent {
+ bool isFrequent;
+ bool clearHistory;
+ // Represents whether we were able to determine isFrequent conclusively
+ bool isConclusive;
+ };
+ Frequent isFrequent(nsecs_t now) const;
bool isAnimating(nsecs_t now) const;
bool hasEnoughDataForHeuristic() const;
std::optional<Fps> calculateRefreshRateIfPossible(const RefreshRateSelector&, nsecs_t now);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 3e12db6..8ddcfa1 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -130,7 +130,7 @@
pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
}
- applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
+ applyNewVsyncScheduleIfNonNull(std::move(pacesetterVsyncSchedule));
}
void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
@@ -149,7 +149,7 @@
pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
}
- applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
+ applyNewVsyncScheduleIfNonNull(std::move(pacesetterVsyncSchedule));
}
void Scheduler::run() {
@@ -693,16 +693,17 @@
pacesetterVsyncSchedule = promotePacesetterDisplayLocked(pacesetterIdOpt);
}
- applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
+ applyNewVsyncScheduleIfNonNull(std::move(pacesetterVsyncSchedule));
}
std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked(
std::optional<PhysicalDisplayId> pacesetterIdOpt) {
// TODO(b/241286431): Choose the pacesetter display.
+ const auto oldPacesetterDisplayIdOpt = mPacesetterDisplayId;
mPacesetterDisplayId = pacesetterIdOpt.value_or(mRefreshRateSelectors.begin()->first);
ALOGI("Display %s is the pacesetter", to_string(*mPacesetterDisplayId).c_str());
- auto vsyncSchedule = getVsyncScheduleLocked(*mPacesetterDisplayId);
+ auto newVsyncSchedule = getVsyncScheduleLocked(*mPacesetterDisplayId);
if (const auto pacesetterPtr = pacesetterSelectorPtrLocked()) {
pacesetterPtr->setIdleTimerCallbacks(
{.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
@@ -713,15 +714,28 @@
pacesetterPtr->startIdleTimer();
+ // Track the new period, which may have changed due to switching to a
+ // new pacesetter or due to a hotplug event. In the former case, this
+ // is important so that VSYNC modulation does not get stuck in the
+ // initiated state if a transition started on the old pacesetter.
const Fps refreshRate = pacesetterPtr->getActiveMode().modePtr->getFps();
- vsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(),
- true /* force */);
+ newVsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(),
+ true /* force */);
}
- return vsyncSchedule;
+ if (oldPacesetterDisplayIdOpt == mPacesetterDisplayId) {
+ return nullptr;
+ }
+ return newVsyncSchedule;
}
-void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule) {
- onNewVsyncSchedule(vsyncSchedule->getDispatch());
+void Scheduler::applyNewVsyncScheduleIfNonNull(
+ std::shared_ptr<VsyncSchedule> pacesetterSchedulePtr) {
+ if (!pacesetterSchedulePtr) {
+ // The pacesetter has not changed, so there is no new VsyncSchedule to
+ // apply.
+ return;
+ }
+ onNewVsyncSchedule(pacesetterSchedulePtr->getDispatch());
std::vector<android::EventThread*> threads;
{
std::lock_guard<std::mutex> lock(mConnectionsLock);
@@ -731,7 +745,7 @@
}
}
for (auto* thread : threads) {
- thread->onNewVsyncSchedule(vsyncSchedule);
+ thread->onNewVsyncSchedule(pacesetterSchedulePtr);
}
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 3423652..720a1cb 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -329,10 +329,12 @@
// MessageQueue and EventThread need to use the new pacesetter's
// VsyncSchedule, and this must happen while mDisplayLock is *not* locked,
// or else we may deadlock with EventThread.
+ // Returns the new pacesetter's VsyncSchedule, or null if the pacesetter is
+ // unchanged.
std::shared_ptr<VsyncSchedule> promotePacesetterDisplayLocked(
std::optional<PhysicalDisplayId> pacesetterIdOpt = std::nullopt)
REQUIRES(kMainThreadContext, mDisplayLock);
- void applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule>) EXCLUDES(mDisplayLock);
+ void applyNewVsyncScheduleIfNonNull(std::shared_ptr<VsyncSchedule>) EXCLUDES(mDisplayLock);
// Blocks until the pacesetter's idle timer thread exits. `mDisplayLock` must not be locked by
// the caller on the main thread to avoid deadlock, since the timer thread locks it before exit.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2f024ce..31bf7ef 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1149,7 +1149,10 @@
displayIdOpt = getPhysicalDisplayIdLocked(displayToken);
}
- if (!displayIdOpt) {
+ // TODO (b/277364366): Clients should be updated to pass in the display they
+ // want, rather than us picking an arbitrary one (the pacesetter, in this
+ // case).
+ if (displayToken && !displayIdOpt) {
ALOGE("%s: Invalid physical display token %p", __func__, displayToken.get());
return NAME_NOT_FOUND;
}
@@ -3712,17 +3715,33 @@
return;
}
+ std::unordered_set<Layer*> visibleLayers;
+ mDrawingState.traverse([&visibleLayers](Layer* layer) {
+ if (layer->isVisibleForInput()) {
+ visibleLayers.insert(layer);
+ }
+ });
+ bool visibleLayersChanged = false;
+ if (visibleLayers != mVisibleLayers) {
+ visibleLayersChanged = true;
+ mVisibleLayers = std::move(visibleLayers);
+ }
+
BackgroundExecutor::getInstance().sendCallbacks({[updateWindowInfo,
windowInfos = std::move(windowInfos),
displayInfos = std::move(displayInfos),
inputWindowCommands =
std::move(mInputWindowCommands),
- inputFlinger = mInputFlinger, this]() {
+ inputFlinger = mInputFlinger, this,
+ visibleLayersChanged]() {
ATRACE_NAME("BackgroundExecutor::updateInputFlinger");
if (updateWindowInfo) {
mWindowInfosListenerInvoker
- ->windowInfosChanged(windowInfos, displayInfos,
- inputWindowCommands.windowInfosReportedListeners);
+ ->windowInfosChanged(std::move(windowInfos), std::move(displayInfos),
+ std::move(
+ inputWindowCommands.windowInfosReportedListeners),
+ /* forceImmediateCall= */ visibleLayersChanged ||
+ !inputWindowCommands.focusRequests.empty());
} else {
// If there are listeners but no changes to input windows, call the listeners
// immediately.
@@ -4228,7 +4247,7 @@
// The current producerId is already a newer producer than the buffer that has a
// barrier. This means the incoming buffer is older and we can release it here. We
// don't wait on the barrier since we know that's stale information.
- if (layer->getDrawingState().producerId > s.bufferData->producerId) {
+ if (layer->getDrawingState().barrierProducerId > s.bufferData->producerId) {
layer->callReleaseBufferCallback(s.bufferData->releaseBufferListener,
externalTexture->getBuffer(),
s.bufferData->frameNumber,
@@ -4239,7 +4258,7 @@
return TraverseBuffersReturnValues::DELETE_AND_CONTINUE_TRAVERSAL;
}
- if (layer->getDrawingState().frameNumber < s.bufferData->barrierFrameNumber) {
+ if (layer->getDrawingState().barrierFrameNumber < s.bufferData->barrierFrameNumber) {
const bool willApplyBarrierFrame =
flushState.bufferLayersReadyToPresent.contains(s.surface.get()) &&
((flushState.bufferLayersReadyToPresent.get(s.surface.get()) >=
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5783c8d..eb9dc74 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -499,7 +499,7 @@
// Implements ISurfaceComposer
sp<IBinder> createDisplay(const String8& displayName, bool secure,
- float requestedRefreshRate = 0);
+ float requestedRefreshRate = 0.0f);
void destroyDisplay(const sp<IBinder>& displayToken);
std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const EXCLUDES(mStateLock) {
Mutex::Autolock lock(mStateLock);
@@ -1424,6 +1424,11 @@
TransactionHandler mTransactionHandler;
display::DisplayMap<ui::LayerStack, frontend::DisplayInfo> mFrontEndDisplayInfos;
bool mFrontEndDisplayInfosChanged = false;
+
+ // Layers visible during the last commit. This set should only be used for testing set equality
+ // and membership. The pointers should not be dereferenced as it's possible the set contains
+ // pointers to freed layers.
+ std::unordered_set<Layer*> mVisibleLayers;
};
class SurfaceComposerAIDL : public gui::BnSurfaceComposer {
diff --git a/services/surfaceflinger/TEST_MAPPING b/services/surfaceflinger/TEST_MAPPING
index 57752b7..155a275 100644
--- a/services/surfaceflinger/TEST_MAPPING
+++ b/services/surfaceflinger/TEST_MAPPING
@@ -7,6 +7,14 @@
"name": "libcompositionengine_test"
},
{
+ "name": "libgui_test",
+ "options": [
+ {
+ "native-test-flag": "--gtest_filter=\"InputSurfacesTest*:MultiDisplayTests*\""
+ }
+ ]
+ },
+ {
"name": "libscheduler_test"
}
],
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
index 292083b..856fbbb 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
@@ -25,20 +25,17 @@
using gui::IWindowInfosListener;
using gui::WindowInfo;
-struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowInfosReportedListener,
- DeathRecipient {
- explicit WindowInfosReportedListener(
- size_t callbackCount,
- const std::unordered_set<sp<gui::IWindowInfosReportedListener>,
- SpHash<gui::IWindowInfosReportedListener>>&
- windowInfosReportedListeners)
- : mCallbacksPending(callbackCount),
- mWindowInfosReportedListeners(windowInfosReportedListeners) {}
+using WindowInfosListenerVector = ftl::SmallVector<const sp<IWindowInfosListener>, 3>;
+
+struct WindowInfosReportedListenerInvoker : gui::BnWindowInfosReportedListener,
+ IBinder::DeathRecipient {
+ WindowInfosReportedListenerInvoker(WindowInfosListenerVector windowInfosListeners,
+ WindowInfosReportedListenerSet windowInfosReportedListeners)
+ : mCallbacksPending(windowInfosListeners.size()),
+ mWindowInfosListeners(std::move(windowInfosListeners)),
+ mWindowInfosReportedListeners(std::move(windowInfosReportedListeners)) {}
binder::Status onWindowInfosReported() override {
- // TODO(b/222421815) There could potentially be callbacks that we don't need to wait for
- // before calling the WindowInfosReportedListeners coming from InputWindowCommands. Filter
- // the list of callbacks down to those from system server.
if (--mCallbacksPending == 0) {
for (const auto& listener : mWindowInfosReportedListeners) {
sp<IBinder> asBinder = IInterface::asBinder(listener);
@@ -46,6 +43,12 @@
listener->onWindowInfosReported();
}
}
+
+ auto wpThis = wp<WindowInfosReportedListenerInvoker>::fromExisting(this);
+ for (const auto& listener : mWindowInfosListeners) {
+ sp<IBinder> binder = IInterface::asBinder(listener);
+ binder->unlinkToDeath(wpThis);
+ }
}
return binder::Status::ok();
}
@@ -54,9 +57,9 @@
private:
std::atomic<size_t> mCallbacksPending;
- std::unordered_set<sp<gui::IWindowInfosReportedListener>,
- SpHash<gui::IWindowInfosReportedListener>>
- mWindowInfosReportedListeners;
+ static constexpr size_t kStaticCapacity = 3;
+ const WindowInfosListenerVector mWindowInfosListeners;
+ WindowInfosReportedListenerSet mWindowInfosReportedListeners;
};
void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) {
@@ -82,38 +85,81 @@
}
void WindowInfosListenerInvoker::windowInfosChanged(
- const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>& displayInfos,
- const std::unordered_set<sp<gui::IWindowInfosReportedListener>,
- SpHash<gui::IWindowInfosReportedListener>>&
- windowInfosReportedListeners) {
- ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners;
+ std::vector<WindowInfo> windowInfos, std::vector<DisplayInfo> displayInfos,
+ WindowInfosReportedListenerSet reportedListeners, bool forceImmediateCall) {
+ reportedListeners.insert(sp<WindowInfosListenerInvoker>::fromExisting(this));
+ auto callListeners = [this, windowInfos = std::move(windowInfos),
+ displayInfos = std::move(displayInfos)](
+ WindowInfosReportedListenerSet reportedListeners) mutable {
+ WindowInfosListenerVector windowInfosListeners;
+ {
+ std::scoped_lock lock(mListenersMutex);
+ for (const auto& [_, listener] : mWindowInfosListeners) {
+ windowInfosListeners.push_back(listener);
+ }
+ }
+
+ auto reportedInvoker =
+ sp<WindowInfosReportedListenerInvoker>::make(windowInfosListeners,
+ std::move(reportedListeners));
+
+ for (const auto& listener : windowInfosListeners) {
+ sp<IBinder> asBinder = IInterface::asBinder(listener);
+
+ // linkToDeath is used here to ensure that the windowInfosReportedListeners
+ // are called even if one of the windowInfosListeners dies before
+ // calling onWindowInfosReported.
+ asBinder->linkToDeath(reportedInvoker);
+
+ auto status =
+ listener->onWindowInfosChanged(windowInfos, displayInfos, reportedInvoker);
+ if (!status.isOk()) {
+ reportedInvoker->onWindowInfosReported();
+ }
+ }
+ };
+
{
- std::scoped_lock lock(mListenersMutex);
- for (const auto& [_, listener] : mWindowInfosListeners) {
- windowInfosListeners.push_back(listener);
+ std::scoped_lock lock(mMessagesMutex);
+ // If there are unacked messages and this isn't a forced call, then return immediately.
+ // If a forced window infos change doesn't happen first, the update will be sent after
+ // the WindowInfosReportedListeners are called. If a forced window infos change happens or
+ // if there are subsequent delayed messages before this update is sent, then this message
+ // will be dropped and the listeners will only be called with the latest info. This is done
+ // to reduce the amount of binder memory used.
+ if (mActiveMessageCount > 0 && !forceImmediateCall) {
+ mWindowInfosChangedDelayed = std::move(callListeners);
+ mReportedListenersDelayed.merge(reportedListeners);
+ return;
}
+
+ mWindowInfosChangedDelayed = nullptr;
+ reportedListeners.merge(mReportedListenersDelayed);
+ mActiveMessageCount++;
+ }
+ callListeners(std::move(reportedListeners));
+}
+
+binder::Status WindowInfosListenerInvoker::onWindowInfosReported() {
+ std::function<void(WindowInfosReportedListenerSet)> callListeners;
+ WindowInfosReportedListenerSet reportedListeners;
+
+ {
+ std::scoped_lock lock{mMessagesMutex};
+ mActiveMessageCount--;
+ if (!mWindowInfosChangedDelayed || mActiveMessageCount > 0) {
+ return binder::Status::ok();
+ }
+
+ mActiveMessageCount++;
+ callListeners = std::move(mWindowInfosChangedDelayed);
+ mWindowInfosChangedDelayed = nullptr;
+ reportedListeners = std::move(mReportedListenersDelayed);
+ mReportedListenersDelayed.clear();
}
- auto windowInfosReportedListener = windowInfosReportedListeners.empty()
- ? nullptr
- : sp<WindowInfosReportedListener>::make(windowInfosListeners.size(),
- windowInfosReportedListeners);
- for (const auto& listener : windowInfosListeners) {
- sp<IBinder> asBinder = IInterface::asBinder(listener);
-
- // linkToDeath is used here to ensure that the windowInfosReportedListeners
- // are called even if one of the windowInfosListeners dies before
- // calling onWindowInfosReported.
- if (windowInfosReportedListener) {
- asBinder->linkToDeath(windowInfosReportedListener);
- }
-
- auto status = listener->onWindowInfosChanged(windowInfos, displayInfos,
- windowInfosReportedListener);
- if (windowInfosReportedListener && !status.isOk()) {
- windowInfosReportedListener->onWindowInfosReported();
- }
- }
+ callListeners(std::move(reportedListeners));
+ return binder::Status::ok();
}
} // namespace android
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h
index d60a9c4..4da9828 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.h
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.h
@@ -23,34 +23,42 @@
#include <android/gui/IWindowInfosReportedListener.h>
#include <binder/IBinder.h>
#include <ftl/small_map.h>
+#include <gui/SpHash.h>
#include <utils/Mutex.h>
namespace android {
-class SurfaceFlinger;
+using WindowInfosReportedListenerSet =
+ std::unordered_set<sp<gui::IWindowInfosReportedListener>,
+ gui::SpHash<gui::IWindowInfosReportedListener>>;
-class WindowInfosListenerInvoker : public IBinder::DeathRecipient {
+class WindowInfosListenerInvoker : public gui::BnWindowInfosReportedListener,
+ public IBinder::DeathRecipient {
public:
void addWindowInfosListener(sp<gui::IWindowInfosListener>);
void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);
- void windowInfosChanged(const std::vector<gui::WindowInfo>&,
- const std::vector<gui::DisplayInfo>&,
- const std::unordered_set<sp<gui::IWindowInfosReportedListener>,
- SpHash<gui::IWindowInfosReportedListener>>&
- windowInfosReportedListeners);
+ void windowInfosChanged(std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>,
+ WindowInfosReportedListenerSet windowInfosReportedListeners,
+ bool forceImmediateCall);
+
+ binder::Status onWindowInfosReported() override;
protected:
void binderDied(const wp<IBinder>& who) override;
private:
- struct WindowInfosReportedListener;
-
std::mutex mListenersMutex;
static constexpr size_t kStaticCapacity = 3;
ftl::SmallMap<wp<IBinder>, const sp<gui::IWindowInfosListener>, kStaticCapacity>
mWindowInfosListeners GUARDED_BY(mListenersMutex);
+
+ std::mutex mMessagesMutex;
+ uint32_t mActiveMessageCount GUARDED_BY(mMessagesMutex) = 0;
+ std::function<void(WindowInfosReportedListenerSet)> mWindowInfosChangedDelayed
+ GUARDED_BY(mMessagesMutex);
+ WindowInfosReportedListenerSet mReportedListenersDelayed;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
index ddf3363..88d39db 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
@@ -662,10 +662,9 @@
mLifecycleManager.commitChanges();
LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers());
UPDATE_AND_VERIFY(hierarchyBuilder);
- std::vector<uint32_t> expectedTraversalPath = {1, 11, 2, 21};
+ std::vector<uint32_t> expectedTraversalPath = {2, 21, 1, 11};
EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
- expectedTraversalPath = {1, 11, 2, 21};
EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
expectedTraversalPath = {};
EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
@@ -678,8 +677,8 @@
setLayerStack(3, 1);
UPDATE_AND_VERIFY(hierarchyBuilder);
- std::vector<uint32_t> expected = {3, 1, 11, 111, 12, 121, 122, 1221, 13, 2,
- 1, 11, 111, 12, 121, 122, 1221, 13, 2};
+ std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 3,
+ 1, 11, 111, 12, 121, 122, 1221, 13, 2};
EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expected);
EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expected);
expected = {};
@@ -693,7 +692,7 @@
setLayerStack(3, 1);
UPDATE_AND_VERIFY(hierarchyBuilder);
- std::vector<uint32_t> expected = {3, 1, 11, 111, 12, 121, 122, 1221, 13, 2};
+ std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 3};
EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expected);
EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expected);
expected = {};
@@ -710,8 +709,8 @@
createRootLayer(4);
UPDATE_AND_VERIFY(hierarchyBuilder);
- std::vector<uint32_t> expected = {3, 1, 11, 111, 12, 121, 122, 1221, 13, 2, 4,
- 1, 11, 111, 12, 121, 122, 1221, 13, 2, 4};
+ std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 4, 3,
+ 1, 11, 111, 12, 121, 122, 1221, 13, 2, 4};
EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expected);
EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expected);
expected = {};
@@ -729,7 +728,7 @@
destroyLayerHandle(1);
UPDATE_AND_VERIFY(hierarchyBuilder);
- std::vector<uint32_t> expected = {3, 2, 2};
+ std::vector<uint32_t> expected = {2, 3, 2};
EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expected);
EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expected);
expected = {11, 111, 12, 121, 122, 1221, 13};
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
index 79cfd6a..4301186 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
@@ -297,6 +297,17 @@
mLifecycleManager.applyTransactions(transactions);
}
+ void setBackgroundBlurRadius(uint32_t id, uint32_t backgroundBlurRadius) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eBackgroundBlurRadiusChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.backgroundBlurRadius = backgroundBlurRadius;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
LayerLifecycleManager mLifecycleManager;
};
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index b767276..85d86a7 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -84,7 +84,7 @@
auto frequentLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS {
const auto& infos = history().mActiveLayerInfos;
return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) {
- return pair.second.second->isFrequent(now);
+ return pair.second.second->isFrequent(now).isFrequent;
});
}
@@ -95,6 +95,13 @@
});
}
+ auto clearLayerHistoryCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS {
+ const auto& infos = history().mActiveLayerInfos;
+ return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) {
+ return pair.second.second->isFrequent(now).clearHistory;
+ });
+ }
+
void setDefaultLayerVote(Layer* layer,
LayerHistory::LayerVoteType vote) NO_THREAD_SAFETY_ANALYSIS {
auto [found, layerPair] = history().findLayer(layer->getSequence());
@@ -764,6 +771,7 @@
time += std::chrono::nanoseconds(3s).count();
history().record(layer->getSequence(), layer->getLayerProps(), time, time,
LayerHistory::LayerUpdateType::Buffer);
+ EXPECT_EQ(0, clearLayerHistoryCount(time));
ASSERT_EQ(1, summarizeLayerHistory(time).size());
EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
@@ -778,6 +786,7 @@
time += (MAX_FREQUENT_LAYER_PERIOD_NS + 1ms).count();
history().record(layer->getSequence(), layer->getLayerProps(), time, time,
LayerHistory::LayerUpdateType::Buffer);
+ EXPECT_EQ(0, clearLayerHistoryCount(time));
ASSERT_EQ(1, summarizeLayerHistory(time).size());
EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
@@ -787,6 +796,7 @@
// posting another buffer should keep the layer infrequent
history().record(layer->getSequence(), layer->getLayerProps(), time, time,
LayerHistory::LayerUpdateType::Buffer);
+ EXPECT_EQ(0, clearLayerHistoryCount(time));
ASSERT_EQ(1, summarizeLayerHistory(time).size());
EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
@@ -798,6 +808,7 @@
LayerHistory::LayerUpdateType::Buffer);
history().record(layer->getSequence(), layer->getLayerProps(), time, time,
LayerHistory::LayerUpdateType::Buffer);
+ EXPECT_EQ(1, clearLayerHistoryCount(time));
ASSERT_EQ(1, summarizeLayerHistory(time).size());
EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
@@ -808,6 +819,7 @@
time += std::chrono::nanoseconds(3s).count();
history().record(layer->getSequence(), layer->getLayerProps(), time, time,
LayerHistory::LayerUpdateType::Buffer);
+ EXPECT_EQ(0, clearLayerHistoryCount(time));
ASSERT_EQ(1, summarizeLayerHistory(time).size());
EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
@@ -818,6 +830,64 @@
time += (60_Hz).getPeriodNsecs();
history().record(layer->getSequence(), layer->getLayerProps(), time, time,
LayerHistory::LayerUpdateType::Buffer);
+ EXPECT_EQ(0, clearLayerHistoryCount(time));
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(1, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+ EXPECT_EQ(0, animatingLayerCount(time));
+}
+
+TEST_F(LayerHistoryTest, inconclusiveLayerBecomingFrequent) {
+ auto layer = createLayer();
+
+ EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+
+ nsecs_t time = systemTime();
+
+ EXPECT_EQ(1, layerCount());
+ EXPECT_EQ(0, activeLayerCount());
+ EXPECT_EQ(0, frequentLayerCount(time));
+ EXPECT_EQ(0, animatingLayerCount(time));
+
+ // Fill up the window with frequent updates
+ for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE; i++) {
+ history().record(layer->getSequence(), layer->getLayerProps(), time, time,
+ LayerHistory::LayerUpdateType::Buffer);
+ time += (60_Hz).getPeriodNsecs();
+
+ EXPECT_EQ(1, layerCount());
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(1, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+ }
+
+ // posting infrequent buffers after long inactivity should make the layer
+ // inconclusive but frequent.
+ time += std::chrono::nanoseconds(3s).count();
+ history().record(layer->getSequence(), layer->getLayerProps(), time, time,
+ LayerHistory::LayerUpdateType::Buffer);
+ time += (MAX_FREQUENT_LAYER_PERIOD_NS + 1ms).count();
+ history().record(layer->getSequence(), layer->getLayerProps(), time, time,
+ LayerHistory::LayerUpdateType::Buffer);
+ EXPECT_EQ(0, clearLayerHistoryCount(time));
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(1, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+ EXPECT_EQ(0, animatingLayerCount(time));
+
+ // posting more buffers should make the layer frequent and switch the refresh rate to max
+ // by clearing the history
+ history().record(layer->getSequence(), layer->getLayerProps(), time, time,
+ LayerHistory::LayerUpdateType::Buffer);
+ history().record(layer->getSequence(), layer->getLayerProps(), time, time,
+ LayerHistory::LayerUpdateType::Buffer);
+ history().record(layer->getSequence(), layer->getLayerProps(), time, time,
+ LayerHistory::LayerUpdateType::Buffer);
+ EXPECT_EQ(1, clearLayerHistoryCount(time));
ASSERT_EQ(1, summarizeLayerHistory(time).size());
EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 5a066a6..b8a7446 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -79,6 +79,7 @@
.displays = mFrontEndDisplayInfos,
.displayChanges = hasDisplayChanges,
.globalShadowSettings = globalShadowSettings,
+ .supportsBlur = true,
.supportedLayerGenericMetadata = {},
.genericLayerMetadataKeyMap = {}};
actualBuilder.update(args);
@@ -333,6 +334,19 @@
EXPECT_EQ(getSnapshot({.id = 111})->inputInfo.touchableRegion.bounds(), modifiedTouchCrop);
}
+TEST_F(LayerSnapshotTest, blurUpdatesWhenAlphaChanges) {
+ static constexpr int blurRadius = 42;
+ setBackgroundBlurRadius(1221, blurRadius);
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_EQ(getSnapshot({.id = 1221})->backgroundBlurRadius, blurRadius);
+
+ static constexpr float alpha = 0.5;
+ setAlpha(12, alpha);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_EQ(getSnapshot({.id = 1221})->backgroundBlurRadius, blurRadius * alpha);
+}
+
// Display Mirroring Tests
// tree with 3 levels of children
// ROOT (DISPLAY 0)
@@ -352,7 +366,7 @@
createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
setLayerStack(3, 1);
- std::vector<uint32_t> expected = {3, 1, 11, 111, 13, 2, 1, 11, 111, 12, 121, 122, 1221, 13, 2};
+ std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 3, 1, 11, 111, 13, 2};
UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
}
@@ -371,8 +385,8 @@
createDisplayMirrorLayer(4, ui::LayerStack::fromValue(0));
setLayerStack(4, 4);
- std::vector<uint32_t> expected = {4, 1, 11, 111, 13, 2, 3, 1, 11,
- 111, 13, 2, 1, 11, 111, 13, 2};
+ std::vector<uint32_t> expected = {1, 11, 111, 13, 2, 3, 1, 11, 111,
+ 13, 2, 4, 1, 11, 111, 13, 2};
UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootId = 3})->outputFilter.layerStack.id, 3u);
EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootId = 4})->outputFilter.layerStack.id, 4u);
@@ -395,7 +409,7 @@
setCrop(111, Rect{200, 200});
Region touch{Rect{0, 0, 1000, 1000}};
setTouchableRegion(111, touch);
- std::vector<uint32_t> expected = {3, 1, 11, 111, 13, 2, 1, 11, 111, 13, 2};
+ std::vector<uint32_t> expected = {1, 11, 111, 13, 2, 3, 1, 11, 111, 13, 2};
UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
EXPECT_TRUE(getSnapshot({.id = 111})->inputInfo.touchableRegion.hasSameRects(touch));
Region touchCroppedByMirrorRoot{Rect{0, 0, 50, 50}};
@@ -407,7 +421,7 @@
setFlags(12, layer_state_t::eLayerSkipScreenshot, layer_state_t::eLayerSkipScreenshot);
createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
setLayerStack(3, 1);
- std::vector<uint32_t> expected = {3, 1, 11, 111, 13, 2, 1, 11, 111, 12, 121, 122, 1221, 13, 2};
+ std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 3, 1, 11, 111, 13, 2};
UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
destroyLayerHandle(3);
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
@@ -417,8 +431,8 @@
size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size();
createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
setLayerStack(3, 1);
- std::vector<uint32_t> expected = {3, 1, 11, 111, 12, 121, 122, 1221, 13, 2,
- 1, 11, 111, 12, 121, 122, 1221, 13, 2};
+ std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 3,
+ 1, 11, 111, 12, 121, 122, 1221, 13, 2};
UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
destroyLayerHandle(3);
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index dc76b4c..0c43831 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -384,4 +384,23 @@
}
}
+TEST_F(SchedulerTest, changingPacesetterChangesVsyncSchedule) {
+ // Add a second display so we can change the pacesetter.
+ mScheduler->registerDisplay(kDisplayId2,
+ std::make_shared<RefreshRateSelector>(kDisplay2Modes,
+ kDisplay2Mode60->getId()));
+ // Ensure that the pacesetter is the one we expect.
+ mScheduler->setPacesetterDisplay(kDisplayId1);
+
+ // Switching to the other will call onNewVsyncSchedule.
+ EXPECT_CALL(*mEventThread, onNewVsyncSchedule(mScheduler->getVsyncSchedule(kDisplayId2)))
+ .Times(1);
+ mScheduler->setPacesetterDisplay(kDisplayId2);
+}
+
+TEST_F(SchedulerTest, promotingSamePacesetterDoesNotChangeVsyncSchedule) {
+ EXPECT_CALL(*mEventThread, onNewVsyncSchedule(_)).Times(0);
+ mScheduler->setPacesetterDisplay(kDisplayId1);
+}
+
} // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
index 6a9c970..1cc9ba4 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
@@ -17,12 +17,60 @@
#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"
+#include <scheduler/Fps.h>
+
#include "DisplayTransactionTestHelpers.h"
+#include "FpsOps.h"
namespace android {
namespace {
-class CreateDisplayTest : public DisplayTransactionTest {};
+class CreateDisplayTest : public DisplayTransactionTest {
+public:
+ void createDisplayWithRequestedRefreshRate(const String8& name, uint64_t displayId,
+ float pacesetterDisplayRefreshRate,
+ float requestedRefreshRate,
+ float expectedAdjustedRefreshRate) {
+ // --------------------------------------------------------------------
+ // Call Expectations
+
+ // --------------------------------------------------------------------
+ // Invocation
+
+ sp<IBinder> displayToken = mFlinger.createDisplay(name, false, requestedRefreshRate);
+
+ // --------------------------------------------------------------------
+ // Postconditions
+
+ // The display should have been added to the current state
+ ASSERT_TRUE(hasCurrentDisplayState(displayToken));
+ const auto& display = getCurrentDisplayState(displayToken);
+ EXPECT_TRUE(display.isVirtual());
+ EXPECT_EQ(display.requestedRefreshRate, Fps::fromValue(requestedRefreshRate));
+ EXPECT_EQ(name.string(), display.displayName);
+
+ std::optional<VirtualDisplayId> vid =
+ DisplayId::fromValue<VirtualDisplayId>(displayId | DisplayId::FLAG_VIRTUAL);
+ ASSERT_TRUE(vid.has_value());
+
+ sp<DisplayDevice> device =
+ mFlinger.createVirtualDisplayDevice(displayToken, *vid, requestedRefreshRate);
+ EXPECT_TRUE(device->isVirtual());
+ device->adjustRefreshRate(Fps::fromValue(pacesetterDisplayRefreshRate));
+ // verifying desired value
+ EXPECT_EQ(device->getAdjustedRefreshRate(), Fps::fromValue(expectedAdjustedRefreshRate));
+ // verifying rounding up
+ if (requestedRefreshRate < pacesetterDisplayRefreshRate) {
+ EXPECT_GE(device->getAdjustedRefreshRate(), Fps::fromValue(requestedRefreshRate));
+ } else {
+ EXPECT_EQ(device->getAdjustedRefreshRate(),
+ Fps::fromValue(pacesetterDisplayRefreshRate));
+ }
+
+ // --------------------------------------------------------------------
+ // Cleanup conditions
+ }
+};
TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForNonsecureDisplay) {
const String8 name("virtual.test");
@@ -84,5 +132,82 @@
EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
}
+// Requesting 0 tells SF not to do anything, i.e., default to refresh as physical displays
+TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRate0) {
+ const String8 displayName("virtual.test");
+ const uint64_t displayId = 123ull;
+ const float kPacesetterDisplayRefreshRate = 60.f;
+ const float kRequestedRefreshRate = 0.f;
+ const float kExpectedAdjustedRefreshRate = 0.f;
+ createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+ kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
+}
+
+// Requesting negative refresh rate, will be ignored, same as requesting 0
+TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNegative) {
+ const String8 displayName("virtual.test");
+ const uint64_t displayId = 123ull;
+ const float kPacesetterDisplayRefreshRate = 60.f;
+ const float kRequestedRefreshRate = -60.f;
+ const float kExpectedAdjustedRefreshRate = 0.f;
+ createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+ kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
+}
+
+// Requesting a higher refresh rate than the pacesetter
+TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateHigh) {
+ const String8 displayName("virtual.test");
+ const uint64_t displayId = 123ull;
+ const float kPacesetterDisplayRefreshRate = 60.f;
+ const float kRequestedRefreshRate = 90.f;
+ const float kExpectedAdjustedRefreshRate = 60.f;
+ createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+ kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
+}
+
+// Requesting the same refresh rate as the pacesetter
+TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateSame) {
+ const String8 displayName("virtual.test");
+ const uint64_t displayId = 123ull;
+ const float kPacesetterDisplayRefreshRate = 60.f;
+ const float kRequestedRefreshRate = 60.f;
+ const float kExpectedAdjustedRefreshRate = 60.f;
+ createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+ kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
+}
+
+// Requesting a divisor (30) of the pacesetter (60) should be honored
+TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateDivisor) {
+ const String8 displayName("virtual.test");
+ const uint64_t displayId = 123ull;
+ const float kPacesetterDisplayRefreshRate = 60.f;
+ const float kRequestedRefreshRate = 30.f;
+ const float kExpectedAdjustedRefreshRate = 30.f;
+ createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+ kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
+}
+
+// Requesting a non divisor (45) of the pacesetter (120) should round up to a divisor (60)
+TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisor) {
+ const String8 displayName("virtual.test");
+ const uint64_t displayId = 123ull;
+ const float kPacesetterDisplayRefreshRate = 120.f;
+ const float kRequestedRefreshRate = 45.f;
+ const float kExpectedAdjustedRefreshRate = 60.f;
+ createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+ kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
+}
+
+// Requesting a non divisor (75) of the pacesetter (120) should round up to pacesetter (120)
+TEST_F(CreateDisplayTest, createDisplayWithRequestedRefreshRateNoneDivisorMax) {
+ const String8 displayName("virtual.test");
+ const uint64_t displayId = 123ull;
+ const float kPacesetterDisplayRefreshRate = 120.f;
+ const float kRequestedRefreshRate = 75.f;
+ const float kExpectedAdjustedRefreshRate = 120.f;
+ createDisplayWithRequestedRefreshRate(displayName, displayId, kPacesetterDisplayRefreshRate,
+ kRequestedRefreshRate, kExpectedAdjustedRefreshRate);
+}
+
} // namespace
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 6f48df8..cfa366f 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -48,10 +48,12 @@
#include "TestableScheduler.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockDisplayMode.h"
+#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockEventThread.h"
#include "mock/MockFrameTimeline.h"
#include "mock/MockFrameTracer.h"
#include "mock/MockSchedulerCallback.h"
+#include "mock/system/window/MockNativeWindow.h"
namespace android {
namespace renderengine {
@@ -375,8 +377,8 @@
void commitAndComposite() { mFlinger->composite(commit(), kVsyncId); }
- auto createDisplay(const String8& displayName, bool secure) {
- return mFlinger->createDisplay(displayName, secure);
+ auto createDisplay(const String8& displayName, bool secure, float requestedRefreshRate = 0.0f) {
+ return mFlinger->createDisplay(displayName, secure, requestedRefreshRate);
}
auto destroyDisplay(const sp<IBinder>& displayToken) {
@@ -525,6 +527,24 @@
mFlinger->getDynamicDisplayInfoFromToken(displayToken, dynamicDisplayInfo);
}
+ sp<DisplayDevice> createVirtualDisplayDevice(const sp<IBinder> displayToken,
+ VirtualDisplayId displayId,
+ float requestedRefreshRate) {
+ constexpr ui::Size kResolution = {1080, 1920};
+ auto compositionDisplay = compositionengine::impl::
+ createDisplay(mFlinger->getCompositionEngine(),
+ compositionengine::DisplayCreationArgsBuilder()
+ .setId(displayId)
+ .setPixels(kResolution)
+ .setPowerAdvisor(&mPowerAdvisor)
+ .build());
+ DisplayDeviceCreationArgs creationArgs(mFlinger, mFlinger->getHwComposer(), displayToken,
+ compositionDisplay);
+ creationArgs.requestedRefreshRate = Fps::fromValue(requestedRefreshRate);
+ creationArgs.nativeWindow = sp<mock::NativeWindow>::make();
+ return sp<DisplayDevice>::make(creationArgs);
+ }
+
/* ------------------------------------------------------------------------
* Read-only access to private data to assert post-conditions.
*/
@@ -962,6 +982,7 @@
scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback;
std::unique_ptr<frametimeline::impl::TokenManager> mTokenManager;
scheduler::TestableScheduler* mScheduler = nullptr;
+ Hwc2::mock::PowerAdvisor mPowerAdvisor;
};
} // namespace android
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index dec3b20..922a44f 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -252,27 +252,31 @@
Swapchain(Surface& surface_,
uint32_t num_images_,
VkPresentModeKHR present_mode,
- int pre_transform_)
+ int pre_transform_,
+ int64_t refresh_duration_)
: surface(surface_),
num_images(num_images_),
mailbox_mode(present_mode == VK_PRESENT_MODE_MAILBOX_KHR),
pre_transform(pre_transform_),
frame_timestamps_enabled(false),
+ refresh_duration(refresh_duration_),
acquire_next_image_timeout(-1),
shared(IsSharedPresentMode(present_mode)) {
- ANativeWindow* window = surface.window.get();
- native_window_get_refresh_cycle_duration(
- window,
- &refresh_duration);
}
- uint64_t get_refresh_duration()
+
+ VkResult get_refresh_duration(uint64_t& outRefreshDuration)
{
ANativeWindow* window = surface.window.get();
- native_window_get_refresh_cycle_duration(
+ int err = native_window_get_refresh_cycle_duration(
window,
&refresh_duration);
- return static_cast<uint64_t>(refresh_duration);
-
+ if (err != android::OK) {
+ ALOGE("%s:native_window_get_refresh_cycle_duration failed: %s (%d)",
+ __func__, strerror(-err), err );
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+ outRefreshDuration = refresh_duration;
+ return VK_SUCCESS;
}
Surface& surface;
@@ -1626,6 +1630,13 @@
return VK_ERROR_SURFACE_LOST_KHR;
}
+ int64_t refresh_duration;
+ err = native_window_get_refresh_cycle_duration(window, &refresh_duration);
+ if (err != android::OK) {
+ ALOGE("native_window_get_refresh_cycle_duration query failed: %s (%d)",
+ strerror(-err), err);
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
// -- Allocate our Swapchain object --
// After this point, we must deallocate the swapchain on error.
@@ -1636,8 +1647,8 @@
return VK_ERROR_OUT_OF_HOST_MEMORY;
Swapchain* swapchain = new (mem)
Swapchain(surface, num_images, create_info->presentMode,
- TranslateVulkanToNativeTransform(create_info->preTransform));
-
+ TranslateVulkanToNativeTransform(create_info->preTransform),
+ refresh_duration);
VkSwapchainImageCreateInfoANDROID swapchain_image_create = {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast"
@@ -2308,9 +2319,7 @@
ATRACE_CALL();
Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
- VkResult result = VK_SUCCESS;
-
- pDisplayTimingProperties->refreshDuration = swapchain.get_refresh_duration();
+ VkResult result = swapchain.get_refresh_duration(pDisplayTimingProperties->refreshDuration);
return result;
}