Merge "Remove sourceClip from OutputCompositionState"
diff --git a/include/input/Flags.h b/include/input/Flags.h
index f43829f..4ad9056 100644
--- a/include/input/Flags.h
+++ b/include/input/Flags.h
@@ -68,10 +68,10 @@
template <typename F, typename T, T... I>
constexpr auto generate_flag_values(std::integer_sequence<T, I...> seq) {
- constexpr int count = seq.size();
+ constexpr size_t count = seq.size();
std::array<F, count> values{};
- for (int i = 0, v = 0; v < count; ++i) {
+ for (size_t i = 0, v = 0; v < count; ++i) {
values[v++] = static_cast<F>(T{1} << i);
}
diff --git a/include/input/Input.h b/include/input/Input.h
index 9525bcb..d40ba43 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -527,13 +527,11 @@
inline void setActionButton(int32_t button) { mActionButton = button; }
- inline float getXScale() const { return mXScale; }
+ inline float getXOffset() const { return mTransform.tx(); }
- inline float getYScale() const { return mYScale; }
+ inline float getYOffset() const { return mTransform.ty(); }
- inline float getXOffset() const { return mXOffset; }
-
- inline float getYOffset() const { return mYOffset; }
+ inline ui::Transform getTransform() const { return mTransform; }
inline float getXPrecision() const { return mXPrecision; }
@@ -695,8 +693,8 @@
void initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton,
int32_t flags, int32_t edgeFlags, int32_t metaState, int32_t buttonState,
- MotionClassification classification, float xScale, float yScale, float xOffset,
- float yOffset, float xPrecision, float yPrecision, float rawXCursorPosition,
+ MotionClassification classification, const ui::Transform& transform,
+ float xPrecision, float yPrecision, float rawXCursorPosition,
float rawYCursorPosition, nsecs_t downTime, nsecs_t eventTime,
size_t pointerCount, const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords);
@@ -713,7 +711,7 @@
// Apply 3x3 perspective matrix transformation.
// Matrix is in row-major form and compatible with SkMatrix.
- void transform(const float matrix[9]);
+ void transform(const std::array<float, 9>& matrix);
#ifdef __ANDROID__
status_t readFromParcel(Parcel* parcel);
@@ -747,10 +745,6 @@
int32_t mMetaState;
int32_t mButtonState;
MotionClassification mClassification;
- float mXScale;
- float mYScale;
- float mXOffset;
- float mYOffset;
ui::Transform mTransform;
float mXPrecision;
float mYPrecision;
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 24f8e77..8e00969 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -37,6 +37,7 @@
#include <binder/Parcelable.h>
#include <input/Input.h>
#include <sys/stat.h>
+#include <ui/Transform.h>
#include <utils/BitSet.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -115,10 +116,12 @@
uint8_t empty2[3]; // 3 bytes to fill gap created by classification
int32_t edgeFlags;
nsecs_t downTime __attribute__((aligned(8)));
- float xScale;
- float yScale;
- float xOffset;
- float yOffset;
+ float dsdx;
+ float dtdx;
+ float dtdy;
+ float dsdy;
+ float tx;
+ float ty;
float xPrecision;
float yPrecision;
float xCursorPosition;
@@ -319,11 +322,10 @@
int32_t displayId, std::array<uint8_t, 32> hmac, int32_t action,
int32_t actionButton, int32_t flags, int32_t edgeFlags,
int32_t metaState, int32_t buttonState,
- MotionClassification classification, float xScale, float yScale,
- float xOffset, float yOffset, float xPrecision, float yPrecision,
- float xCursorPosition, float yCursorPosition, nsecs_t downTime,
- nsecs_t eventTime, uint32_t pointerCount,
- const PointerProperties* pointerProperties,
+ MotionClassification classification, const ui::Transform& transform,
+ float xPrecision, float yPrecision, float xCursorPosition,
+ float yCursorPosition, nsecs_t downTime, nsecs_t eventTime,
+ uint32_t pointerCount, const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords);
/* Publishes a focus event to the input channel.
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index d67ce15..157538e 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -614,7 +614,7 @@
talkWithDriver(false);
}
-int IPCThreadState::setupPolling(int* fd)
+status_t IPCThreadState::setupPolling(int* fd)
{
if (mProcess->mDriverFD < 0) {
return -EBADF;
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 25c0b19..9aa82d9 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -18,6 +18,9 @@
#include <binder/IServiceManager.h>
+#include <inttypes.h>
+#include <unistd.h>
+
#include <android/os/BnServiceCallback.h>
#include <android/os/IServiceManager.h>
#include <binder/IPCThreadState.h>
@@ -36,8 +39,6 @@
#include "Static.h"
-#include <unistd.h>
-
namespace android {
using AidlServiceManager = android::os::IServiceManager;
@@ -219,7 +220,8 @@
const bool isVendorService =
strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
- const long timeout = uptimeMillis() + 5000;
+ const long timeout = 5000;
+ int64_t startTime = uptimeMillis();
// Vendor code can't access system properties
if (!gSystemBootCompleted && !isVendorService) {
#ifdef __ANDROID__
@@ -233,15 +235,21 @@
// retry interval in millisecond; note that vendor services stay at 100ms
const long sleepTime = gSystemBootCompleted ? 1000 : 100;
+ ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
+ ProcessState::self()->getDriverName().c_str());
+
int n = 0;
- while (uptimeMillis() < timeout) {
+ while (uptimeMillis() - startTime < timeout) {
n++;
- ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
- ProcessState::self()->getDriverName().c_str());
usleep(1000*sleepTime);
sp<IBinder> svc = checkService(name);
- if (svc != nullptr) return svc;
+ if (svc != nullptr) {
+ ALOGI("Waiting for service '%s' on '%s' successful after waiting %" PRIi64 "ms",
+ String8(name).string(), ProcessState::self()->getDriverName().c_str(),
+ uptimeMillis() - startTime);
+ return svc;
+ }
}
ALOGW("Service %s didn't start. Returning NULL", String8(name).string());
return nullptr;
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 8d51cdc..2bd39a7 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -85,8 +85,8 @@
int64_t clearCallingIdentity();
// Restores PID/UID (not SID)
void restoreCallingIdentity(int64_t token);
-
- int setupPolling(int* fd);
+
+ status_t setupPolling(int* fd);
status_t handlePolledCommands();
void flushCommands();
diff --git a/libs/binder/include/binder/Parcelable.h b/libs/binder/include/binder/Parcelable.h
index c113279..83c2f19 100644
--- a/libs/binder/include/binder/Parcelable.h
+++ b/libs/binder/include/binder/Parcelable.h
@@ -53,11 +53,20 @@
// Returns android::OK on success and an appropriate error otherwise.
virtual status_t readFromParcel(const Parcel* parcel) = 0;
- // 'Stable' means this parcelable is guaranteed to be stable for multiple years.
+ // WARNING: for use by auto-generated code only (AIDL). Should not be used
+ // manually, or there is a risk of breaking CTS, GTS, VTS, or CTS-on-GSI
+ // tests.
+ enum class Stability {
+ STABILITY_LOCAL,
+ STABILITY_VINTF, // corresponds to @VintfStability
+ };
+
+ // 'Stable' means this parcelable is guaranteed to be stable for multiple
+ // years.
// It must be guaranteed by setting stability field in aidl_interface.
- // WARNING: isStable() is only expected to be overridden by auto-generated code.
- // Returns true if this parcelable is stable.
- virtual bool isStable() const { return false; }
+ // WARNING: getStability() is only expected to be overridden by auto-generated
+ // code. Returns true if this parcelable is stable.
+ virtual Stability getStability() const { return Stability::STABILITY_LOCAL; }
}; // class Parcelable
#if defined(__clang__)
diff --git a/libs/binder/ndk/include_platform/android/binder_process.h b/libs/binder/ndk/include_platform/android/binder_process.h
index fdefbb4..f408fad 100644
--- a/libs/binder/ndk/include_platform/android/binder_process.h
+++ b/libs/binder/ndk/include_platform/android/binder_process.h
@@ -19,10 +19,15 @@
#include <stdint.h>
#include <sys/cdefs.h>
+#include <android/binder_status.h>
+
__BEGIN_DECLS
/**
* This creates a threadpool for incoming binder transactions if it has not already been created.
+ *
+ * When using this, it is expected that ABinderProcess_setupPolling and
+ * ABinderProcess_handlePolledCommands are not used.
*/
void ABinderProcess_startThreadPool();
/**
@@ -37,4 +42,27 @@
*/
void ABinderProcess_joinThreadPool();
+/**
+ * This gives you an fd to wait on. Whenever data is available on the fd,
+ * ABinderProcess_handlePolledCommands can be called to handle binder queries.
+ * This is expected to be used in a single threaded process which waits on
+ * events from multiple different fds.
+ *
+ * When using this, it is expected ABinderProcess_startThreadPool and
+ * ABinderProcess_joinThreadPool are not used.
+ *
+ * \param fd out param corresponding to the binder domain opened in this
+ * process.
+ * \return STATUS_OK on success
+ */
+__attribute__((weak)) binder_status_t ABinderProcess_setupPolling(int* fd) __INTRODUCED_IN(31);
+
+/**
+ * This will handle all queued binder commands in this process and then return.
+ * It is expected to be called whenever there is data on the fd.
+ *
+ * \return STATUS_OK on success
+ */
+__attribute__((weak)) binder_status_t ABinderProcess_handlePolledCommands() __INTRODUCED_IN(31);
+
__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 9b5fa26..d435382 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -113,6 +113,8 @@
LIBBINDER_NDK31 { # introduced=31
global:
+ ABinderProcess_handlePolledCommands; # apex
+ ABinderProcess_setupPolling; # apex
AIBinder_getCallingSid; # apex
AIBinder_setRequestingSid; # apex
};
diff --git a/libs/binder/ndk/process.cpp b/libs/binder/ndk/process.cpp
index c89caaf..ac582a4 100644
--- a/libs/binder/ndk/process.cpp
+++ b/libs/binder/ndk/process.cpp
@@ -34,3 +34,11 @@
void ABinderProcess_joinThreadPool() {
IPCThreadState::self()->joinThreadPool();
}
+
+binder_status_t ABinderProcess_setupPolling(int* fd) {
+ return IPCThreadState::self()->setupPolling(fd);
+}
+
+binder_status_t ABinderProcess_handlePolledCommands() {
+ return IPCThreadState::self()->handlePolledCommands();
+}
diff --git a/libs/binder/ndk/tests/Android.bp b/libs/binder/ndk/tests/Android.bp
index 5f5265c..7c271f6 100644
--- a/libs/binder/ndk/tests/Android.bp
+++ b/libs/binder/ndk/tests/Android.bp
@@ -40,6 +40,7 @@
cc_defaults {
name: "test_libbinder_ndk_test_defaults",
defaults: ["test_libbinder_ndk_defaults"],
+ // critical that libbinder/libbinder_ndk are shared for VTS
shared_libs: [
"libandroid_runtime_lazy",
"libbase",
@@ -63,7 +64,7 @@
"IBinderNdkUnitTest-cpp",
"IBinderNdkUnitTest-ndk_platform",
],
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "vts"],
require_root: true,
// force since binderVendorDoubleLoadTest has its own
@@ -81,13 +82,14 @@
"IBinderVendorDoubleLoadTest-ndk_platform",
"libbinder_aidl_test_stub-ndk_platform",
],
+ // critical that libbinder/libbinder_ndk are shared for VTS
shared_libs: [
"libbase",
"libbinder",
"libbinder_ndk",
"libutils",
],
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "vts"],
}
aidl_interface {
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index e3fdb4b..9b2fcf0 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -24,6 +24,7 @@
#include <android/binder_process.h>
#include <gtest/gtest.h>
#include <iface/iface.h>
+#include <utils/Looper.h>
// warning: this is assuming that libbinder_ndk is using the same copy
// of libbinder that we are.
@@ -107,19 +108,39 @@
}
};
-int manualService(const char* instance) {
- ABinderProcess_setThreadPoolMaxThreadCount(0);
-
+void manualService(const char* instance) {
// Strong reference to MyFoo kept by service manager.
binder_status_t status = (new MyFoo)->addService(instance);
if (status != STATUS_OK) {
LOG(FATAL) << "Could not register: " << status << " " << instance;
}
+}
+int manualPollingService(const char* instance) {
+ int fd;
+ CHECK(STATUS_OK == ABinderProcess_setupPolling(&fd));
+ manualService(instance);
+ class Handler : public LooperCallback {
+ int handleEvent(int /*fd*/, int /*events*/, void* /*data*/) override {
+ ABinderProcess_handlePolledCommands();
+ return 1; // Continue receiving callbacks.
+ }
+ };
+
+ sp<Looper> looper = Looper::prepare(0 /* opts */);
+ looper->addFd(fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, new Handler(), nullptr /*data*/);
+ // normally, would add additional fds
+ while (true) {
+ looper->pollAll(-1 /* timeoutMillis */);
+ }
+ return 1; // should not reach
+}
+int manualThreadPoolService(const char* instance) {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ manualService(instance);
ABinderProcess_joinThreadPool();
-
- return 1; // should not return
+ return 1;
}
// This is too slow
@@ -448,11 +469,11 @@
if (fork() == 0) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
- return manualService(IFoo::kInstanceNameToDieFor);
+ return manualThreadPoolService(IFoo::kInstanceNameToDieFor);
}
if (fork() == 0) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
- return manualService(IFoo::kSomeInstanceName);
+ return manualPollingService(IFoo::kSomeInstanceName);
}
if (fork() == 0) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 2680e84..a03835b 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -155,6 +155,7 @@
"binderStabilityTest.cpp",
],
+ // critical that libbinder/libbinder_ndk are shared for VTS
shared_libs: [
"libbinder_ndk",
"libbinder",
@@ -166,7 +167,7 @@
"binderStabilityTestIface-ndk_platform",
],
- test_suites: ["device-tests"],
+ test_suites: ["device-tests", "vts"],
require_root: true,
}
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 4a4510e..686e274 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -92,6 +92,7 @@
export_shared_lib_headers: [
"libbinder",
+ "libinput",
],
// bufferhub is not used when building libgui for vendors
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 1030b82..117ce58 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -448,19 +448,36 @@
// ------------------------------- InputWindowCommands ----------------------------------------
-void InputWindowCommands::merge(const InputWindowCommands& other) {
+bool InputWindowCommands::merge(const InputWindowCommands& other) {
+ bool changes = false;
+#ifndef NO_INPUT
+ changes |= !other.focusRequests.empty();
+ focusRequests.insert(focusRequests.end(), std::make_move_iterator(other.focusRequests.begin()),
+ std::make_move_iterator(other.focusRequests.end()));
+#endif
+ changes |= other.syncInputWindows && !syncInputWindows;
syncInputWindows |= other.syncInputWindows;
+ return changes;
}
void InputWindowCommands::clear() {
+#ifndef NO_INPUT
+ focusRequests.clear();
+#endif
syncInputWindows = false;
}
void InputWindowCommands::write(Parcel& output) const {
+#ifndef NO_INPUT
+ output.writeParcelableVector(focusRequests);
+#endif
output.writeBool(syncInputWindows);
}
void InputWindowCommands::read(const Parcel& input) {
+#ifndef NO_INPUT
+ input.readParcelableVector(&focusRequests);
+#endif
syncInputWindows = input.readBool();
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index d797a35..229a5c2 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1364,6 +1364,21 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFocusedWindow(
+ const sp<IBinder>& token, const sp<IBinder>& focusedToken, nsecs_t timestampNanos) {
+ FocusRequest request;
+ request.token = token;
+ request.focusedToken = focusedToken;
+ request.timestamp = timestampNanos;
+ return setFocusedWindow(request);
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFocusedWindow(
+ const FocusRequest& request) {
+ mInputWindowCommands.focusRequests.push_back(request);
+ return *this;
+}
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::syncInputWindows() {
mInputWindowCommands.syncInputWindows = true;
return *this;
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 00ae220..41aad0d 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -26,6 +26,7 @@
#include <math/mat4.h>
#ifndef NO_INPUT
+#include <android/FocusRequest.h>
#include <input/InputWindow.h>
#endif
@@ -283,9 +284,13 @@
};
struct InputWindowCommands {
+#ifndef NO_INPUT
+ std::vector<FocusRequest> focusRequests;
+#endif
bool syncInputWindows{false};
- void merge(const InputWindowCommands& other);
+ // Merges the passed in commands and returns true if there were any changes.
+ bool merge(const InputWindowCommands& other);
void clear();
void write(Parcel& output) const;
void read(const Parcel& input);
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index eb757ba..d5ca0f6 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -507,6 +507,9 @@
#ifndef NO_INPUT
Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
+ Transaction& setFocusedWindow(const sp<IBinder>& token, const sp<IBinder>& focusedToken,
+ nsecs_t timestampNanos);
+ Transaction& setFocusedWindow(const FocusRequest& request);
Transaction& syncInputWindows();
#endif
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 8a9f261..7dd5276 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -60,6 +60,7 @@
"LatencyStatistics.cpp",
"VelocityControl.cpp",
"VelocityTracker.cpp",
+ "android/FocusRequest.aidl",
"android/os/IInputFlinger.aidl",
"android/os/ISetInputWindowsListener.aidl",
],
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 2ac079e..fc73de3 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -325,10 +325,10 @@
void MotionEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton,
int32_t flags, int32_t edgeFlags, int32_t metaState,
- int32_t buttonState, MotionClassification classification, float xScale,
- float yScale, float xOffset, float yOffset, float xPrecision,
- float yPrecision, float rawXCursorPosition, float rawYCursorPosition,
- nsecs_t downTime, nsecs_t eventTime, size_t pointerCount,
+ int32_t buttonState, MotionClassification classification,
+ const ui::Transform& transform, float xPrecision, float yPrecision,
+ float rawXCursorPosition, float rawYCursorPosition, nsecs_t downTime,
+ nsecs_t eventTime, size_t pointerCount,
const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords) {
InputEvent::initialize(id, deviceId, source, displayId, hmac);
@@ -339,10 +339,7 @@
mMetaState = metaState;
mButtonState = buttonState;
mClassification = classification;
- mXScale = xScale;
- mYScale = yScale;
- mXOffset = xOffset;
- mYOffset = yOffset;
+ mTransform = transform;
mXPrecision = xPrecision;
mYPrecision = yPrecision;
mRawXCursorPosition = rawXCursorPosition;
@@ -365,10 +362,7 @@
mMetaState = other->mMetaState;
mButtonState = other->mButtonState;
mClassification = other->mClassification;
- mXScale = other->mXScale;
- mYScale = other->mYScale;
- mXOffset = other->mXOffset;
- mYOffset = other->mYOffset;
+ mTransform = other->mTransform;
mXPrecision = other->mXPrecision;
mYPrecision = other->mYPrecision;
mRawXCursorPosition = other->mRawXCursorPosition;
@@ -398,18 +392,20 @@
}
float MotionEvent::getXCursorPosition() const {
- const float rawX = getRawXCursorPosition();
- return rawX * mXScale + mXOffset;
+ vec2 vals = mTransform.transform(getRawXCursorPosition(), getRawYCursorPosition());
+ return vals.x;
}
float MotionEvent::getYCursorPosition() const {
- const float rawY = getRawYCursorPosition();
- return rawY * mYScale + mYOffset;
+ vec2 vals = mTransform.transform(getRawXCursorPosition(), getRawYCursorPosition());
+ return vals.y;
}
void MotionEvent::setCursorPosition(float x, float y) {
- mRawXCursorPosition = (x - mXOffset) / mXScale;
- mRawYCursorPosition = (y - mYOffset) / mYScale;
+ ui::Transform inverse = mTransform.inverse();
+ vec2 vals = inverse.transform(x, y);
+ mRawXCursorPosition = vals.x;
+ mRawYCursorPosition = vals.y;
}
const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
@@ -421,14 +417,7 @@
}
float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
- float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
- switch (axis) {
- case AMOTION_EVENT_AXIS_X:
- return value * mXScale + mXOffset;
- case AMOTION_EVENT_AXIS_Y:
- return value * mYScale + mYOffset;
- }
- return value;
+ return getHistoricalAxisValue(axis, pointerIndex, getHistorySize());
}
const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
@@ -443,14 +432,23 @@
float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
size_t historicalIndex) const {
- float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
+ if (axis != AMOTION_EVENT_AXIS_X && axis != AMOTION_EVENT_AXIS_Y) {
+ return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
+ }
+
+ float rawX = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getX();
+ float rawY = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getY();
+ vec2 vals = mTransform.transform(rawX, rawY);
+
switch (axis) {
case AMOTION_EVENT_AXIS_X:
- return value * mXScale + mXOffset;
+ return vals.x;
case AMOTION_EVENT_AXIS_Y:
- return value * mYScale + mYOffset;
+ return vals.y;
}
- return value;
+
+ // This should never happen
+ return 0;
}
ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
@@ -464,23 +462,24 @@
}
void MotionEvent::offsetLocation(float xOffset, float yOffset) {
- mXOffset += xOffset;
- mYOffset += yOffset;
+ float currXOffset = mTransform.tx();
+ float currYOffset = mTransform.ty();
+ mTransform.set(currXOffset + xOffset, currYOffset + yOffset);
}
void MotionEvent::scale(float globalScaleFactor) {
- mXOffset *= globalScaleFactor;
- mYOffset *= globalScaleFactor;
+ mTransform.set(mTransform.tx() * globalScaleFactor, mTransform.ty() * globalScaleFactor);
mXPrecision *= globalScaleFactor;
mYPrecision *= globalScaleFactor;
size_t numSamples = mSamplePointerCoords.size();
for (size_t i = 0; i < numSamples; i++) {
- mSamplePointerCoords.editItemAt(i).scale(globalScaleFactor);
+ mSamplePointerCoords.editItemAt(i).scale(globalScaleFactor, globalScaleFactor,
+ globalScaleFactor);
}
}
-static void transformPoint(const float matrix[9], float x, float y, float *outX, float *outY) {
+static vec2 transformPoint(const std::array<float, 9>& matrix, float x, float y) {
// Apply perspective transform like Skia.
float newX = matrix[0] * x + matrix[1] * y + matrix[2];
float newY = matrix[3] * x + matrix[4] * y + matrix[5];
@@ -488,22 +487,25 @@
if (newZ) {
newZ = 1.0f / newZ;
}
- *outX = newX * newZ;
- *outY = newY * newZ;
+ vec2 transformedPoint;
+ transformedPoint.x = newX * newZ;
+ transformedPoint.y = newY * newZ;
+ return transformedPoint;
}
-static float transformAngle(const float matrix[9], float angleRadians,
- float originX, float originY) {
+static float transformAngle(const std::array<float, 9>& matrix, float angleRadians, float originX,
+ float originY) {
// Construct and transform a vector oriented at the specified clockwise angle from vertical.
// Coordinate system: down is increasing Y, right is increasing X.
float x = sinf(angleRadians);
float y = -cosf(angleRadians);
- transformPoint(matrix, x, y, &x, &y);
- x -= originX;
- y -= originY;
+ vec2 transformedPoint = transformPoint(matrix, x, y);
+
+ transformedPoint.x -= originX;
+ transformedPoint.y -= originY;
// Derive the transformed vector's clockwise angle from vertical.
- float result = atan2f(x, -y);
+ float result = atan2f(transformedPoint.x, -transformedPoint.y);
if (result < - M_PI_2) {
result += M_PI;
} else if (result > M_PI_2) {
@@ -512,51 +514,51 @@
return result;
}
-void MotionEvent::transform(const float matrix[9]) {
- // The tricky part of this implementation is to preserve the value of
- // rawX and rawY. So we apply the transformation to the first point
- // then derive an appropriate new X/Y offset that will preserve rawX
- // and rawY for that point.
- float oldXOffset = mXOffset;
- float oldYOffset = mYOffset;
- float newX, newY;
- float scaledRawX = getRawX(0) * mXScale;
- float scaledRawY = getRawY(0) * mYScale;
- transformPoint(matrix, scaledRawX + oldXOffset, scaledRawY + oldYOffset, &newX, &newY);
- mXOffset = newX - scaledRawX;
- mYOffset = newY - scaledRawY;
+void MotionEvent::transform(const std::array<float, 9>& matrix) {
+ // We want to preserve the rawX and rawY so we just update the transform
+ // using the values of the transform passed in
+ ui::Transform newTransform;
+ newTransform.set(matrix);
+ mTransform = newTransform * mTransform;
// Determine how the origin is transformed by the matrix so that we
// can transform orientation vectors.
- float originX, originY;
- transformPoint(matrix, 0, 0, &originX, &originY);
-
- // Apply the transformation to cursor position.
- if (isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition)) {
- float x = mRawXCursorPosition * mXScale + oldXOffset;
- float y = mRawYCursorPosition * mYScale + oldYOffset;
- transformPoint(matrix, x, y, &x, &y);
- mRawXCursorPosition = (x - mXOffset) / mXScale;
- mRawYCursorPosition = (y - mYOffset) / mYScale;
- }
+ vec2 origin = transformPoint(matrix, 0, 0);
// Apply the transformation to all samples.
size_t numSamples = mSamplePointerCoords.size();
for (size_t i = 0; i < numSamples; i++) {
PointerCoords& c = mSamplePointerCoords.editItemAt(i);
- float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) * mXScale + oldXOffset;
- float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) * mYScale + oldYOffset;
- transformPoint(matrix, x, y, &x, &y);
- c.setAxisValue(AMOTION_EVENT_AXIS_X, (x - mXOffset) / mXScale);
- c.setAxisValue(AMOTION_EVENT_AXIS_Y, (y - mYOffset) / mYScale);
-
float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
- transformAngle(matrix, orientation, originX, originY));
+ transformAngle(matrix, orientation, origin.x, origin.y));
}
}
#ifdef __ANDROID__
+static status_t readFromParcel(ui::Transform& transform, const Parcel& parcel) {
+ float dsdx, dtdx, tx, dtdy, dsdy, ty;
+ status_t status = parcel.readFloat(&dsdx);
+ status |= parcel.readFloat(&dtdx);
+ status |= parcel.readFloat(&tx);
+ status |= parcel.readFloat(&dtdy);
+ status |= parcel.readFloat(&dsdy);
+ status |= parcel.readFloat(&ty);
+
+ transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
+ return status;
+}
+
+static status_t writeToParcel(const ui::Transform& transform, Parcel& parcel) {
+ status_t status = parcel.writeFloat(transform.dsdx());
+ status |= parcel.writeFloat(transform.dtdx());
+ status |= parcel.writeFloat(transform.tx());
+ status |= parcel.writeFloat(transform.dtdy());
+ status |= parcel.writeFloat(transform.dsdy());
+ status |= parcel.writeFloat(transform.ty());
+ return status;
+}
+
status_t MotionEvent::readFromParcel(Parcel* parcel) {
size_t pointerCount = parcel->readInt32();
size_t sampleCount = parcel->readInt32();
@@ -582,10 +584,11 @@
mMetaState = parcel->readInt32();
mButtonState = parcel->readInt32();
mClassification = static_cast<MotionClassification>(parcel->readByte());
- mXScale = parcel->readFloat();
- mYScale = parcel->readFloat();
- mXOffset = parcel->readFloat();
- mYOffset = parcel->readFloat();
+
+ result = android::readFromParcel(mTransform, *parcel);
+ if (result != OK) {
+ return result;
+ }
mXPrecision = parcel->readFloat();
mYPrecision = parcel->readFloat();
mRawXCursorPosition = parcel->readFloat();
@@ -640,10 +643,11 @@
parcel->writeInt32(mMetaState);
parcel->writeInt32(mButtonState);
parcel->writeByte(static_cast<int8_t>(mClassification));
- parcel->writeFloat(mXScale);
- parcel->writeFloat(mYScale);
- parcel->writeFloat(mXOffset);
- parcel->writeFloat(mYOffset);
+
+ status_t result = android::writeToParcel(mTransform, *parcel);
+ if (result != OK) {
+ return result;
+ }
parcel->writeFloat(mXPrecision);
parcel->writeFloat(mYPrecision);
parcel->writeFloat(mRawXCursorPosition);
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 8dcc415..b088ee7 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -195,14 +195,14 @@
msg->body.motion.edgeFlags = body.motion.edgeFlags;
// nsecs_t downTime
msg->body.motion.downTime = body.motion.downTime;
- // float xScale
- msg->body.motion.xScale = body.motion.xScale;
- // float yScale
- msg->body.motion.yScale = body.motion.yScale;
- // float xOffset
- msg->body.motion.xOffset = body.motion.xOffset;
- // float yOffset
- msg->body.motion.yOffset = body.motion.yOffset;
+
+ msg->body.motion.dsdx = body.motion.dsdx;
+ msg->body.motion.dtdx = body.motion.dtdx;
+ msg->body.motion.dtdy = body.motion.dtdy;
+ msg->body.motion.dsdy = body.motion.dsdy;
+ msg->body.motion.tx = body.motion.tx;
+ msg->body.motion.ty = body.motion.ty;
+
// float xPrecision
msg->body.motion.xPrecision = body.motion.xPrecision;
// float yPrecision
@@ -469,10 +469,10 @@
uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton, int32_t flags,
int32_t edgeFlags, int32_t metaState, int32_t buttonState,
- MotionClassification classification, float xScale, float yScale, float xOffset,
- float yOffset, float xPrecision, float yPrecision, float xCursorPosition,
- float yCursorPosition, nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) {
+ MotionClassification classification, const ui::Transform& transform, float xPrecision,
+ float yPrecision, float xCursorPosition, float yCursorPosition, nsecs_t downTime,
+ nsecs_t eventTime, uint32_t pointerCount, const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords) {
if (ATRACE_ENABLED()) {
std::string message = StringPrintf(
"publishMotionEvent(inputChannel=%s, action=%" PRId32 ")",
@@ -480,17 +480,18 @@
ATRACE_NAME(message.c_str());
}
if (DEBUG_TRANSPORT_ACTIONS) {
+ std::string transformString;
+ transform.dump(transformString, "");
ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
"displayId=%" PRId32 ", "
"action=0x%x, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, "
- "metaState=0x%x, buttonState=0x%x, classification=%s, xScale=%.1f, yScale=%.1f, "
- "xOffset=%.1f, yOffset=%.1f, "
+ "metaState=0x%x, buttonState=0x%x, classification=%s,"
"xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", "
- "pointerCount=%" PRIu32,
+ "pointerCount=%" PRIu32 " transform=%s",
mChannel->getName().c_str(), seq, deviceId, source, displayId, action, actionButton,
flags, edgeFlags, metaState, buttonState,
- motionClassificationToString(classification), xScale, yScale, xOffset, yOffset,
- xPrecision, yPrecision, downTime, eventTime, pointerCount);
+ motionClassificationToString(classification), xPrecision, yPrecision, downTime,
+ eventTime, pointerCount, transformString.c_str());
}
if (!seq) {
@@ -519,10 +520,12 @@
msg.body.motion.metaState = metaState;
msg.body.motion.buttonState = buttonState;
msg.body.motion.classification = classification;
- msg.body.motion.xScale = xScale;
- msg.body.motion.yScale = yScale;
- msg.body.motion.xOffset = xOffset;
- msg.body.motion.yOffset = yOffset;
+ msg.body.motion.dsdx = transform.dsdx();
+ msg.body.motion.dtdx = transform.dtdx();
+ msg.body.motion.dtdy = transform.dtdy();
+ msg.body.motion.dsdy = transform.dsdy();
+ msg.body.motion.tx = transform.tx();
+ msg.body.motion.ty = transform.ty();
msg.body.motion.xPrecision = xPrecision;
msg.body.motion.yPrecision = yPrecision;
msg.body.motion.xCursorPosition = xCursorPosition;
@@ -1166,16 +1169,18 @@
pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords);
}
+ ui::Transform transform;
+ transform.set({msg->body.motion.dsdx, msg->body.motion.dtdx, msg->body.motion.tx,
+ msg->body.motion.dtdy, msg->body.motion.dsdy, msg->body.motion.ty, 0, 0, 1});
event->initialize(msg->body.motion.eventId, msg->body.motion.deviceId, msg->body.motion.source,
msg->body.motion.displayId, msg->body.motion.hmac, msg->body.motion.action,
msg->body.motion.actionButton, msg->body.motion.flags,
msg->body.motion.edgeFlags, msg->body.motion.metaState,
- msg->body.motion.buttonState, msg->body.motion.classification,
- msg->body.motion.xScale, msg->body.motion.yScale, msg->body.motion.xOffset,
- msg->body.motion.yOffset, msg->body.motion.xPrecision,
- msg->body.motion.yPrecision, msg->body.motion.xCursorPosition,
- msg->body.motion.yCursorPosition, msg->body.motion.downTime,
- msg->body.motion.eventTime, pointerCount, pointerProperties, pointerCoords);
+ msg->body.motion.buttonState, msg->body.motion.classification, transform,
+ msg->body.motion.xPrecision, msg->body.motion.yPrecision,
+ msg->body.motion.xCursorPosition, msg->body.motion.yCursorPosition,
+ msg->body.motion.downTime, msg->body.motion.eventTime, pointerCount,
+ pointerProperties, pointerCoords);
}
void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) {
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index 116b963..51190a0 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -174,7 +174,7 @@
}
touchableRegionCropHandle = parcel->readStrongBinder();
- transform.set(std::array<float, 9>{dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
+ transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
return OK;
}
diff --git a/libs/input/android/FocusRequest.aidl b/libs/input/android/FocusRequest.aidl
new file mode 100644
index 0000000..a5034a4
--- /dev/null
+++ b/libs/input/android/FocusRequest.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android;
+
+/** @hide */
+parcelable FocusRequest {
+ /**
+ * Input channel token used to identify the window that should gain focus.
+ */
+ IBinder token;
+ /**
+ * The token that the caller expects currently to be focused. If the
+ * specified token does not match the currently focused window, this request will be dropped.
+ * If the specified focused token matches the currently focused window, the call will succeed.
+ * Set this to "null" if this call should succeed no matter what the currently focused token
+ * is.
+ */
+ @nullable IBinder focusedToken;
+ /**
+ * SYSTEM_TIME_MONOTONIC timestamp in nanos set by the client (wm) when requesting the focus
+ * change. This determines which request gets precedence if there is a focus change request
+ * from another source such as pointer down.
+ */
+ long timestamp;
+}
diff --git a/libs/input/android/os/IInputFlinger.aidl b/libs/input/android/os/IInputFlinger.aidl
index 44bb66d..5eefad3 100644
--- a/libs/input/android/os/IInputFlinger.aidl
+++ b/libs/input/android/os/IInputFlinger.aidl
@@ -16,6 +16,7 @@
package android.os;
+import android.FocusRequest;
import android.InputChannel;
import android.InputWindowInfo;
import android.os.ISetInputWindowsListener;
@@ -31,4 +32,9 @@
in @nullable ISetInputWindowsListener setInputWindowsListener);
void registerInputChannel(in InputChannel channel);
void unregisterInputChannel(in InputChannel channel);
+ /**
+ * Sets focus to the window identified by the token. This must be called
+ * after updating any input window handles.
+ */
+ oneway void setFocusedWindow(in FocusRequest request);
}
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 553dc4c..069bc0e 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -225,6 +225,7 @@
static constexpr float Y_OFFSET = 1.1;
int32_t mId;
+ ui::Transform mTransform;
void initializeEventWithHistory(MotionEvent* event);
void assertEqualsEventWithHistory(const MotionEvent* event);
@@ -233,6 +234,7 @@
void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
mId = InputEvent::nextId();
+ mTransform.set({X_SCALE, 0, X_OFFSET, 0, Y_SCALE, Y_OFFSET, 0, 0, 1});
PointerProperties pointerProperties[2];
pointerProperties[0].clear();
@@ -266,7 +268,7 @@
event->initialize(mId, 2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, HMAC,
AMOTION_EVENT_ACTION_MOVE, 0, AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
- MotionClassification::NONE, X_SCALE, Y_SCALE, X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
+ MotionClassification::NONE, mTransform, 2.0f, 2.1f,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2, pointerProperties,
pointerCoords);
@@ -326,8 +328,7 @@
ASSERT_EQ(AMETA_ALT_ON, event->getMetaState());
ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState());
ASSERT_EQ(MotionClassification::NONE, event->getClassification());
- EXPECT_EQ(X_SCALE, event->getXScale());
- EXPECT_EQ(Y_SCALE, event->getYScale());
+ EXPECT_EQ(mTransform, event->getTransform());
ASSERT_EQ(X_OFFSET, event->getXOffset());
ASSERT_EQ(Y_OFFSET, event->getYOffset());
ASSERT_EQ(2.0f, event->getXPrecision());
@@ -545,7 +546,7 @@
ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&outEvent));
}
-static void setRotationMatrix(float matrix[9], float angle) {
+static void setRotationMatrix(std::array<float, 9>& matrix, float angle) {
float sin = sinf(angle);
float cos = cosf(angle);
matrix[0] = cos;
@@ -584,13 +585,14 @@
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle);
}
MotionEvent event;
+ ui::Transform identityTransform;
event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID,
INVALID_HMAC, AMOTION_EVENT_ACTION_MOVE, 0 /*actionButton*/, 0 /*flags*/,
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
- MotionClassification::NONE, 1 /*xScale*/, 1 /*yScale*/, 0 /*xOffset*/,
- 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
- 3 + RADIUS /*xCursorPosition*/, 2 /*yCursorPosition*/, 0 /*downTime*/,
- 0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
+ MotionClassification::NONE, identityTransform, 0 /*xPrecision*/,
+ 0 /*yPrecision*/, 3 + RADIUS /*xCursorPosition*/, 2 /*yCursorPosition*/,
+ 0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties,
+ pointerCoords);
float originalRawX = 0 + 3;
float originalRawY = -RADIUS + 2;
@@ -606,7 +608,7 @@
ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
// Apply a rotation about the origin by ROTATION degrees clockwise.
- float matrix[9];
+ std::array<float, 9> matrix;
setRotationMatrix(matrix, ROTATION * PI_180);
event.transform(matrix);
@@ -648,11 +650,12 @@
pointerCoords[i].clear();
}
+ ui::Transform identityTransform;
for (MotionClassification classification : classifications) {
event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN,
DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
- AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, classification, 1 /*xScale*/,
- 1 /*yScale*/, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, classification,
+ identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/, 0 /*eventTime*/,
pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(classification, event.getClassification());
@@ -670,10 +673,11 @@
pointerCoords[i].clear();
}
+ ui::Transform identityTransform;
event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_MOUSE, DISPLAY_ID,
INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE,
- AMETA_NONE, 0, MotionClassification::NONE, 1 /*xScale*/, 1 /*yScale*/, 0, 0, 0,
- 0, 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 0 /*downTime*/,
+ AMETA_NONE, 0, MotionClassification::NONE, identityTransform, 0, 0,
+ 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 0 /*downTime*/,
0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
event.offsetLocation(20, 60);
ASSERT_EQ(280, event.getRawXCursorPosition());
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 5ddc858..e1f2562 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -173,12 +173,13 @@
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i);
}
+ ui::Transform transform;
+ transform.set({xScale, 0, xOffset, 0, yScale, yOffset, 0, 0, 1});
status = mPublisher->publishMotionEvent(seq, eventId, deviceId, source, displayId, hmac, action,
actionButton, flags, edgeFlags, metaState, buttonState,
- classification, xScale, yScale, xOffset, yOffset,
- xPrecision, yPrecision, xCursorPosition,
- yCursorPosition, downTime, eventTime, pointerCount,
- pointerProperties, pointerCoords);
+ classification, transform, xPrecision, yPrecision,
+ xCursorPosition, yCursorPosition, downTime, eventTime,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(OK, status)
<< "publisher publishMotionEvent should return OK";
@@ -206,8 +207,7 @@
EXPECT_EQ(metaState, motionEvent->getMetaState());
EXPECT_EQ(buttonState, motionEvent->getButtonState());
EXPECT_EQ(classification, motionEvent->getClassification());
- EXPECT_EQ(xScale, motionEvent->getXScale());
- EXPECT_EQ(yScale, motionEvent->getYScale());
+ EXPECT_EQ(transform, motionEvent->getTransform());
EXPECT_EQ(xOffset, motionEvent->getXOffset());
EXPECT_EQ(yOffset, motionEvent->getYOffset());
EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
@@ -326,10 +326,10 @@
pointerCoords[i].clear();
}
+ ui::Transform identityTransform;
status = mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
- 0, 0, 0, MotionClassification::NONE, 1 /* xScale */,
- 1 /* yScale */, 0, 0, 0, 0,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ 0, 0, 0, MotionClassification::NONE, identityTransform,
+ 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
@@ -342,10 +342,10 @@
PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
+ ui::Transform identityTransform;
status = mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
- 0, 0, 0, MotionClassification::NONE, 1 /* xScale */,
- 1 /* yScale */, 0, 0, 0, 0,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ 0, 0, 0, MotionClassification::NONE, identityTransform,
+ 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
@@ -363,10 +363,10 @@
pointerCoords[i].clear();
}
+ ui::Transform identityTransform;
status = mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
- 0, 0, 0, MotionClassification::NONE, 1 /* xScale */,
- 1 /* yScale */, 0, 0, 0, 0,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ 0, 0, 0, MotionClassification::NONE, identityTransform,
+ 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp
index 3da869b..1b58460 100644
--- a/libs/input/tests/InputWindow_test.cpp
+++ b/libs/input/tests/InputWindow_test.cpp
@@ -53,7 +53,7 @@
i.frameBottom = 19;
i.surfaceInset = 17;
i.globalScaleFactor = 0.3;
- i.transform.set(std::array<float, 9>{0.4, -1, 100, 0.5, 0, 40, 0, 0, 1});
+ i.transform.set({0.4, -1, 100, 0.5, 0, 40, 0, 0, 1});
i.visible = false;
i.canReceiveKeys = false;
i.hasFocus = false;
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 50be9ad..3c5fb22 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -62,16 +62,18 @@
CHECK_OFFSET(InputMessage::Body::Motion, classification, 80);
CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 84);
CHECK_OFFSET(InputMessage::Body::Motion, downTime, 88);
- CHECK_OFFSET(InputMessage::Body::Motion, xScale, 96);
- CHECK_OFFSET(InputMessage::Body::Motion, yScale, 100);
- CHECK_OFFSET(InputMessage::Body::Motion, xOffset, 104);
- CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 108);
- CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 112);
- CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 116);
- CHECK_OFFSET(InputMessage::Body::Motion, xCursorPosition, 120);
- CHECK_OFFSET(InputMessage::Body::Motion, yCursorPosition, 124);
- CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 128);
- CHECK_OFFSET(InputMessage::Body::Motion, pointers, 136);
+ CHECK_OFFSET(InputMessage::Body::Motion, dsdx, 96);
+ CHECK_OFFSET(InputMessage::Body::Motion, dtdx, 100);
+ CHECK_OFFSET(InputMessage::Body::Motion, dtdy, 104);
+ CHECK_OFFSET(InputMessage::Body::Motion, dsdy, 108);
+ CHECK_OFFSET(InputMessage::Body::Motion, tx, 112);
+ CHECK_OFFSET(InputMessage::Body::Motion, ty, 116);
+ CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 120);
+ CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 124);
+ CHECK_OFFSET(InputMessage::Body::Motion, xCursorPosition, 128);
+ CHECK_OFFSET(InputMessage::Body::Motion, yCursorPosition, 132);
+ CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 136);
+ CHECK_OFFSET(InputMessage::Body::Motion, pointers, 144);
CHECK_OFFSET(InputMessage::Body::Focus, eventId, 0);
CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 4);
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 249d9d4..e7db4b0 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -176,12 +176,12 @@
EXPECT_EQ(pointerIndex, pointerCount);
MotionEvent event;
+ ui::Transform identityTransform;
event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN,
DISPLAY_ID, INVALID_HMAC, action, 0 /*actionButton*/, 0 /*flags*/,
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
- MotionClassification::NONE, 1 /*xScale*/, 1 /*yScale*/, 0 /*xOffset*/,
- 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ MotionClassification::NONE, identityTransform, 0 /*xPrecision*/,
+ 0 /*yPrecision*/, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/,
entry.eventTime.count(), pointerCount, properties, coords);
@@ -239,10 +239,10 @@
// It is difficult to determine the correct answer here, but at least the direction
// of the reported velocity should be positive.
std::vector<MotionEventEntry> motions = {
- {0ms, {{ 273, NAN}}},
- {12585us, {{293, NAN}}},
- {14730us, {{293, NAN}}},
- {14730us, {{293, NAN}}}, // ACTION_UP
+ {0ms, {{273, 0}}},
+ {12585us, {{293, 0}}},
+ {14730us, {{293, 0}}},
+ {14730us, {{293, 0}}}, // ACTION_UP
};
computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X,
1600);
@@ -251,10 +251,10 @@
TEST_F(VelocityTrackerTest, ThreePointsZeroVelocityTest) {
// Same coordinate is reported 3 times in a row
std::vector<MotionEventEntry> motions = {
- { 0ms, {{293, NAN}} },
- { 6132us, {{293, NAN}} },
- { 11283us, {{293, NAN}} },
- { 11283us, {{293, NAN}} }, // ACTION_UP
+ {0ms, {{293, 0}}},
+ {6132us, {{293, 0}}},
+ {11283us, {{293, 0}}},
+ {11283us, {{293, 0}}}, // ACTION_UP
};
computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 0);
computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 0);
@@ -263,10 +263,7 @@
TEST_F(VelocityTrackerTest, ThreePointsLinearVelocityTest) {
// Fixed velocity at 5 points per 10 milliseconds
std::vector<MotionEventEntry> motions = {
- { 0ms, {{0, NAN}} },
- { 10ms, {{5, NAN}} },
- { 20ms, {{10, NAN}} },
- { 20ms, {{10, NAN}} }, // ACTION_UP
+ {0ms, {{0, 0}}}, {10ms, {{5, 0}}}, {20ms, {{10, 0}}}, {20ms, {{10, 0}}}, // ACTION_UP
};
computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 500);
computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 500);
diff --git a/libs/input/tests/VerifiedInputEvent_test.cpp b/libs/input/tests/VerifiedInputEvent_test.cpp
index 4e8e840..21cfe8c 100644
--- a/libs/input/tests/VerifiedInputEvent_test.cpp
+++ b/libs/input/tests/VerifiedInputEvent_test.cpp
@@ -39,13 +39,14 @@
pointerCoords[i].clear();
}
+ ui::Transform transform;
+ transform.set({2, 0, 4, 0, 3, 5, 0, 0, 1});
event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_DEFAULT,
INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, flags,
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
- MotionClassification::NONE, 2 /*xScale*/, 3 /*yScale*/, 4 /*xOffset*/,
- 5 /*yOffset*/, 0.1 /*xPrecision*/, 0.2 /*yPrecision*/, 280 /*xCursorPosition*/,
- 540 /*yCursorPosition*/, 100 /*downTime*/, 200 /*eventTime*/, pointerCount,
- pointerProperties, pointerCoords);
+ MotionClassification::NONE, transform, 0.1 /*xPrecision*/, 0.2 /*yPrecision*/,
+ 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 100 /*downTime*/,
+ 200 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
return event;
}
diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp
index 74fb019..a27c09f 100644
--- a/opengl/libs/EGL/BlobCache.cpp
+++ b/opengl/libs/EGL/BlobCache.cpp
@@ -78,12 +78,12 @@
return;
}
- std::shared_ptr<Blob> dummyKey(new Blob(key, keySize, false));
- CacheEntry dummyEntry(dummyKey, nullptr);
+ std::shared_ptr<Blob> cacheKey(new Blob(key, keySize, false));
+ CacheEntry cacheEntry(cacheKey, nullptr);
while (true) {
- auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), dummyEntry);
- if (index == mCacheEntries.end() || dummyEntry < *index) {
+ auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), cacheEntry);
+ if (index == mCacheEntries.end() || cacheEntry < *index) {
// Create a new cache entry.
std::shared_ptr<Blob> keyBlob(new Blob(key, keySize, true));
std::shared_ptr<Blob> valueBlob(new Blob(value, valueSize, true));
@@ -138,10 +138,10 @@
keySize, mMaxKeySize);
return 0;
}
- std::shared_ptr<Blob> dummyKey(new Blob(key, keySize, false));
- CacheEntry dummyEntry(dummyKey, nullptr);
- auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), dummyEntry);
- if (index == mCacheEntries.end() || dummyEntry < *index) {
+ std::shared_ptr<Blob> cacheKey(new Blob(key, keySize, false));
+ CacheEntry cacheEntry(cacheKey, nullptr);
+ auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), cacheEntry);
+ if (index == mCacheEntries.end() || cacheEntry < *index) {
ALOGV("get: no cache entry found for key of size %zu", keySize);
return 0;
}
diff --git a/opengl/libs/EGL/FileBlobCache.cpp b/opengl/libs/EGL/FileBlobCache.cpp
index 3284778..751f3be 100644
--- a/opengl/libs/EGL/FileBlobCache.cpp
+++ b/opengl/libs/EGL/FileBlobCache.cpp
@@ -70,7 +70,7 @@
return;
}
- // Sanity check the size before trying to mmap it.
+ // Check the size before trying to mmap it.
size_t fileSize = statBuf.st_size;
if (fileSize > mMaxTotalSize * 2) {
ALOGE("cache file is too large: %#" PRIx64,
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 510226d..bbd786d 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -138,7 +138,7 @@
};
EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -148,7 +148,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -258,7 +258,7 @@
EXPECT_EQ(components[2], 8);
EXPECT_EQ(components[3], 8);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -268,7 +268,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
EGLint winAttrs[] = {
@@ -306,7 +306,7 @@
get8BitConfig(config);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -316,7 +316,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
EGLint winAttrs[] = {
@@ -398,7 +398,7 @@
EXPECT_EQ(components[2], 10);
EXPECT_EQ(components[3], 2);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -408,7 +408,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
EGLint winAttrs[] = {
@@ -570,7 +570,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -580,7 +580,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -622,7 +622,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -632,7 +632,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
std::vector<EGLint> winAttrs;
@@ -705,7 +705,7 @@
EXPECT_GE(components[2], 16);
EXPECT_GE(components[3], 16);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -714,7 +714,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -734,7 +734,7 @@
ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -809,7 +809,7 @@
EXPECT_EQ(components[2], 10);
EXPECT_EQ(components[3], 2);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -819,7 +819,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -835,7 +835,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -845,7 +845,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -882,7 +882,7 @@
ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(1, numConfigs);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -892,7 +892,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -913,7 +913,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -923,7 +923,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -953,7 +953,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -963,7 +963,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 9efd38f..7fd9c3a 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -17,7 +17,7 @@
mkdir out
-# Create dummy Java files for Android APIs that are used by the code we generate.
+# Create stub Java files for Android APIs that are used by the code we generate.
# This allows us to test the generated code without building the rest of Android.
mkdir -p out/javax/microedition/khronos/opengles
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 18c819f..52d5d4f 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -75,11 +75,23 @@
}
void GpuService::setUpdatableDriverPath(const std::string& driverPath) {
- developerDriverPath = driverPath;
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+
+ // only system_server is allowed to set updatable driver path
+ if (uid != AID_SYSTEM) {
+ ALOGE("Permission Denial: can't set updatable driver path from pid=%d, uid=%d\n", pid, uid);
+ return;
+ }
+
+ std::lock_guard<std::mutex> lock(mLock);
+ mDeveloperDriverPath = driverPath;
}
std::string GpuService::getUpdatableDriverPath() {
- return developerDriverPath;
+ std::lock_guard<std::mutex> lock(mLock);
+ return mDeveloperDriverPath;
}
status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) {
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index 43faa3e..409084b 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -79,7 +79,8 @@
std::shared_ptr<GpuMem> mGpuMem;
std::unique_ptr<GpuStats> mGpuStats;
std::unique_ptr<GpuMemTracer> mGpuMemTracer;
- std::string developerDriverPath;
+ std::mutex mLock;
+ std::string mDeveloperDriverPath;
};
} // namespace android
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 088c6f1..e49667e 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -146,4 +146,9 @@
return NO_ERROR;
}
+binder::Status InputManager::setFocusedWindow(const FocusRequest& request) {
+ mDispatcher->setFocusedWindow(request);
+ return binder::Status::ok();
+}
+
} // namespace android
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 0503e81..bf86a98 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -110,6 +110,7 @@
binder::Status registerInputChannel(const InputChannel& channel) override;
binder::Status unregisterInputChannel(const InputChannel& channel) override;
+ binder::Status setFocusedWindow(const FocusRequest&) override;
private:
sp<InputReaderInterface> mReader;
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 1914a38..4e4af7e 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -199,13 +199,13 @@
const nsecs_t currentTime = now();
+ ui::Transform identityTransform;
MotionEvent event;
event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
ADISPLAY_ID_DEFAULT, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN,
/* actionButton */ 0, /* flags */ 0,
/* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
- 1 /* xScale */, 1 /* yScale */,
- /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
+ identityTransform, /* xPrecision */ 0,
/* yPrecision */ 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, currentTime,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index bfaab3c..5a4143a 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2620,10 +2620,7 @@
motionEntry->edgeFlags, motionEntry->metaState,
motionEntry->buttonState,
motionEntry->classification,
- dispatchEntry->transform.dsdx(),
- dispatchEntry->transform.dsdy(),
- dispatchEntry->transform.tx(),
- dispatchEntry->transform.ty(),
+ dispatchEntry->transform,
motionEntry->xPrecision,
motionEntry->yPrecision,
motionEntry->xCursorPosition,
@@ -3278,13 +3275,13 @@
mLock.unlock();
MotionEvent event;
+ ui::Transform transform;
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, 1 /*xScale*/,
- 1 /*yScale*/, 0 /* xOffset */, 0 /* yOffset */, args->xPrecision,
- args->yPrecision, args->xCursorPosition, args->yCursorPosition,
- args->downTime, args->eventTime, args->pointerCount,
- args->pointerProperties, args->pointerCoords);
+ args->metaState, args->buttonState, args->classification, transform,
+ args->xPrecision, args->yPrecision, args->xCursorPosition,
+ args->yCursorPosition, args->downTime, args->eventTime,
+ args->pointerCount, args->pointerProperties, args->pointerCoords);
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
@@ -5175,4 +5172,19 @@
return result == std::cv_status::no_timeout;
}
+/**
+ * Sets focus to the window identified by the token. This must be called
+ * after updating any input window handles.
+ *
+ * Params:
+ * request.token - input channel token used to identify the window that should gain focus.
+ * request.focusedToken - the token that the caller expects currently to be focused. If the
+ * specified token does not match the currently focused window, this request will be dropped.
+ * If the specified focused token matches the currently focused window, the call will succeed.
+ * Set this to "null" if this call should succeed no matter what the currently focused token is.
+ * request.timestamp - SYSTEM_TIME_MONOTONIC timestamp in nanos set by the client (wm)
+ * when requesting the focus change. This determines which request gets
+ * precedence if there is a focus change request from another source such as pointer down.
+ */
+void InputDispatcher::setFocusedWindow(const FocusRequest&) {}
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index ba7ace0..b4d1079 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -126,6 +126,7 @@
virtual status_t registerInputChannel(
const std::shared_ptr<InputChannel>& inputChannel) override;
+ virtual void setFocusedWindow(const FocusRequest&) override;
virtual status_t registerInputMonitor(const std::shared_ptr<InputChannel>& inputChannel,
int32_t displayId, bool isGestureMonitor) override;
virtual status_t unregisterInputChannel(const InputChannel& inputChannel) override;
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 272b0a6..f97c880 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -18,6 +18,7 @@
#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H
#include <InputListener.h>
+#include <android/FocusRequest.h>
#include <android/os/ISetInputWindowsListener.h>
#include <input/InputApplication.h>
#include <input/InputTransport.h>
@@ -148,6 +149,11 @@
*/
virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
+ /**
+ * Sets focus on the specified window.
+ */
+ virtual void setFocusedWindow(const FocusRequest&) = 0;
+
/* Registers input channels that may be used as targets for input events.
*
* This method may be called on any thread (usually by the input manager).
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index cd655e0..2a2cea5 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -50,6 +50,7 @@
}
binder::Status registerInputChannel(const InputChannel&) { return binder::Status::ok(); }
binder::Status unregisterInputChannel(const InputChannel&) { return binder::Status::ok(); }
+ binder::Status setFocusedWindow(const FocusRequest&) { return binder::Status::ok(); }
private:
virtual ~InputFlinger();
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index d1f20c7..9118805 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -82,6 +82,10 @@
} else {
info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
+ info->addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, mSource, -1.0f, 1.0f, 0.0f, mXScale,
+ 0.0f);
+ info->addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale,
+ 0.0f);
}
info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
@@ -341,6 +345,8 @@
} else {
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
displayId = ADISPLAY_ID_NONE;
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 15d5288..afbec99 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -142,12 +142,14 @@
hoveringIdBits.clear();
touchingIdBits.clear();
canceledIdBits.clear();
+ validIdBits.clear();
}
void CookedPointerData::copyFrom(const CookedPointerData& other) {
pointerCount = other.pointerCount;
hoveringIdBits = other.hoveringIdBits;
touchingIdBits = other.touchingIdBits;
+ validIdBits = other.validIdBits;
for (uint32_t i = 0; i < pointerCount; i++) {
pointerProperties[i].copyFrom(other.pointerProperties[i]);
@@ -288,12 +290,14 @@
const PointerProperties& pointerProperties =
mLastCookedState.cookedPointerData.pointerProperties[i];
const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
- dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
- "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, "
- "toolMinor=%0.3f, "
+ dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, dx=%0.3f, dy=%0.3f, "
+ "pressure=%0.3f, touchMajor=%0.3f, touchMinor=%0.3f, "
+ "toolMajor=%0.3f, toolMinor=%0.3f, "
"orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
"toolType=%d, isHovering=%s\n",
i, pointerProperties.id, pointerCoords.getX(), pointerCoords.getY(),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y),
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
@@ -379,6 +383,7 @@
if (!changes ||
(changes &
(InputReaderConfiguration::CHANGE_DISPLAY_INFO |
+ InputReaderConfiguration::CHANGE_POINTER_CAPTURE |
InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT |
InputReaderConfiguration::CHANGE_SHOW_TOUCHES |
InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
@@ -562,7 +567,7 @@
* 4. Otherwise, use a non-display viewport.
*/
std::optional<DisplayViewport> TouchInputMapper::findViewport() {
- if (mParameters.hasAssociatedDisplay) {
+ if (mParameters.hasAssociatedDisplay && mDeviceMode != DeviceMode::UNSCALED) {
const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
if (displayPort) {
// Find the viewport that contains the same port
@@ -620,7 +625,7 @@
// Determine device mode.
if (mParameters.deviceType == Parameters::DeviceType::POINTER &&
- mConfig.pointerGesturesEnabled) {
+ mConfig.pointerGesturesEnabled && !mConfig.pointerCapture) {
mSource = AINPUT_SOURCE_MOUSE;
mDeviceMode = DeviceMode::POINTER;
if (hasStylus()) {
@@ -2269,15 +2274,26 @@
out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
}
+ // Write output relative fieldis if applicable.
+ uint32_t id = in.id;
+ if (mSource == AINPUT_SOURCE_TOUCHPAD &&
+ mLastCookedState.cookedPointerData.hasPointerCoordsForId(id)) {
+ const PointerCoords& p = mLastCookedState.cookedPointerData.pointerCoordsForId(id);
+ float dx = xTransformed - p.getAxisValue(AMOTION_EVENT_AXIS_X);
+ float dy = yTransformed - p.getAxisValue(AMOTION_EVENT_AXIS_Y);
+ out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, dx);
+ out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, dy);
+ }
+
// Write output properties.
PointerProperties& properties = mCurrentCookedState.cookedPointerData.pointerProperties[i];
- uint32_t id = in.id;
properties.clear();
properties.id = id;
properties.toolType = in.toolType;
- // Write id index.
+ // Write id index and mark id as valid.
mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
+ mCurrentCookedState.cookedPointerData.validIdBits.markBit(id);
}
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 94486a6..df6581d 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -103,7 +103,7 @@
uint32_t pointerCount;
PointerProperties pointerProperties[MAX_POINTERS];
PointerCoords pointerCoords[MAX_POINTERS];
- BitSet32 hoveringIdBits, touchingIdBits, canceledIdBits;
+ BitSet32 hoveringIdBits, touchingIdBits, canceledIdBits, validIdBits;
uint32_t idToIndex[MAX_POINTER_ID + 1];
CookedPointerData();
@@ -129,6 +129,8 @@
inline bool isTouching(uint32_t pointerIndex) const {
return touchingIdBits.hasBit(pointerProperties[pointerIndex].id);
}
+
+ inline bool hasPointerCoordsForId(uint32_t id) const { return validIdBits.hasBit(id); }
};
class TouchInputMapper : public InputMapper {
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index eb9ac68..6465cc9 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -30,14 +30,14 @@
"AnrTracker_test.cpp",
"BlockingQueue_test.cpp",
"EventHub_test.cpp",
- "TestInputListener.cpp",
+ "IInputFlingerQuery.aidl",
"InputClassifier_test.cpp",
"InputClassifierConverter_test.cpp",
"InputDispatcher_test.cpp",
"InputReader_test.cpp",
"InputFlingerService_test.cpp",
+ "TestInputListener.cpp",
"UinputDevice.cpp",
- "IInputFlingerQuery.aidl"
],
aidl: {
include_dirs: [
diff --git a/services/inputflinger/tests/IInputFlingerQuery.aidl b/services/inputflinger/tests/IInputFlingerQuery.aidl
index 755373b..b5c5c9e 100644
--- a/services/inputflinger/tests/IInputFlingerQuery.aidl
+++ b/services/inputflinger/tests/IInputFlingerQuery.aidl
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+import android.FocusRequest;
import android.InputChannel;
import android.InputWindowInfo;
import android.os.ISetInputWindowsListener;
@@ -24,4 +25,5 @@
/* Test interfaces */
void getInputWindows(out InputWindowInfo[] inputHandles);
void getInputChannels(out InputChannel[] channels);
+ void getLastFocusRequest(out FocusRequest request);
}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 4cf4909..296201d 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -433,10 +433,11 @@
constexpr int32_t metaState = AMETA_NONE;
constexpr MotionClassification classification = MotionClassification::NONE;
+ ui::Transform identityTransform;
// Rejects undefined motion actions.
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
- /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
- 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
+ identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
@@ -448,10 +449,10 @@
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_POINTER_DOWN |
(1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
- 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
+ pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
@@ -460,10 +461,10 @@
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_POINTER_DOWN |
(~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
- 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
+ pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
@@ -473,10 +474,10 @@
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_POINTER_UP |
(1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
- 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
+ pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
@@ -485,10 +486,10 @@
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_POINTER_UP |
(~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
- 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
+ pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
@@ -497,9 +498,8 @@
// Rejects motion events with invalid number of pointers.
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
- 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ARBITRARY_TIME, ARBITRARY_TIME,
+ identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 0, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -508,9 +508,8 @@
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
- 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ARBITRARY_TIME, ARBITRARY_TIME,
+ identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -521,9 +520,8 @@
pointerProperties[0].id = -1;
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
- 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ARBITRARY_TIME, ARBITRARY_TIME,
+ identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -533,9 +531,8 @@
pointerProperties[0].id = MAX_POINTER_ID + 1;
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
- 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ARBITRARY_TIME, ARBITRARY_TIME,
+ identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -547,9 +544,8 @@
pointerProperties[1].id = 1;
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
- 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ARBITRARY_TIME, ARBITRARY_TIME,
+ identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 2, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -810,7 +806,11 @@
void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
- void setWindowScale(float xScale, float yScale) { mInfo.transform.set(xScale, 0, 0, yScale); }
+ void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
+ mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
+ }
+
+ void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
@@ -1025,13 +1025,13 @@
}
MotionEvent event;
+ ui::Transform identityTransform;
event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
- mButtonState, MotionClassification::NONE, /* xScale */ 1, /* yScale */ 1,
- /* xOffset */ 0,
- /* yOffset */ 0, /* xPrecision */ 0, /* yPrecision */ 0,
- mRawXCursorPosition, mRawYCursorPosition, mEventTime, mEventTime,
- mPointers.size(), pointerProperties.data(), pointerCoords.data());
+ mButtonState, MotionClassification::NONE, identityTransform,
+ /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
+ mRawYCursorPosition, mEventTime, mEventTime, mPointers.size(),
+ pointerProperties.data(), pointerCoords.data());
return event;
}
@@ -2489,133 +2489,123 @@
<< ", got " << motionEvent.getY(i);
}
}
+
+ void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
+ std::vector<PointF> expectedPoints) {
+ NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, touchedPoints);
+ mDispatcher->notifyMotion(&motionArgs);
+
+ // Always consume from window1 since it's the window that has the InputReceiver
+ consumeMotionEvent(mWindow1, action, expectedPoints);
+ }
};
TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
// Touch Window 1
PointF touchedPoint = {10, 10};
PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
-
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {touchedPoint});
- mDispatcher->notifyMotion(&motionArgs);
- consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
// Release touch on Window 1
- motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {touchedPoint});
- mDispatcher->notifyMotion(&motionArgs);
- // consume the UP event
- consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
// Touch Window 2
touchedPoint = {150, 150};
expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
-
- motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {touchedPoint});
- mDispatcher->notifyMotion(&motionArgs);
-
- // Consuming from window1 since it's the window that has the InputReceiver
- consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
}
-TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
+TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
+ // Set scale value for window2
mWindow2->setWindowScale(0.5f, 0.5f);
// Touch Window 1
PointF touchedPoint = {10, 10};
PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
-
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {touchedPoint});
- mDispatcher->notifyMotion(&motionArgs);
- consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
-
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
// Release touch on Window 1
- motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {touchedPoint});
- mDispatcher->notifyMotion(&motionArgs);
- // consume the UP event
- consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
// Touch Window 2
touchedPoint = {150, 150};
expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
- motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {touchedPoint});
- mDispatcher->notifyMotion(&motionArgs);
-
- // Consuming from window1 since it's the window that has the InputReceiver
- consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
+ // Update the transform so rotation is set
+ mWindow2->setWindowTransform(0, -1, 1, 0);
+ expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
}
-TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
+TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
mWindow2->setWindowScale(0.5f, 0.5f);
// Touch Window 1
std::vector<PointF> touchedPoints = {PointF{10, 10}};
std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
-
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, touchedPoints);
- mDispatcher->notifyMotion(&motionArgs);
- consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
// Touch Window 2
int32_t actionPointerDown =
AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- touchedPoints.emplace_back(PointF{150, 150});
- expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
+ touchedPoints.push_back(PointF{150, 150});
+ expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
+ touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
- motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, touchedPoints);
- mDispatcher->notifyMotion(&motionArgs);
+ // Release Window 2
+ int32_t actionPointerUp =
+ AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+ touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
+ expectedPoints.pop_back();
- // Consuming from window1 since it's the window that has the InputReceiver
- consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
+ // Update the transform so rotation is set for Window 2
+ mWindow2->setWindowTransform(0, -1, 1, 0);
+ expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
+ touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
}
-TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
+TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
mWindow2->setWindowScale(0.5f, 0.5f);
// Touch Window 1
std::vector<PointF> touchedPoints = {PointF{10, 10}};
std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
-
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, touchedPoints);
- mDispatcher->notifyMotion(&motionArgs);
- consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
// Touch Window 2
int32_t actionPointerDown =
AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- touchedPoints.emplace_back(PointF{150, 150});
- expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
+ touchedPoints.push_back(PointF{150, 150});
+ expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
- motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, touchedPoints);
- mDispatcher->notifyMotion(&motionArgs);
-
- // Consuming from window1 since it's the window that has the InputReceiver
- consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
+ touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
// Move both windows
touchedPoints = {{20, 20}, {175, 175}};
expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
- motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, touchedPoints);
- mDispatcher->notifyMotion(&motionArgs);
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
- consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
+ // Release Window 2
+ int32_t actionPointerUp =
+ AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+ touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
+ expectedPoints.pop_back();
+
+ // Touch Window 2
+ mWindow2->setWindowTransform(0, -1, 1, 0);
+ expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
+ touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
+
+ // Move both windows
+ touchedPoints = {{20, 20}, {175, 175}};
+ expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
+ getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
+
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
}
TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
@@ -2624,36 +2614,22 @@
// Touch Window 1
std::vector<PointF> touchedPoints = {PointF{10, 10}};
std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
-
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, touchedPoints);
- mDispatcher->notifyMotion(&motionArgs);
- consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
// Touch Window 2
int32_t actionPointerDown =
AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- touchedPoints.emplace_back(PointF{150, 150});
- expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
+ touchedPoints.push_back(PointF{150, 150});
+ expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
- motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, touchedPoints);
- mDispatcher->notifyMotion(&motionArgs);
-
- // Consuming from window1 since it's the window that has the InputReceiver
- consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
+ touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
// Move both windows
touchedPoints = {{20, 20}, {175, 175}};
expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
- motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, touchedPoints);
- mDispatcher->notifyMotion(&motionArgs);
-
- consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
+ touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
}
class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp
index ce82d28..02342c0 100644
--- a/services/inputflinger/tests/InputFlingerService_test.cpp
+++ b/services/inputflinger/tests/InputFlingerService_test.cpp
@@ -55,6 +55,7 @@
namespace android {
static const sp<IBinder> TestInfoToken = new BBinder();
+static const sp<IBinder> FocusedTestInfoToken = new BBinder();
static constexpr int32_t TestInfoId = 1;
static const std::string TestInfoName = "InputFlingerServiceTestInputWindowInfo";
static constexpr Flags<InputWindowInfo::Flag> TestInfoFlags = InputWindowInfo::Flag::NOT_FOCUSABLE;
@@ -102,7 +103,9 @@
protected:
void InitializeInputFlinger();
- void setInputWindowsByInfos(std::vector<InputWindowInfo>& infos);
+ void setInputWindowsByInfos(const std::vector<InputWindowInfo>& infos);
+ void setFocusedWindow(const sp<IBinder> token, const sp<IBinder> focusedToken,
+ nsecs_t timestampNanos);
void setInputWindowsFinished();
void verifyInputWindowInfo(const InputWindowInfo& info) const;
@@ -137,6 +140,7 @@
binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles);
binder::Status getInputChannels(std::vector<::android::InputChannel>* channels);
+ binder::Status getLastFocusRequest(FocusRequest*);
status_t dump(int fd, const Vector<String16>& args) override;
@@ -146,11 +150,13 @@
binder::Status registerInputChannel(const InputChannel& channel) override;
binder::Status unregisterInputChannel(const InputChannel& channel) override;
+ binder::Status setFocusedWindow(const FocusRequest&) override;
private:
mutable Mutex mLock;
std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mHandlesPerDisplay;
std::vector<std::shared_ptr<InputChannel>> mInputChannels;
+ FocusRequest mFocusRequest;
};
class TestInputQuery : public BnInputFlingerQuery {
@@ -158,6 +164,7 @@
TestInputQuery(sp<android::TestInputManager> manager) : mManager(manager){};
binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override;
binder::Status getInputChannels(std::vector<::android::InputChannel>* channels) override;
+ binder::Status getLastFocusRequest(FocusRequest*) override;
private:
sp<android::TestInputManager> mManager;
@@ -172,6 +179,10 @@
return mManager->getInputChannels(channels);
}
+binder::Status TestInputQuery::getLastFocusRequest(FocusRequest* request) {
+ return mManager->getLastFocusRequest(request);
+}
+
binder::Status SetInputWindowsListener::onSetInputWindowsFinished() {
if (mCbFunc != nullptr) {
mCbFunc();
@@ -251,6 +262,16 @@
return binder::Status::ok();
}
+binder::Status TestInputManager::getLastFocusRequest(FocusRequest* request) {
+ *request = mFocusRequest;
+ return binder::Status::ok();
+}
+
+binder::Status TestInputManager::setFocusedWindow(const FocusRequest& request) {
+ mFocusRequest = request;
+ return binder::Status::ok();
+}
+
void InputFlingerServiceTest::SetUp() {
mSetInputWindowsListener = new SetInputWindowsListener([&]() {
std::unique_lock<std::mutex> lock(mLock);
@@ -270,8 +291,8 @@
mInfo.frameBottom = TestInfoFrameBottom;
mInfo.surfaceInset = TestInfoSurfaceInset;
mInfo.globalScaleFactor = TestInfoGlobalScaleFactor;
- mInfo.transform.set(std::array<float, 9>{TestInfoWindowXScale, 0, TestInfoFrameLeft, 0,
- TestInfoWindowYScale, TestInfoFrameTop, 0, 0, 1});
+ mInfo.transform.set({TestInfoWindowXScale, 0, TestInfoFrameLeft, 0, TestInfoWindowYScale,
+ TestInfoFrameTop, 0, 0, 1});
mInfo.touchableRegion = TestInfoTouchableRegion;
mInfo.visible = TestInfoVisible;
mInfo.canReceiveKeys = TestInfoCanReceiveKeys;
@@ -310,13 +331,25 @@
mQuery = interface_cast<IInputFlingerQuery>(input);
}
-void InputFlingerServiceTest::setInputWindowsByInfos(std::vector<InputWindowInfo>& infos) {
+void InputFlingerServiceTest::setInputWindowsByInfos(const std::vector<InputWindowInfo>& infos) {
std::unique_lock<std::mutex> lock(mLock);
mService->setInputWindows(infos, mSetInputWindowsListener);
// Verify listener call
EXPECT_NE(mSetInputWindowsFinishedCondition.wait_for(lock, 1s), std::cv_status::timeout);
}
+void InputFlingerServiceTest::setFocusedWindow(const sp<IBinder> token,
+ const sp<IBinder> focusedToken,
+ nsecs_t timestampNanos) {
+ FocusRequest request;
+ request.token = TestInfoToken;
+ request.focusedToken = focusedToken;
+ request.timestamp = timestampNanos;
+ mService->setFocusedWindow(request);
+ // call set input windows and wait for the callback to drain the queue.
+ setInputWindowsByInfos(std::vector<InputWindowInfo>());
+}
+
/**
* Test InputFlinger service interface SetInputWindows
*/
@@ -376,6 +409,30 @@
EXPECT_EQ(channels.size(), 0UL);
}
+TEST_F(InputFlingerServiceTest, InputWindow_setFocusedWindow) {
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ setFocusedWindow(TestInfoToken, nullptr /* focusedToken */, now);
+
+ FocusRequest request;
+ mQuery->getLastFocusRequest(&request);
+
+ EXPECT_EQ(request.token, TestInfoToken);
+ EXPECT_EQ(request.focusedToken, nullptr);
+ EXPECT_EQ(request.timestamp, now);
+}
+
+TEST_F(InputFlingerServiceTest, InputWindow_setFocusedWindowWithFocusedToken) {
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ setFocusedWindow(TestInfoToken, FocusedTestInfoToken, now);
+
+ FocusRequest request;
+ mQuery->getLastFocusRequest(&request);
+
+ EXPECT_EQ(request.token, TestInfoToken);
+ EXPECT_EQ(request.focusedToken, FocusedTestInfoToken);
+ EXPECT_EQ(request.timestamp, now);
+}
+
} // namespace android
int main(int argc, char** argv) {
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 21dd3c7..232045b 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -297,6 +297,8 @@
mConfig.defaultPointerDisplayId = pointerDisplayId;
}
+ float getPointerGestureMovementSpeedRatio() { return mConfig.pointerGestureMovementSpeedRatio; }
+
private:
DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
int32_t orientation, const std::string& uniqueId, std::optional<uint8_t> physicalPort,
@@ -7533,4 +7535,207 @@
constexpr int32_t yExpected = (x + 1) - DISPLAY_WIDTH / 4;
processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected);
}
+
+TEST_F(MultiTouchInputMapperTest, Process_TouchpadCapture) {
+ // we need a pointer controller for mouse mode of touchpad (start pointer at 0,0)
+ std::shared_ptr<FakePointerController> fakePointerController =
+ std::make_shared<FakePointerController>();
+ fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
+ fakePointerController->setPosition(0, 0);
+ fakePointerController->setButtonState(0);
+
+ // prepare device and capture
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION | ID | SLOT);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
+ mFakePolicy->setPointerCapture(true);
+ mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // captured touchpad should be a touchpad source
+ NotifyDeviceResetArgs resetArgs;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
+
+ // run captured pointer tests - note that this is unscaled, so input listener events should be
+ // identical to what the hardware sends (accounting for any
+ // calibration).
+ // FINGER 0 DOWN
+ processId(mapper, 1);
+ processPosition(mapper, 100 + RAW_X_MIN, 100 + RAW_Y_MIN);
+ processKey(mapper, BTN_TOUCH, 1);
+ processSync(mapper);
+
+ // expect coord[0] to contain initial location of touch 0
+ NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(1U, args.pointerCount);
+ ASSERT_EQ(0, args.pointerProperties[0].id);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, args.source);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 100, 100, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // FINGER 1 DOWN
+ processSlot(mapper, 1);
+ processId(mapper, 2);
+ processPosition(mapper, 560 + RAW_X_MIN, 154 + RAW_Y_MIN);
+ processSync(mapper);
+
+ // expect coord[0] to contain previous location, coord[1] to contain new touch 1 location
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | 0x0100, args.action);
+ ASSERT_EQ(2U, args.pointerCount);
+ ASSERT_EQ(0, args.pointerProperties[0].id);
+ ASSERT_EQ(1, args.pointerProperties[1].id);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 100, 100, 1, 0, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[1], 560, 154, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // FINGER 1 MOVE
+ processPosition(mapper, 540 + RAW_X_MIN, 690 + RAW_Y_MIN);
+ processSync(mapper);
+
+ // expect coord[0] to contain previous location, coord[1] to contain new touch 1 location
+ // from move
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 100, 100, 1, 0, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[1], 540, 690, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // FINGER 0 MOVE
+ processSlot(mapper, 0);
+ processPosition(mapper, 50 + RAW_X_MIN, 800 + RAW_Y_MIN);
+ processSync(mapper);
+
+ // expect coord[0] to contain new touch 0 location, coord[1] to contain previous location
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 50, 800, 1, 0, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[1], 540, 690, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // BUTTON DOWN
+ processKey(mapper, BTN_LEFT, 1);
+ processSync(mapper);
+
+ // touchinputmapper design sends a move before button press
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
+
+ // BUTTON UP
+ processKey(mapper, BTN_LEFT, 0);
+ processSync(mapper);
+
+ // touchinputmapper design sends a move after button release
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+
+ // FINGER 0 UP
+ processId(mapper, -1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | 0x0000, args.action);
+
+ // FINGER 1 MOVE
+ processSlot(mapper, 1);
+ processPosition(mapper, 320 + RAW_X_MIN, 900 + RAW_Y_MIN);
+ processSync(mapper);
+
+ // expect coord[0] to contain new location of touch 1, and properties[0].id to contain 1
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_EQ(1U, args.pointerCount);
+ ASSERT_EQ(1, args.pointerProperties[0].id);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 320, 900, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // FINGER 1 UP
+ processId(mapper, -1);
+ processKey(mapper, BTN_TOUCH, 0);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
+
+ // non captured touchpad should be a mouse source
+ mFakePolicy->setPointerCapture(false);
+ configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+ ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_UnCapturedTouchpadPointer) {
+ std::shared_ptr<FakePointerController> fakePointerController =
+ std::make_shared<FakePointerController>();
+ fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
+ fakePointerController->setPosition(0, 0);
+ fakePointerController->setButtonState(0);
+
+ // prepare device and capture
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION | ID | SLOT);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
+ mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ // run uncaptured pointer tests - pushes out generic events
+ // FINGER 0 DOWN
+ processId(mapper, 3);
+ processPosition(mapper, 100, 100);
+ processKey(mapper, BTN_TOUCH, 1);
+ processSync(mapper);
+
+ // start at (100,100), cursor should be at (0,0) * scale
+ NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ // FINGER 0 MOVE
+ processPosition(mapper, 200, 200);
+ processSync(mapper);
+
+ // compute scaling to help with touch position checking
+ float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
+ float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ float scale =
+ mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
+
+ // translate from (100,100) -> (200,200), cursor should have changed to (100,100) * scale)
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 100 * scale, 100 * scale, 0,
+ 0, 0, 0, 0, 0, 0, 0));
+}
+
+TEST_F(MultiTouchInputMapperTest, WhenCapturedAndNotCaptured_GetSources) {
+ std::shared_ptr<FakePointerController> fakePointerController =
+ std::make_shared<FakePointerController>();
+
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION | ID | SLOT);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
+ mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+ mFakePolicy->setPointerCapture(false);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // uncaptured touchpad should be a pointer device
+ ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
+
+ // captured touchpad should be a touchpad device
+ mFakePolicy->setPointerCapture(true);
+ configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
+}
+
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7d5cb67..aba5861 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1567,7 +1567,7 @@
mEventQueue->refresh();
}
-nsecs_t SurfaceFlinger::getVsyncPeriod() const {
+nsecs_t SurfaceFlinger::getVsyncPeriodFromHWC() const {
const auto displayId = getInternalDisplayIdLocked();
if (!displayId || !getHwComposer().isConnected(*displayId)) {
return 0;
@@ -1774,7 +1774,7 @@
setPowerModeInternal(display, currentDisplayPowerMode);
// Reset the timing values to account for the period of the swapped in HWC
- const nsecs_t vsyncPeriod = getVsyncPeriod();
+ const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
// The present fences returned from vr_hwc are not an accurate
@@ -2932,6 +2932,10 @@
mInputFlinger->setInputWindows(inputInfos,
mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
: nullptr);
+ for (const auto& focusRequest : mInputWindowCommands.focusRequests) {
+ mInputFlinger->setFocusedWindow(focusRequest);
+ }
+ mInputWindowCommands.focusRequests.clear();
}
void SurfaceFlinger::commitInputWindowCommands() {
@@ -3922,13 +3926,8 @@
}
uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) {
- uint32_t flags = 0;
- if (inputWindowCommands.syncInputWindows) {
- flags |= eTraversalNeeded;
- }
-
- mPendingInputWindowCommands.merge(inputWindowCommands);
- return flags;
+ const bool hasChanges = mPendingInputWindowCommands.merge(inputWindowCommands);
+ return hasChanges ? eTraversalNeeded : 0;
}
status_t SurfaceFlinger::mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle,
@@ -4209,8 +4208,7 @@
{});
setPowerModeInternal(display, hal::PowerMode::ON);
-
- const nsecs_t vsyncPeriod = getVsyncPeriod();
+ const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
// Use phase of 0 since phase is not known.
@@ -4245,7 +4243,7 @@
if (mInterceptor->isEnabled()) {
mInterceptor->savePowerModeUpdate(display->getSequenceId(), static_cast<int32_t>(mode));
}
-
+ const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
if (currentMode == hal::PowerMode::OFF) {
if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno));
@@ -4254,7 +4252,7 @@
if (display->isPrimary() && mode != hal::PowerMode::DOZE_SUSPEND) {
getHwComposer().setVsyncEnabled(*displayId, mHWCVsyncPendingState);
mScheduler->onScreenAcquired(mAppConnectionHandle);
- mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+ mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
}
mVisibleRegionsDirty = true;
@@ -4281,7 +4279,7 @@
getHwComposer().setPowerMode(*displayId, mode);
if (display->isPrimary() && currentMode == hal::PowerMode::DOZE_SUSPEND) {
mScheduler->onScreenAcquired(mAppConnectionHandle);
- mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+ mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
}
} else if (mode == hal::PowerMode::DOZE_SUSPEND) {
// Leave display going to doze
@@ -4394,7 +4392,7 @@
}
void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) const {
- StringAppendF(&result, "%" PRId64 "\n", getVsyncPeriod());
+ StringAppendF(&result, "%" PRId64 "\n", getVsyncPeriodFromHWC());
if (args.size() > 1) {
const auto name = String8(args[1]);
@@ -4459,7 +4457,7 @@
mPhaseConfiguration->dump(result);
StringAppendF(&result,
" present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64 " ns\n\n",
- dispSyncPresentTimeOffset, getVsyncPeriod());
+ dispSyncPresentTimeOffset, getVsyncPeriodFromHWC());
scheduler::RefreshRateConfigs::Policy policy = mRefreshRateConfigs->getDisplayManagerPolicy();
StringAppendF(&result,
@@ -5324,7 +5322,8 @@
case 1035: {
n = data.readInt32();
mDebugDisplayConfigSetByBackdoor = false;
- if (n >= 0) {
+ const auto numConfigs = mRefreshRateConfigs->getAllRefreshRates().size();
+ if (n >= 0 && n < numConfigs) {
const auto displayToken = getInternalDisplayToken();
status_t result = setActiveConfig(displayToken, n);
if (result != NO_ERROR) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d56321d..2c4e40d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -856,7 +856,7 @@
/* ------------------------------------------------------------------------
* VSync
*/
- nsecs_t getVsyncPeriod() const REQUIRES(mStateLock);
+ nsecs_t getVsyncPeriodFromHWC() const REQUIRES(mStateLock);
// Sets the refresh rate by switching active configs, if they are available for
// the desired refresh rate.
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 009de06..fc11537 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -88,7 +88,7 @@
using HotplugEvent = TestableSurfaceFlinger::HotplugEvent;
using HWC2Display = TestableSurfaceFlinger::HWC2Display;
-constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666;
+constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'667;
constexpr int32_t DEFAULT_DPI = 320;
constexpr int DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT = HAL_PIXEL_FORMAT_RGB_565;