Merge "PointerChoreographer: Show spot hover icon for stylus when showing taps" into main
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 82cacca..d233902 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -145,6 +145,9 @@
* Buffers which are replaced or removed from the scene in the transaction invoking
* this callback may be reused after this point.
*
+ * Starting with API level 36, prefer using \a ASurfaceTransaction_OnBufferRelease to listen
+ * to when a buffer is ready to be reused.
+ *
* \param context Optional context provided by the client that is passed into
* the callback.
*
@@ -190,6 +193,35 @@
__INTRODUCED_IN(31);
/**
+ * The ASurfaceTransaction_OnBufferRelease callback is invoked when a buffer that was passed in
+ * ASurfaceTransaction_setBuffer is ready to be reused.
+ *
+ * This callback is guaranteed to be invoked if ASurfaceTransaction_setBuffer is called with a non
+ * null buffer. If the buffer in the transaction is replaced via another call to
+ * ASurfaceTransaction_setBuffer, the callback will be invoked immediately. Otherwise the callback
+ * will be invoked before the ASurfaceTransaction_OnComplete callback after the buffer was
+ * presented.
+ *
+ * If this callback is set, caller should not release the buffer using the
+ * ASurfaceTransaction_OnComplete.
+ *
+ * \param context Optional context provided by the client that is passed into the callback.
+ *
+ * \param release_fence_fd Returns the fence file descriptor used to signal the release of buffer
+ * associated with this callback. If this fence is valid (>=0), the buffer has not yet been released
+ * and the fence will signal when the buffer has been released. If the fence is -1 , the buffer is
+ * already released. The recipient of the callback takes ownership of the fence fd and is
+ * responsible for closing it.
+ *
+ * THREADING
+ * The callback can be invoked on any thread.
+ *
+ * Available since API level 36.
+ */
+typedef void (*ASurfaceTransaction_OnBufferRelease)(void* _Null_unspecified context,
+ int release_fence_fd) __INTRODUCED_IN(36);
+
+/**
* Returns the timestamp of when the frame was latched by the framework. Once a frame is
* latched by the framework, it is presented at the following hardware vsync.
*
@@ -251,7 +283,7 @@
/**
* The returns the fence used to signal the release of the PREVIOUS buffer set on
* this surface. If this fence is valid (>=0), the PREVIOUS buffer has not yet been released and the
- * fence will signal when the PREVIOUS buffer has been released. If the fence is -1 , the PREVIOUS
+ * fence will signal when the PREVIOUS buffer has been released. If the fence is -1, the PREVIOUS
* buffer is already released. The recipient of the callback takes ownership of the
* previousReleaseFenceFd and is responsible for closing it.
*
@@ -353,6 +385,9 @@
* Note that the buffer must be allocated with AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE
* as the surface control might be composited using the GPU.
*
+ * Starting with API level 36, prefer using \a ASurfaceTransaction_setBufferWithRelease to
+ * set a buffer and a callback which will be invoked when the buffer is ready to be reused.
+ *
* Available since API level 29.
*/
void ASurfaceTransaction_setBuffer(ASurfaceTransaction* _Nonnull transaction,
@@ -361,6 +396,29 @@
__INTRODUCED_IN(29);
/**
+ * Updates the AHardwareBuffer displayed for \a surface_control. If not -1, the
+ * acquire_fence_fd should be a file descriptor that is signaled when all pending work
+ * for the buffer is complete and the buffer can be safely read.
+ *
+ * The frameworks takes ownership of the \a acquire_fence_fd passed and is responsible
+ * for closing it.
+ *
+ * Note that the buffer must be allocated with AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE
+ * as the surface control might be composited using the GPU.
+ *
+ * When the buffer is ready to be reused, the ASurfaceTransaction_OnBufferRelease
+ * callback will be invoked. If the buffer is null, the callback will not be invoked.
+ *
+ * Available since API level 36.
+ */
+void ASurfaceTransaction_setBufferWithRelease(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ AHardwareBuffer* _Nonnull buffer,
+ int acquire_fence_fd, void* _Null_unspecified context,
+ ASurfaceTransaction_OnBufferRelease _Nonnull func)
+ __INTRODUCED_IN(36);
+
+/**
* Updates the color for \a surface_control. This will make the background color for the
* ASurfaceControl visible in transparent regions of the surface. Colors \a r, \a g,
* and \a b must be within the range that is valid for \a dataspace. \a dataspace and \a alpha
diff --git a/include/input/Resampler.h b/include/input/Resampler.h
index 2892137..67d92bd 100644
--- a/include/input/Resampler.h
+++ b/include/input/Resampler.h
@@ -35,9 +35,9 @@
virtual ~Resampler() = default;
/**
- * Tries to resample motionEvent at resampleTime. The provided resampleTime must be greater than
+ * Tries to resample motionEvent at frameTime. The provided frameTime must be greater than
* the latest sample time of motionEvent. It is not guaranteed that resampling occurs at
- * resampleTime. Interpolation may occur is futureSample is available. Otherwise, motionEvent
+ * frameTime. Interpolation may occur is futureSample is available. Otherwise, motionEvent
* may be resampled by another method, or not resampled at all. Furthermore, it is the
* implementer's responsibility to guarantee the following:
* - If resampling occurs, a single additional sample should be added to motionEvent. That is,
@@ -45,15 +45,14 @@
* samples by the end of the resampling. No other field of motionEvent should be modified.
* - If resampling does not occur, then motionEvent must not be modified in any way.
*/
- virtual void resampleMotionEvent(std::chrono::nanoseconds resampleTime,
- MotionEvent& motionEvent,
+ virtual void resampleMotionEvent(std::chrono::nanoseconds frameTime, MotionEvent& motionEvent,
const InputMessage* futureSample) = 0;
};
class LegacyResampler final : public Resampler {
public:
/**
- * Tries to resample `motionEvent` at `resampleTime` by adding a resampled sample at the end of
+ * Tries to resample `motionEvent` at `frameTime` by adding a resampled sample at the end of
* `motionEvent` with eventTime equal to `resampleTime` and pointer coordinates determined by
* linear interpolation or linear extrapolation. An earlier `resampleTime` will be used if
* extrapolation takes place and `resampleTime` is too far in the future. If `futureSample` is
@@ -61,7 +60,7 @@
* data, LegacyResampler will extrapolate. Otherwise, no resampling takes place and
* `motionEvent` is unmodified.
*/
- void resampleMotionEvent(std::chrono::nanoseconds resampleTime, MotionEvent& motionEvent,
+ void resampleMotionEvent(std::chrono::nanoseconds frameTime, MotionEvent& motionEvent,
const InputMessage* futureSample) override;
private:
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 319716e..cbba711 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -40,6 +40,7 @@
cc_library_headers {
name: "libarect_headers",
+ host_supported: true,
vendor_available: true,
min_sdk_version: "29",
// TODO(b/153609531): remove when no longer needed.
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index f518a22..3cd2b9a 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -46,6 +46,7 @@
#include "android/binder_ibinder.h"
using namespace android;
+using namespace std::chrono_literals;
constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
@@ -54,7 +55,7 @@
constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestService";
constexpr char kBinderNdkUnitTestServiceFlagged[] = "BinderNdkUnitTestFlagged";
-constexpr unsigned int kShutdownWaitTime = 11;
+constexpr auto kShutdownWaitTime = 30s;
constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;
class MyTestFoo : public IFoo {
@@ -253,12 +254,22 @@
}
bool isServiceRunning(const char* serviceName) {
- AIBinder* binder = AServiceManager_checkService(serviceName);
- if (binder == nullptr) {
- return false;
+ static const sp<android::IServiceManager> sm(android::defaultServiceManager());
+ const Vector<String16> services = sm->listServices();
+ for (const auto service : services) {
+ if (service == String16(serviceName)) return true;
}
- AIBinder_decStrong(binder);
+ return false;
+}
+bool isServiceShutdownWithWait(const char* serviceName) {
+ LOG(INFO) << "About to check and wait for shutdown of " << std::string(serviceName);
+ const auto before = std::chrono::steady_clock::now();
+ while (isServiceRunning(serviceName)) {
+ sleep(1);
+ const auto after = std::chrono::steady_clock::now();
+ if (after - before >= kShutdownWaitTime) return false;
+ }
return true;
}
@@ -450,8 +461,8 @@
service = nullptr;
IPCThreadState::self()->flushCommands();
// Make sure the service is dead after some time of no use
- sleep(kShutdownWaitTime);
- ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService));
+ ASSERT_TRUE(isServiceShutdownWithWait(kLazyBinderNdkUnitTestService))
+ << "Service failed to shut down";
}
TEST(NdkBinder, ForcedPersistenceTest) {
@@ -466,14 +477,12 @@
service = nullptr;
IPCThreadState::self()->flushCommands();
- sleep(kShutdownWaitTime);
-
- bool isRunning = isServiceRunning(kForcePersistNdkUnitTestService);
-
if (i == 0) {
- ASSERT_TRUE(isRunning) << "Service shut down when it shouldn't have.";
+ ASSERT_TRUE(isServiceRunning(kForcePersistNdkUnitTestService))
+ << "Service shut down when it shouldn't have.";
} else {
- ASSERT_FALSE(isRunning) << "Service failed to shut down.";
+ ASSERT_TRUE(isServiceShutdownWithWait(kForcePersistNdkUnitTestService))
+ << "Service failed to shut down";
}
}
}
@@ -491,10 +500,7 @@
service = nullptr;
IPCThreadState::self()->flushCommands();
- LOG(INFO) << "ActiveServicesCallbackTest about to sleep";
- sleep(kShutdownWaitTime);
-
- ASSERT_FALSE(isServiceRunning(kActiveServicesNdkUnitTestService))
+ ASSERT_TRUE(isServiceShutdownWithWait(kActiveServicesNdkUnitTestService))
<< "Service failed to shut down.";
}
diff --git a/libs/binder/tests/binderCacheUnitTest.cpp b/libs/binder/tests/binderCacheUnitTest.cpp
index 92dab19..482d197 100644
--- a/libs/binder/tests/binderCacheUnitTest.cpp
+++ b/libs/binder/tests/binderCacheUnitTest.cpp
@@ -137,9 +137,9 @@
ASSERT_EQ(binder1, result);
// Kill the server, this should remove from cache.
- foo.killServer(binder1);
pid_t pid;
ASSERT_EQ(OK, binder1->getDebugPid(&pid));
+ foo.killServer(binder1);
system(("kill -9 " + std::to_string(pid)).c_str());
sp<IBinder> binder2 = sp<BBinder>::make();
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index fbca35e..a1e53c5 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -454,7 +454,7 @@
GTEST_SKIP() << "This test requires multiple threads";
}
- constexpr size_t kNumThreads = 10;
+ constexpr size_t kNumThreads = 5;
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 94998e5..c65eafa 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -1266,6 +1266,11 @@
mTransactionHangCallback = std::move(callback);
}
+void BLASTBufferQueue::setApplyToken(sp<IBinder> applyToken) {
+ std::lock_guard _lock{mMutex};
+ mApplyToken = std::move(applyToken);
+}
+
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
BLASTBufferQueue::BufferReleaseReader::BufferReleaseReader(
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 868dbd0..ba58a15 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -143,7 +143,7 @@
* indicates the reason for the hang.
*/
void setTransactionHangCallback(std::function<void(const std::string&)> callback);
-
+ void setApplyToken(sp<IBinder>);
virtual ~BLASTBufferQueue();
void onFirstRef() override;
@@ -272,7 +272,7 @@
// Queues up transactions using this token in SurfaceFlinger. This prevents queued up
// transactions from other parts of the client from blocking this transaction.
- const sp<IBinder> mApplyToken GUARDED_BY(mMutex) = sp<BBinder>::make();
+ sp<IBinder> mApplyToken GUARDED_BY(mMutex) = sp<BBinder>::make();
// Guards access to mDequeueTimestamps since we cannot hold to mMutex in onFrameDequeued or
// we will deadlock.
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index eb2a61d..53f4a36 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -186,6 +186,10 @@
mBlastBufferQueueAdapter->mergeWithNextTransaction(merge, frameNumber);
}
+ void setApplyToken(sp<IBinder> applyToken) {
+ mBlastBufferQueueAdapter->setApplyToken(std::move(applyToken));
+ }
+
private:
sp<TestBLASTBufferQueue> mBlastBufferQueueAdapter;
};
@@ -511,6 +515,69 @@
adapter.waitForCallbacks();
}
+class WaitForCommittedCallback {
+public:
+ WaitForCommittedCallback() = default;
+ ~WaitForCommittedCallback() = default;
+
+ void wait() {
+ std::unique_lock lock(mMutex);
+ cv.wait(lock, [this] { return mCallbackReceived; });
+ }
+
+ void notify() {
+ std::unique_lock lock(mMutex);
+ mCallbackReceived = true;
+ cv.notify_one();
+ mCallbackReceivedTimeStamp = std::chrono::system_clock::now();
+ }
+ auto getCallback() {
+ return [this](void* /* unused context */, nsecs_t /* latchTime */,
+ const sp<Fence>& /* presentFence */,
+ const std::vector<SurfaceControlStats>& /* stats */) { notify(); };
+ }
+ std::chrono::time_point<std::chrono::system_clock> mCallbackReceivedTimeStamp;
+
+private:
+ std::mutex mMutex;
+ std::condition_variable cv;
+ bool mCallbackReceived = false;
+};
+
+TEST_F(BLASTBufferQueueTest, setApplyToken) {
+ sp<IBinder> applyToken = sp<BBinder>::make();
+ WaitForCommittedCallback firstTransaction;
+ WaitForCommittedCallback secondTransaction;
+ {
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+ adapter.setApplyToken(applyToken);
+ sp<IGraphicBufferProducer> igbProducer;
+ setUpProducer(adapter, igbProducer);
+
+ Transaction t;
+ t.addTransactionCommittedCallback(firstTransaction.getCallback(), nullptr);
+ adapter.mergeWithNextTransaction(&t, 1);
+ queueBuffer(igbProducer, 127, 127, 127,
+ /*presentTimeDelay*/ std::chrono::nanoseconds(500ms).count());
+ }
+ {
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+ adapter.setApplyToken(applyToken);
+ sp<IGraphicBufferProducer> igbProducer;
+ setUpProducer(adapter, igbProducer);
+
+ Transaction t;
+ t.addTransactionCommittedCallback(secondTransaction.getCallback(), nullptr);
+ adapter.mergeWithNextTransaction(&t, 1);
+ queueBuffer(igbProducer, 127, 127, 127, /*presentTimeDelay*/ 0);
+ }
+
+ firstTransaction.wait();
+ secondTransaction.wait();
+ EXPECT_GT(secondTransaction.mCallbackReceivedTimeStamp,
+ firstTransaction.mCallbackReceivedTimeStamp);
+}
+
TEST_F(BLASTBufferQueueTest, SetCrop_Item) {
uint8_t r = 255;
uint8_t g = 0;
diff --git a/libs/input/Resampler.cpp b/libs/input/Resampler.cpp
index c663649..b535ff4 100644
--- a/libs/input/Resampler.cpp
+++ b/libs/input/Resampler.cpp
@@ -241,13 +241,15 @@
motionEvent.getId());
}
-void LegacyResampler::resampleMotionEvent(nanoseconds resampleTime, MotionEvent& motionEvent,
+void LegacyResampler::resampleMotionEvent(nanoseconds frameTime, MotionEvent& motionEvent,
const InputMessage* futureSample) {
if (mPreviousDeviceId && *mPreviousDeviceId != motionEvent.getDeviceId()) {
mLatestSamples.clear();
}
mPreviousDeviceId = motionEvent.getDeviceId();
+ const nanoseconds resampleTime = frameTime - RESAMPLE_LATENCY;
+
updateLatestSamples(motionEvent);
const std::optional<Sample> sample = (futureSample != nullptr)
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 43bc894..3ec167a 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -95,6 +95,7 @@
},
},
},
+ native_coverage: false,
}
// NOTE: This is a compile time test, and does not need to be
diff --git a/libs/input/tests/Resampler_test.cpp b/libs/input/tests/Resampler_test.cpp
index 7ae9a28..26dee39 100644
--- a/libs/input/tests/Resampler_test.cpp
+++ b/libs/input/tests/Resampler_test.cpp
@@ -120,6 +120,47 @@
} // namespace
+/**
+ * The testing setup assumes an input rate of 200 Hz and a display rate of 60 Hz. This implies that
+ * input events are received every 5 milliseconds, while the display consumes batched events every
+ * ~16 milliseconds. The resampler's RESAMPLE_LATENCY constant determines the resample time, which
+ * is calculated as frameTime - RESAMPLE_LATENCY. resampleTime specifies the time used for
+ * resampling. For example, if the desired frame time consumption is ~16 milliseconds, the resample
+ * time would be ~11 milliseconds. Consequenly, the last added sample to the motion event has an
+ * event time of ~11 milliseconds. Note that there are specific scenarios where resampleMotionEvent
+ * is not called with a multiple of ~16 milliseconds. These cases are primarily for data addition
+ * or to test other functionalities of the resampler.
+ *
+ * Coordinates are calculated using linear interpolation (lerp) based on the last two available
+ * samples. Linear interpolation is defined as (a + alpha*(b - a)). Let t_b and t_a be the
+ * timestamps of samples a and b, respectively. The interpolation factor alpha is calculated as
+ * (resampleTime - t_a) / (t_b - t_a). The value of alpha determines whether the resampled
+ * coordinates are interpolated or extrapolated. If alpha falls within the semi-closed interval [0,
+ * 1), the coordinates are interpolated. If alpha is greater than or equal to 1, the coordinates are
+ * extrapolated.
+ *
+ * The timeline below depics an interpolation scenario
+ * -----------------------------------|---------|---------|---------|----------
+ * 10ms 11ms 15ms 16ms
+ * MOVE | MOVE |
+ * resampleTime frameTime
+ * Based on the timeline alpha is (11 - 10)/(15 - 10) = 1/5. Thus, coordinates are interpolated.
+ *
+ * The following timeline portrays an extrapolation scenario
+ * -------------------------|---------|---------|-------------------|----------
+ * 5ms 10ms 11ms 16ms
+ * MOVE MOVE | |
+ * resampleTime frameTime
+ * Likewise, alpha = (11 - 5)/(10 - 5) = 6/5. Hence, coordinates are extrapolated.
+ *
+ * If a motion event was resampled, the tests will check that the following conditions are satisfied
+ * to guarantee resampling correctness:
+ * - The motion event metadata must not change.
+ * - The number of samples in the motion event must only increment by 1.
+ * - The resampled values must be at the end of motion event coordinates.
+ * - The rasamples values must be near the hand calculations.
+ * - The resampled time must be the most recent one in motion event.
+ */
class ResamplerTest : public testing::Test {
protected:
ResamplerTest() : mResampler(std::make_unique<LegacyResampler>()) {}
@@ -225,7 +266,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
+ mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
EXPECT_EQ(motionEvent.getTouchMajor(0), TOUCH_MAJOR_VALUE);
@@ -243,7 +284,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr);
+ mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr);
assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
}
@@ -270,23 +311,6 @@
assertMotionEventIsNotResampled(originalMotionEvent, motionFromSecondDevice);
}
-// Increments of 16 ms for display refresh rate
-// Increments of 6 ms for input frequency
-// Resampling latency is known to be 5 ms
-// Therefore, first resampling time will be 11 ms
-
-/**
- * Timeline
- * ----+----------------------+---------+---------+---------+----------
- * 0ms 10ms 11ms 15ms 16ms
- * DOWN MOVE | MSG |
- * resample frame
- * Resampling occurs at 11ms. It is possible to interpolate because there is a sample available
- * after the resample time. It is assumed that the InputMessage frequency is 100Hz, and the frame
- * frequency is 60Hz. This means the time between InputMessage samples is 10ms, and the time between
- * frames is ~16ms. Resample time is frameTime - RESAMPLE_LATENCY. The resampled sample must be the
- * last one in the batch to consume.
- */
TEST_F(ResamplerTest, SinglePointerSingleSampleInterpolation) {
MotionEvent motionEvent =
InputStream{{InputSample{10ms,
@@ -297,7 +321,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
+ mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
{Pointer{.id = 0,
@@ -338,18 +362,13 @@
const MotionEvent originalMotionEvent = secondMotionEvent;
- mResampler->resampleMotionEvent(11ms, secondMotionEvent, nullptr);
+ mResampler->resampleMotionEvent(16ms, secondMotionEvent, nullptr);
assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, secondMotionEvent,
{Pointer{.id = 0,
.x = 2.2f,
.y = 4.4f,
.isResampled = true}});
- // Integrity of the whole motionEvent
- // History size should increment by 1
- // Check if the resampled value is the last one
- // Check if the resampleTime is correct
- // Check if the PointerCoords are consistent with the other computations
}
TEST_F(ResamplerTest, SinglePointerMultipleSampleInterpolation) {
@@ -364,7 +383,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
+ mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
{Pointer{.id = 0,
@@ -382,7 +401,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, nullptr);
+ mResampler->resampleMotionEvent(16ms, motionEvent, nullptr);
assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
{Pointer{.id = 0,
@@ -400,7 +419,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, nullptr);
+ mResampler->resampleMotionEvent(16ms, motionEvent, nullptr);
assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
}
@@ -414,7 +433,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(27ms, motionEvent, nullptr);
+ mResampler->resampleMotionEvent(32ms, motionEvent, nullptr);
assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
}
@@ -428,7 +447,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(43ms, motionEvent, nullptr);
+ mResampler->resampleMotionEvent(48ms, motionEvent, nullptr);
assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
{Pointer{.id = 0,
@@ -451,7 +470,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
+ mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
{Pointer{.x = 2.2f, .y = 2.2f, .isResampled = true},
@@ -475,7 +494,7 @@
const MotionEvent originalMotionEvent = secondMotionEvent;
- mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
+ mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, secondMotionEvent,
{Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
@@ -498,7 +517,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
+ mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
{Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
@@ -517,7 +536,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr);
+ mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr);
assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
{Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
@@ -539,7 +558,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
+ mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
{Pointer{.x = 1.4f, .y = 1.4f, .isResampled = true},
@@ -560,7 +579,7 @@
const MotionEvent originalSecondMotionEvent = secondMotionEvent;
- mResampler->resampleMotionEvent(27ms, secondMotionEvent, &secondFutureSample);
+ mResampler->resampleMotionEvent(32ms, secondMotionEvent, &secondFutureSample);
assertMotionEventIsResampledAndCoordsNear(originalSecondMotionEvent, secondMotionEvent,
{Pointer{.x = 3.8f, .y = 3.8f, .isResampled = true},
@@ -586,7 +605,7 @@
const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
- mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
+ mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
}
@@ -606,7 +625,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
+ mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
}
@@ -629,7 +648,7 @@
const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
- mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
+ mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
assertMotionEventIsResampledAndCoordsNear(secondOriginalMotionEvent, secondMotionEvent,
{Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
@@ -650,7 +669,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
+ mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
}
@@ -672,7 +691,7 @@
const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
- mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
+ mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
}
@@ -691,7 +710,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
+ mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
}
@@ -713,7 +732,7 @@
const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
- mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
+ mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
}
@@ -746,7 +765,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
+ mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
}
@@ -782,7 +801,7 @@
const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
- mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
+ mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
}
@@ -815,7 +834,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr);
+ mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr);
assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
}
@@ -847,7 +866,7 @@
const MotionEvent originalMotionEvent = motionEvent;
- mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr);
+ mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr);
assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
}
diff --git a/services/gpuservice/vts/TEST_MAPPING b/services/gpuservice/vts/TEST_MAPPING
index b33e962..a809be1 100644
--- a/services/gpuservice/vts/TEST_MAPPING
+++ b/services/gpuservice/vts/TEST_MAPPING
@@ -1,7 +1,13 @@
{
"presubmit": [
{
- "name": "GpuServiceVendorTests"
+ "name": "GpuServiceVendorTests",
+ "options": [
+ {
+ // Exclude test methods that require a physical device to run.
+ "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
+ }
+ ]
}
]
}
diff --git a/services/gpuservice/vts/src/com/android/tests/gpuservice/GpuWorkTracepointTest.java b/services/gpuservice/vts/src/com/android/tests/gpuservice/GpuWorkTracepointTest.java
index 6c16335..5c12323 100644
--- a/services/gpuservice/vts/src/com/android/tests/gpuservice/GpuWorkTracepointTest.java
+++ b/services/gpuservice/vts/src/com/android/tests/gpuservice/GpuWorkTracepointTest.java
@@ -19,7 +19,7 @@
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
-import android.platform.test.annotations.RestrictedBuildTest;
+import android.platform.test.annotations.RequiresDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -63,7 +63,7 @@
}
@VsrTest(requirements={"VSR-3.3-004"})
- @RestrictedBuildTest
+ @RequiresDevice
@Test
public void testGpuWorkPeriodTracepointFormat() throws Exception {
CommandResult commandResult = getDevice().executeShellV2Command(
diff --git a/services/inputflinger/TEST_MAPPING b/services/inputflinger/TEST_MAPPING
index af9d2eb..10fec74 100644
--- a/services/inputflinger/TEST_MAPPING
+++ b/services/inputflinger/TEST_MAPPING
@@ -298,9 +298,14 @@
"name": "CtsInputRootTestCases"
}
],
- "staged-platinum-postsubmit": [
+ "platinum-postsubmit": [
{
"name": "inputflinger_tests"
}
+ ],
+ "staged-platinum-postsubmit": [
+ {
+ "name": "libinput_tests"
+ }
]
}
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 7bec94e..69874c9 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -466,6 +466,9 @@
virtual void notifyTouchpadHardwareState(const SelfContainedHardwareState& schs,
int32_t deviceId) = 0;
+ /* Sends the Info of gestures that happen on the touchpad. */
+ virtual void notifyTouchpadGestureInfo(GestureType type, int32_t deviceId) = 0;
+
/* Gets the keyboard layout for a particular input device. */
virtual std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier& identifier,
diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
index c8e7790..dd46bbc 100644
--- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
+++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
@@ -20,14 +20,19 @@
#include <sstream>
#include <android-base/stringprintf.h>
+#include <com_android_input_flags.h>
#include <input/PrintTools.h>
#include <linux/input-event-codes.h>
#include <log/log_main.h>
+namespace input_flags = com::android::input::flags;
+
namespace android {
namespace {
+static constexpr uint32_t SOURCE = AINPUT_SOURCE_TOUCHPAD;
+
int32_t actionWithIndex(int32_t action, int32_t index) {
return action | (index << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
}
@@ -43,6 +48,12 @@
return i;
}
+void addRawMotionRange(InputDeviceInfo& deviceInfo, int32_t androidAxis,
+ RawAbsoluteAxisInfo& evdevAxis) {
+ deviceInfo.addMotionRange(androidAxis, SOURCE, evdevAxis.minValue, evdevAxis.maxValue,
+ evdevAxis.flat, evdevAxis.fuzz, evdevAxis.resolution);
+}
+
} // namespace
CapturedTouchpadEventConverter::CapturedTouchpadEventConverter(
@@ -108,8 +119,15 @@
}
void CapturedTouchpadEventConverter::populateMotionRanges(InputDeviceInfo& info) const {
- tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_X, ABS_MT_POSITION_X);
- tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_Y, ABS_MT_POSITION_Y);
+ if (input_flags::include_relative_axis_values_for_captured_touchpads()) {
+ tryAddRawMotionRangeWithRelative(/*byref*/ info, AMOTION_EVENT_AXIS_X,
+ AMOTION_EVENT_AXIS_RELATIVE_X, ABS_MT_POSITION_X);
+ tryAddRawMotionRangeWithRelative(/*byref*/ info, AMOTION_EVENT_AXIS_Y,
+ AMOTION_EVENT_AXIS_RELATIVE_Y, ABS_MT_POSITION_Y);
+ } else {
+ tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_X, ABS_MT_POSITION_X);
+ tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_Y, ABS_MT_POSITION_Y);
+ }
tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOUCH_MAJOR, ABS_MT_TOUCH_MAJOR);
tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOUCH_MINOR, ABS_MT_TOUCH_MINOR);
tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOOL_MAJOR, ABS_MT_WIDTH_MAJOR);
@@ -135,8 +153,23 @@
int32_t evdevAxis) const {
std::optional<RawAbsoluteAxisInfo> info = mDeviceContext.getAbsoluteAxisInfo(evdevAxis);
if (info) {
- deviceInfo.addMotionRange(androidAxis, SOURCE, info->minValue, info->maxValue, info->flat,
- info->fuzz, info->resolution);
+ addRawMotionRange(/*byref*/ deviceInfo, androidAxis, *info);
+ }
+}
+
+void CapturedTouchpadEventConverter::tryAddRawMotionRangeWithRelative(InputDeviceInfo& deviceInfo,
+ int32_t androidAxis,
+ int32_t androidRelativeAxis,
+ int32_t evdevAxis) const {
+ std::optional<RawAbsoluteAxisInfo> axisInfo = mDeviceContext.getAbsoluteAxisInfo(evdevAxis);
+ if (axisInfo) {
+ addRawMotionRange(/*byref*/ deviceInfo, androidAxis, *axisInfo);
+
+ // The largest movement we could possibly report on a relative axis is from the minimum to
+ // the maximum (or vice versa) of the absolute axis.
+ float range = axisInfo->maxValue - axisInfo->minValue;
+ deviceInfo.addMotionRange(androidRelativeAxis, SOURCE, -range, range, axisInfo->flat,
+ axisInfo->fuzz, axisInfo->resolution);
}
}
@@ -163,7 +196,7 @@
std::list<NotifyArgs> out;
std::vector<PointerCoords> coords;
std::vector<PointerProperties> properties;
- std::map<size_t, size_t> coordsIndexForSlotNumber;
+ std::map<size_t /*slotNumber*/, size_t /*coordsIndex*/> coordsIndexForSlotNumber;
// For all the touches that were already down, send a MOVE event with their updated coordinates.
// A convention of the MotionEvent API is that pointer coordinates in UP events match the
@@ -175,11 +208,19 @@
// to stay perfectly still between frames, and if it does the worst that can happen is
// an extra MOVE event, so it's not worth the overhead of checking for changes.
coordsIndexForSlotNumber[slotNumber] = coords.size();
- coords.push_back(makePointerCoordsForSlot(mMotionAccumulator.getSlot(slotNumber)));
+ coords.push_back(makePointerCoordsForSlot(slotNumber));
properties.push_back({.id = pointerId, .toolType = ToolType::FINGER});
}
out.push_back(
makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_MOVE, coords, properties));
+ if (input_flags::include_relative_axis_values_for_captured_touchpads()) {
+ // For any further events we send from this sync, the pointers won't have moved relative
+ // to the positions we just reported in this MOVE event, so zero out the relative axes.
+ for (PointerCoords& pointer : coords) {
+ pointer.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0);
+ pointer.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0);
+ }
+ }
}
std::vector<size_t> upSlots, downSlots;
@@ -234,6 +275,9 @@
/*flags=*/cancel ? AMOTION_EVENT_FLAG_CANCELED : 0));
freePointerIdForSlot(slotNumber);
+ if (input_flags::include_relative_axis_values_for_captured_touchpads()) {
+ mPreviousCoordsForSlotNumber.erase(slotNumber);
+ }
coords.erase(coords.begin() + indexToRemove);
properties.erase(properties.begin() + indexToRemove);
// Now that we've removed some coords and properties, we might have to update the slot
@@ -254,7 +298,7 @@
: actionWithIndex(AMOTION_EVENT_ACTION_POINTER_DOWN, coordsIndex);
coordsIndexForSlotNumber[slotNumber] = coordsIndex;
- coords.push_back(makePointerCoordsForSlot(mMotionAccumulator.getSlot(slotNumber)));
+ coords.push_back(makePointerCoordsForSlot(slotNumber));
properties.push_back(
{.id = allocatePointerIdToSlot(slotNumber), .toolType = ToolType::FINGER});
@@ -286,12 +330,22 @@
AMOTION_EVENT_INVALID_CURSOR_POSITION, mDownTime, /*videoFrames=*/{});
}
-PointerCoords CapturedTouchpadEventConverter::makePointerCoordsForSlot(
- const MultiTouchMotionAccumulator::Slot& slot) const {
+PointerCoords CapturedTouchpadEventConverter::makePointerCoordsForSlot(size_t slotNumber) {
+ const MultiTouchMotionAccumulator::Slot& slot = mMotionAccumulator.getSlot(slotNumber);
PointerCoords coords;
coords.clear();
coords.setAxisValue(AMOTION_EVENT_AXIS_X, slot.getX());
coords.setAxisValue(AMOTION_EVENT_AXIS_Y, slot.getY());
+ if (input_flags::include_relative_axis_values_for_captured_touchpads()) {
+ if (auto it = mPreviousCoordsForSlotNumber.find(slotNumber);
+ it != mPreviousCoordsForSlotNumber.end()) {
+ auto [oldX, oldY] = it->second;
+ coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, slot.getX() - oldX);
+ coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, slot.getY() - oldY);
+ }
+ mPreviousCoordsForSlotNumber[slotNumber] = std::make_pair(slot.getX(), slot.getY());
+ }
+
coords.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, slot.getTouchMajor());
coords.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, slot.getTouchMinor());
coords.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, slot.getToolMajor());
diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.h b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.h
index 9b6df7a..d6c0708 100644
--- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.h
+++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.h
@@ -21,6 +21,7 @@
#include <map>
#include <set>
#include <string>
+#include <utility>
#include <vector>
#include <android/input.h>
@@ -49,12 +50,14 @@
private:
void tryAddRawMotionRange(InputDeviceInfo& deviceInfo, int32_t androidAxis,
int32_t evdevAxis) const;
+ void tryAddRawMotionRangeWithRelative(InputDeviceInfo& deviceInfo, int32_t androidAxis,
+ int32_t androidRelativeAxis, int32_t evdevAxis) const;
[[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when, nsecs_t readTime);
[[nodiscard]] NotifyMotionArgs makeMotionArgs(nsecs_t when, nsecs_t readTime, int32_t action,
const std::vector<PointerCoords>& coords,
const std::vector<PointerProperties>& properties,
int32_t actionButton = 0, int32_t flags = 0);
- PointerCoords makePointerCoordsForSlot(const MultiTouchMotionAccumulator::Slot& slot) const;
+ PointerCoords makePointerCoordsForSlot(size_t slotNumber);
int32_t allocatePointerIdToSlot(size_t slotNumber);
void freePointerIdForSlot(size_t slotNumber);
@@ -76,8 +79,7 @@
std::bitset<MAX_POINTER_ID + 1> mPointerIdsInUse;
std::map<size_t, int32_t> mPointerIdForSlotNumber;
-
- static constexpr uint32_t SOURCE = AINPUT_SOURCE_TOUCHPAD;
+ std::map<size_t, std::pair<float, float>> mPreviousCoordsForSlotNumber;
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index b17e79a..9a36bfb 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -480,6 +480,9 @@
return;
}
mGesturesToProcess.push_back(*gesture);
+ if (mTouchpadHardwareStateNotificationsEnabled) {
+ getPolicy()->notifyTouchpadGestureInfo(gesture->type, getDeviceId());
+ }
}
std::list<NotifyArgs> TouchpadInputMapper::processGestures(nsecs_t when, nsecs_t readTime) {
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 95283ba..744cf4a 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -123,4 +123,5 @@
"device-tests",
"device-platinum-tests",
],
+ native_coverage: false,
}
diff --git a/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp b/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp
index f20c43c..353011a 100644
--- a/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp
+++ b/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp
@@ -20,6 +20,7 @@
#include <memory>
#include <EventHub.h>
+#include <com_android_input_flags.h>
#include <gtest/gtest.h>
#include <linux/input-event-codes.h>
#include <linux/input.h>
@@ -32,6 +33,8 @@
#include "TestEventMatchers.h"
#include "TestInputListener.h"
+namespace input_flags = com::android::input::flags;
+
namespace android {
using testing::AllOf;
@@ -47,6 +50,8 @@
mReader(mFakeEventHub, mFakePolicy, mFakeListener),
mDevice(newDevice()),
mDeviceContext(*mDevice, EVENTHUB_ID) {
+ input_flags::include_relative_axis_values_for_captured_touchpads(true);
+
const size_t slotCount = 8;
mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, 0, slotCount - 1, 0, 0, 0);
mAccumulator.configure(mDeviceContext, slotCount, /*usingSlotsProtocol=*/true);
@@ -126,7 +131,7 @@
TEST_F(CapturedTouchpadEventConverterTest, MotionRanges_allAxesPresent_populatedCorrectly) {
mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, 0, 4000, 0, 0, 45);
- mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, 0, 2500, 0, 0, 40);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, -500, 2000, 0, 0, 40);
mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, 0, 1100, 0, 0, 35);
mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, 0, 1000, 0, 0, 30);
mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, 0, 900, 0, 0, 25);
@@ -150,8 +155,8 @@
const InputDeviceInfo::MotionRange* posY =
info.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHPAD);
ASSERT_NE(nullptr, posY);
- EXPECT_NEAR(0, posY->min, EPSILON);
- EXPECT_NEAR(2500, posY->max, EPSILON);
+ EXPECT_NEAR(-500, posY->min, EPSILON);
+ EXPECT_NEAR(2000, posY->max, EPSILON);
EXPECT_NEAR(40, posY->resolution, EPSILON);
const InputDeviceInfo::MotionRange* touchMajor =
@@ -182,8 +187,22 @@
EXPECT_NEAR(800, toolMinor->max, EPSILON);
EXPECT_NEAR(20, toolMinor->resolution, EPSILON);
- // ...except orientation and pressure, which get scaled, and size, which is generated from other
- // values.
+ // ...except for the relative motion axes, derived from the corresponding absolute ones:
+ const InputDeviceInfo::MotionRange* relX =
+ info.getMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, AINPUT_SOURCE_TOUCHPAD);
+ ASSERT_NE(nullptr, relX);
+ EXPECT_NEAR(-4000, relX->min, EPSILON);
+ EXPECT_NEAR(4000, relX->max, EPSILON);
+ EXPECT_NEAR(45, relX->resolution, EPSILON);
+
+ const InputDeviceInfo::MotionRange* relY =
+ info.getMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, AINPUT_SOURCE_TOUCHPAD);
+ ASSERT_NE(nullptr, relY);
+ EXPECT_NEAR(-2500, relY->min, EPSILON);
+ EXPECT_NEAR(2500, relY->max, EPSILON);
+ EXPECT_NEAR(40, relY->resolution, EPSILON);
+
+ // ...orientation and pressure, which get scaled:
const InputDeviceInfo::MotionRange* orientation =
info.getMotionRange(AMOTION_EVENT_AXIS_ORIENTATION, AINPUT_SOURCE_TOUCHPAD);
ASSERT_NE(nullptr, orientation);
@@ -198,6 +217,7 @@
EXPECT_NEAR(1, pressure->max, EPSILON);
EXPECT_NEAR(0, pressure->resolution, EPSILON);
+ // ... and size, which is generated from other values.
const InputDeviceInfo::MotionRange* size =
info.getMotionRange(AMOTION_EVENT_AXIS_SIZE, AINPUT_SOURCE_TOUCHPAD);
ASSERT_NE(nullptr, size);
@@ -219,7 +239,9 @@
// present, since it's generated from axes that aren't provided by this device).
EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHPAD));
EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHPAD));
- EXPECT_EQ(2u, info.getMotionRanges().size());
+ EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, AINPUT_SOURCE_TOUCHPAD));
+ EXPECT_NE(nullptr, info.getMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, AINPUT_SOURCE_TOUCHPAD));
+ EXPECT_EQ(4u, info.getMotionRanges().size());
}
TEST_F(CapturedTouchpadEventConverterTest, OneFinger_motionReportedCorrectly) {
@@ -235,14 +257,16 @@
EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
- WithCoords(50, 100), WithToolType(ToolType::FINGER)));
+ WithCoords(50, 100), WithRelativeMotion(0, 0),
+ WithToolType(ToolType::FINGER)));
processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 99);
EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
- WithCoords(52, 99), WithToolType(ToolType::FINGER)));
+ WithCoords(52, 99), WithRelativeMotion(2, -1),
+ WithToolType(ToolType::FINGER)));
processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
processAxis(conv, EV_KEY, BTN_TOUCH, 0);
@@ -255,8 +279,9 @@
VariantWith<NotifyMotionArgs>(
WithMotionAction(AMOTION_EVENT_ACTION_UP))));
EXPECT_THAT(args,
- Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(52, 99), WithPointerCount(1u),
- WithToolType(ToolType::FINGER)))));
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithCoords(52, 99), WithRelativeMotion(0, 0), WithPointerCount(1u),
+ WithToolType(ToolType::FINGER)))));
}
TEST_F(CapturedTouchpadEventConverterTest, OneFinger_touchDimensionsPassedThrough) {
@@ -507,13 +532,13 @@
EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
- WithCoords(51, 100)));
+ WithCoords(51, 100), WithRelativeMotion(0, 0)));
processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
- WithCoords(52, 100)));
+ WithCoords(52, 100), WithRelativeMotion(1, 0)));
}
TEST_F(CapturedTouchpadEventConverterTest, FingerArrivingAfterPalm_onlyFingerReported) {
@@ -553,7 +578,7 @@
EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
- WithCoords(98, 148)));
+ WithCoords(98, 148), WithRelativeMotion(-2, -2)));
}
TEST_F(CapturedTouchpadEventConverterTest, FingerAndFingerTurningIntoPalm_partiallyCancelled) {
@@ -660,7 +685,8 @@
EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
- WithCoords(50, 100), WithToolType(ToolType::FINGER)));
+ WithCoords(50, 100), WithRelativeMotion(0, 0),
+ WithToolType(ToolType::FINGER)));
processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 52);
@@ -678,13 +704,16 @@
ElementsAre(VariantWith<NotifyMotionArgs>(
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
WithPointerCount(1u), WithCoords(52, 99),
+ WithRelativeMotion(2, -1),
WithToolType(ToolType::FINGER))),
VariantWith<NotifyMotionArgs>(
AllOf(WithMotionAction(
AMOTION_EVENT_ACTION_POINTER_DOWN |
1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
WithPointerCount(2u), WithPointerCoords(0, 52, 99),
+ WithPointerRelativeMotion(0, 0, 0),
WithPointerCoords(1, 250, 200),
+ WithPointerRelativeMotion(1, 0, 0),
WithPointerToolType(0, ToolType::FINGER),
WithPointerToolType(1, ToolType::FINGER)))));
@@ -700,14 +729,17 @@
std::list<NotifyArgs> args = processSync(conv);
EXPECT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
- WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
- VariantWith<NotifyMotionArgs>(WithMotionAction(
- AMOTION_EVENT_ACTION_POINTER_UP |
- 0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT))));
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
+ WithPointerRelativeMotion(1, 5, 2))),
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(
+ AMOTION_EVENT_ACTION_POINTER_UP |
+ 0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ WithPointerRelativeMotion(1, 0, 0)))));
EXPECT_THAT(args,
Each(VariantWith<NotifyMotionArgs>(
AllOf(WithPointerCount(2u), WithPointerCoords(0, 52, 99),
- WithPointerCoords(1, 255, 202),
+ WithPointerRelativeMotion(0, 0, 0), WithPointerCoords(1, 255, 202),
WithPointerToolType(1, ToolType::FINGER),
WithPointerToolType(0, ToolType::FINGER)))));
@@ -723,9 +755,69 @@
WithMotionAction(AMOTION_EVENT_ACTION_UP))));
EXPECT_THAT(args,
Each(VariantWith<NotifyMotionArgs>(AllOf(WithPointerCount(1u), WithCoords(255, 202),
+ WithRelativeMotion(0, 0),
WithToolType(ToolType::FINGER)))));
}
+TEST_F(CapturedTouchpadEventConverterTest, RelativeMotionAxesClearedForNewFingerInSlot) {
+ CapturedTouchpadEventConverter conv = createConverter();
+ // Put down one finger.
+ processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
+ processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
+
+ processAxis(conv, EV_KEY, BTN_TOUCH, 1);
+ processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
+
+ EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
+ WithCoords(50, 100), WithRelativeMotion(0, 0)));
+
+ // Move it in negative X and Y directions.
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 47);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 97);
+
+ EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithCoords(47, 97),
+ WithRelativeMotion(-3, -3)));
+
+ // Lift it.
+ processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
+ processAxis(conv, EV_KEY, BTN_TOUCH, 0);
+ processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
+
+ std::list<NotifyArgs> args = processSync(conv);
+ EXPECT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE)),
+ VariantWith<NotifyMotionArgs>(
+ WithMotionAction(AMOTION_EVENT_ACTION_UP))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(AllOf(WithCoords(47, 97),
+ WithRelativeMotion(0, 0),
+ WithPointerCount(1u)))));
+
+ // Put down another finger using the same slot. Relative axis values should be cleared.
+ processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 2);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 60);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 60);
+
+ processAxis(conv, EV_KEY, BTN_TOUCH, 1);
+ processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
+
+ EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPointerCount(1u),
+ WithCoords(60, 60), WithRelativeMotion(0, 0)));
+
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 64);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 58);
+
+ EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithPointerCount(1u),
+ WithCoords(64, 58), WithRelativeMotion(4, -2)));
+}
+
// Pointer IDs max out at 31, and so must be reused once a touch is lifted to avoid running out.
TEST_F(CapturedTouchpadEventConverterTest, PointerIdsReusedAfterLift) {
CapturedTouchpadEventConverter conv = createConverter();
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
index e1f844c..f373cac 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
@@ -256,6 +256,10 @@
mTouchpadHardwareStateNotified.notify_all();
}
+void FakeInputReaderPolicy::notifyTouchpadGestureInfo(GestureType type, int32_t deviceId) {
+ std::scoped_lock lock(mLock);
+}
+
std::shared_ptr<KeyCharacterMap> FakeInputReaderPolicy::getKeyboardLayoutOverlay(
const InputDeviceIdentifier&, const std::optional<KeyboardLayoutInfo>) {
return nullptr;
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.h b/services/inputflinger/tests/FakeInputReaderPolicy.h
index 61bb9fc..3a2b4e9 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.h
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.h
@@ -85,6 +85,7 @@
void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override;
void notifyTouchpadHardwareState(const SelfContainedHardwareState& schs,
int32_t deviceId) override;
+ void notifyTouchpadGestureInfo(GestureType type, int32_t deviceId) override;
std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier&, const std::optional<KeyboardLayoutInfo>) override;
std::string getDeviceAlias(const InputDeviceIdentifier&) override;
diff --git a/services/inputflinger/tests/TestEventMatchers.h b/services/inputflinger/tests/TestEventMatchers.h
index cfedc6e..6fa3365 100644
--- a/services/inputflinger/tests/TestEventMatchers.h
+++ b/services/inputflinger/tests/TestEventMatchers.h
@@ -615,7 +615,12 @@
explicit WithPointerIdMatcher(size_t index, int32_t pointerId)
: mIndex(index), mPointerId(pointerId) {}
- bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
+ bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream* os) const {
+ if (mIndex >= args.pointerCoords.size()) {
+ *os << "Pointer index " << mIndex << " is out of bounds";
+ return false;
+ }
+
return args.pointerProperties[mIndex].id == mPointerId;
}
@@ -646,12 +651,51 @@
return (isnan(x) ? isnan(argX) : x == argX) && (isnan(y) ? isnan(argY) : y == argY);
}
-MATCHER_P2(WithRelativeMotion, x, y, "InputEvent with specified relative motion") {
- const auto argX = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
- const auto argY = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
- *result_listener << "expected relative motion (" << x << ", " << y << "), but got (" << argX
- << ", " << argY << ")";
- return argX == x && argY == y;
+/// Relative motion matcher
+class WithRelativeMotionMatcher {
+public:
+ using is_gtest_matcher = void;
+ explicit WithRelativeMotionMatcher(size_t pointerIndex, float relX, float relY)
+ : mPointerIndex(pointerIndex), mRelX(relX), mRelY(relY) {}
+
+ bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
+ if (mPointerIndex >= event.pointerCoords.size()) {
+ *os << "Pointer index " << mPointerIndex << " is out of bounds";
+ return false;
+ }
+
+ const PointerCoords& coords = event.pointerCoords[mPointerIndex];
+ bool matches = mRelX == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X) &&
+ mRelY == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
+ if (!matches) {
+ *os << "expected relative motion (" << mRelX << ", " << mRelY << ") at pointer index "
+ << mPointerIndex << ", but got ("
+ << coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X) << ", "
+ << coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y) << ")";
+ }
+ return matches;
+ }
+
+ void DescribeTo(std::ostream* os) const {
+ *os << "with relative motion (" << mRelX << ", " << mRelY << ") at pointer index "
+ << mPointerIndex;
+ }
+
+ void DescribeNegationTo(std::ostream* os) const { *os << "wrong relative motion"; }
+
+private:
+ const size_t mPointerIndex;
+ const float mRelX;
+ const float mRelY;
+};
+
+inline WithRelativeMotionMatcher WithRelativeMotion(float relX, float relY) {
+ return WithRelativeMotionMatcher(0, relX, relY);
+}
+
+inline WithRelativeMotionMatcher WithPointerRelativeMotion(size_t pointerIndex, float relX,
+ float relY) {
+ return WithRelativeMotionMatcher(pointerIndex, relX, relY);
}
MATCHER_P3(WithGestureOffset, dx, dy, epsilon,
@@ -758,10 +802,14 @@
return argToolType == toolType;
}
-MATCHER_P2(WithPointerToolType, pointer, toolType,
+MATCHER_P2(WithPointerToolType, pointerIndex, toolType,
"InputEvent with specified tool type for pointer") {
- const auto argToolType = arg.pointerProperties[pointer].toolType;
- *result_listener << "expected pointer " << pointer << " to have tool type "
+ if (std::cmp_greater_equal(pointerIndex, arg.getPointerCount())) {
+ *result_listener << "Pointer index " << pointerIndex << " is out of bounds";
+ return false;
+ }
+ const auto argToolType = arg.pointerProperties[pointerIndex].toolType;
+ *result_listener << "expected pointer " << pointerIndex << " to have tool type "
<< ftl::enum_string(toolType) << ", but got " << ftl::enum_string(argToolType);
return argToolType == toolType;
}
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index ddc3310..7e362f4 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -283,6 +283,7 @@
void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {}
void notifyTouchpadHardwareState(const SelfContainedHardwareState& schs,
int32_t deviceId) override {}
+ void notifyTouchpadGestureInfo(GestureType type, int32_t deviceId) override {}
std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier& identifier,
const std::optional<KeyboardLayoutInfo> layoutInfo) override {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index bd093f5..d08e261 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -305,7 +305,7 @@
// The logic here checks if hwc was able to provide some dpi, and if so if the dpi
// disparity between the axes is more reasonable than a rough estimate, otherwise use
// the estimated dpi as a corrected value.
- if (estimatedDpi.x == -1 || estimatedDpi.x == -1) {
+ if (estimatedDpi.x == -1 || estimatedDpi.y == -1) {
return dpi;
}
if (dpi.x == -1 || dpi.y == -1) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index be00079..5e13154 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -38,7 +38,6 @@
#include <FrameTimeline/FrameTimeline.h>
#include <scheduler/interface/ICompositor.h>
-#include <algorithm>
#include <cinttypes>
#include <cstdint>
#include <functional>
@@ -46,16 +45,15 @@
#include <numeric>
#include <common/FlagManager.h>
-#include "../Layer.h"
#include "EventThread.h"
#include "FrameRateOverrideMappings.h"
#include "FrontEnd/LayerHandle.h"
+#include "Layer.h"
#include "OneShotTimer.h"
#include "RefreshRateStats.h"
#include "SurfaceFlingerFactory.h"
#include "SurfaceFlingerProperties.h"
#include "TimeStats/TimeStats.h"
-#include "VSyncTracker.h"
#include "VsyncConfiguration.h"
#include "VsyncController.h"
#include "VsyncSchedule.h"
@@ -361,10 +359,8 @@
if (cycle == Cycle::Render) {
mRenderEventThread = std::move(eventThread);
- mRenderEventConnection = mRenderEventThread->createEventConnection();
} else {
mLastCompositeEventThread = std::move(eventThread);
- mLastCompositeEventConnection = mLastCompositeEventThread->createEventConnection();
}
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 1367ec3..c88b563 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -145,10 +145,6 @@
Cycle, EventRegistrationFlags eventRegistration = {},
const sp<IBinder>& layerHandle = nullptr) EXCLUDES(mChoreographerLock);
- const sp<EventThreadConnection>& getEventConnection(Cycle cycle) const {
- return cycle == Cycle::Render ? mRenderEventConnection : mLastCompositeEventConnection;
- }
-
enum class Hotplug { Connected, Disconnected };
void dispatchHotplug(PhysicalDisplayId, Hotplug);
@@ -467,10 +463,7 @@
void onExpectedPresentTimePosted(TimePoint expectedPresentTime) override EXCLUDES(mDisplayLock);
std::unique_ptr<EventThread> mRenderEventThread;
- sp<EventThreadConnection> mRenderEventConnection;
-
std::unique_ptr<EventThread> mLastCompositeEventThread;
- sp<EventThreadConnection> mLastCompositeEventConnection;
std::atomic<nsecs_t> mLastResyncTime = 0;
diff --git a/services/surfaceflinger/Scheduler/VsyncModulator.cpp b/services/surfaceflinger/Scheduler/VsyncModulator.cpp
index fa377e9..3c5f68c 100644
--- a/services/surfaceflinger/Scheduler/VsyncModulator.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncModulator.cpp
@@ -21,7 +21,6 @@
#include "VsyncModulator.h"
-#include <android-base/properties.h>
#include <common/trace.h>
#include <log/log.h>
@@ -37,8 +36,7 @@
VsyncModulator::VsyncModulator(const VsyncConfigSet& config, Now now)
: mVsyncConfigSet(config),
- mNow(now),
- mTraceDetailedInfo(base::GetBoolProperty("debug.sf.vsync_trace_detailed_info", false)) {}
+ mNow(now) {}
VsyncConfig VsyncModulator::setVsyncConfigSet(const VsyncConfigSet& config) {
std::lock_guard<std::mutex> lock(mMutex);
@@ -71,10 +69,6 @@
break;
}
- if (mTraceDetailedInfo) {
- SFTRACE_INT("mEarlyWakeup", static_cast<int>(mEarlyWakeupRequests.size()));
- }
-
if (mEarlyWakeupRequests.empty() && schedule == Schedule::EarlyEnd) {
mEarlyTransactionFrames = MIN_EARLY_TRANSACTION_FRAMES;
mEarlyTransactionStartTime = mNow();
@@ -167,15 +161,19 @@
const VsyncConfig& offsets = getNextVsyncConfig();
mVsyncConfig = offsets;
- if (mTraceDetailedInfo) {
- const bool isEarly = &offsets == &mVsyncConfigSet.early;
- const bool isEarlyGpu = &offsets == &mVsyncConfigSet.earlyGpu;
- const bool isLate = &offsets == &mVsyncConfigSet.late;
+ // Trace config type
+ SFTRACE_INT("Vsync-Early", &mVsyncConfig == &mVsyncConfigSet.early);
+ SFTRACE_INT("Vsync-EarlyGpu", &mVsyncConfig == &mVsyncConfigSet.earlyGpu);
+ SFTRACE_INT("Vsync-Late", &mVsyncConfig == &mVsyncConfigSet.late);
- SFTRACE_INT("Vsync-EarlyOffsetsOn", isEarly);
- SFTRACE_INT("Vsync-EarlyGpuOffsetsOn", isEarlyGpu);
- SFTRACE_INT("Vsync-LateOffsetsOn", isLate);
- }
+ // Trace early vsync conditions
+ SFTRACE_INT("EarlyWakeupRequests",
+ static_cast<int>(mEarlyWakeupRequests.size()));
+ SFTRACE_INT("EarlyTransactionFrames", mEarlyTransactionFrames);
+ SFTRACE_INT("RefreshRateChangePending", mRefreshRateChangePending);
+
+ // Trace early gpu conditions
+ SFTRACE_INT("EarlyGpuFrames", mEarlyGpuFrames);
return offsets;
}
@@ -183,7 +181,6 @@
void VsyncModulator::binderDied(const wp<IBinder>& who) {
std::lock_guard<std::mutex> lock(mMutex);
mEarlyWakeupRequests.erase(who);
-
static_cast<void>(updateVsyncConfigLocked());
}
diff --git a/services/surfaceflinger/Scheduler/VsyncModulator.h b/services/surfaceflinger/Scheduler/VsyncModulator.h
index be0d334..d0a7935 100644
--- a/services/surfaceflinger/Scheduler/VsyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VsyncModulator.h
@@ -105,7 +105,6 @@
std::atomic<TimePoint> mLastTransactionCommitTime = TimePoint();
const Now mNow;
- const bool mTraceDetailedInfo;
};
} // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index fa31643..9b10c94 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -64,17 +64,6 @@
void DisplayTransactionTest::injectMockScheduler(PhysicalDisplayId displayId) {
LOG_ALWAYS_FATAL_IF(mFlinger.scheduler());
-
- EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_));
- EXPECT_CALL(*mEventThread, createEventConnection(_, _))
- .WillOnce(Return(
- sp<EventThreadConnection>::make(mEventThread, mock::EventThread::kCallingUid)));
-
- EXPECT_CALL(*mSFEventThread, registerDisplayEventConnection(_));
- EXPECT_CALL(*mSFEventThread, createEventConnection(_, _))
- .WillOnce(Return(sp<EventThreadConnection>::make(mSFEventThread,
- mock::EventThread::kCallingUid)));
-
mFlinger.setupScheduler(std::make_unique<mock::VsyncController>(),
std::make_shared<mock::VSyncTracker>(),
std::unique_ptr<EventThread>(mEventThread),
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 45ca7e2..ac09cbc 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -124,7 +124,7 @@
// createConnection call to scheduler makes a createEventConnection call to EventThread. Make
// sure that call gets executed and returns an EventThread::Connection object.
- EXPECT_CALL(*mEventThread, createEventConnection(_, _))
+ EXPECT_CALL(*mEventThread, createEventConnection(_))
.WillRepeatedly(Return(mEventThreadConnection));
mScheduler->setEventThread(Cycle::Render, std::move(eventThread));
@@ -797,7 +797,7 @@
const auto mockConnection1 = sp<MockEventThreadConnection>::make(mEventThread);
const auto mockConnection2 = sp<MockEventThreadConnection>::make(mEventThread);
- EXPECT_CALL(*mEventThread, createEventConnection(_, _))
+ EXPECT_CALL(*mEventThread, createEventConnection(_))
.WillOnce(Return(mockConnection1))
.WillOnce(Return(mockConnection2));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 4b0a7c3..8699621 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -187,16 +187,6 @@
mAppEventThread = eventThread.get();
auto sfEventThread = std::make_unique<mock::EventThread>();
- EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
- EXPECT_CALL(*eventThread, createEventConnection(_, _))
- .WillOnce(Return(sp<EventThreadConnection>::make(eventThread.get(),
- mock::EventThread::kCallingUid)));
-
- EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
- EXPECT_CALL(*sfEventThread, createEventConnection(_, _))
- .WillOnce(Return(sp<EventThreadConnection>::make(sfEventThread.get(),
- mock::EventThread::kCallingUid)));
-
auto vsyncController = std::make_unique<mock::VsyncController>();
auto vsyncTracker = std::make_shared<mock::VSyncTracker>();
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index df16b2e..d92f891 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -74,10 +74,8 @@
void setEventThread(Cycle cycle, std::unique_ptr<EventThread> eventThreadPtr) {
if (cycle == Cycle::Render) {
mRenderEventThread = std::move(eventThreadPtr);
- mRenderEventConnection = mRenderEventThread->createEventConnection();
} else {
mLastCompositeEventThread = std::move(eventThreadPtr);
- mLastCompositeEventConnection = mLastCompositeEventThread->createEventConnection();
}
}
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 725354b..347a396 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -16,7 +16,6 @@
#pragma once
-#include <algorithm>
#include <chrono>
#include <memory>
#include <variant>
@@ -44,7 +43,6 @@
#include "Layer.h"
#include "NativeWindowSurface.h"
#include "RenderArea.h"
-#include "Scheduler/MessageQueue.h"
#include "Scheduler/RefreshRateSelector.h"
#include "SurfaceFlinger.h"
#include "TestableScheduler.h"
@@ -60,7 +58,6 @@
#include "Scheduler/VSyncTracker.h"
#include "Scheduler/VsyncController.h"
-#include "mock/MockVSyncDispatch.h"
#include "mock/MockVSyncTracker.h"
#include "mock/MockVsyncController.h"
@@ -88,9 +85,7 @@
public:
~Factory() = default;
- std::unique_ptr<HWComposer> createHWComposer(const std::string&) override {
- return nullptr;
- }
+ std::unique_ptr<HWComposer> createHWComposer(const std::string&) override { return nullptr; }
std::unique_ptr<scheduler::VsyncConfiguration> createVsyncConfiguration(
Fps /*currentRefreshRate*/) override {
@@ -276,17 +271,6 @@
auto eventThread = makeMock<mock::EventThread>(options.useNiceMock);
auto sfEventThread = makeMock<mock::EventThread>(options.useNiceMock);
-
- EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
- EXPECT_CALL(*eventThread, createEventConnection(_, _))
- .WillOnce(Return(sp<EventThreadConnection>::make(eventThread.get(),
- mock::EventThread::kCallingUid)));
-
- EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
- EXPECT_CALL(*sfEventThread, createEventConnection(_, _))
- .WillOnce(Return(sp<EventThreadConnection>::make(sfEventThread.get(),
- mock::EventThread::kCallingUid)));
-
auto vsyncController = makeMock<mock::VsyncController>(options.useNiceMock);
auto vsyncTracker = makeSharedMock<mock::VSyncTracker>(options.useNiceMock);
@@ -502,7 +486,7 @@
}
auto getDisplayNativePrimaries(const sp<IBinder>& displayToken,
- ui::DisplayPrimaries &primaries) {
+ ui::DisplayPrimaries& primaries) {
return mFlinger->SurfaceFlinger::getDisplayNativePrimaries(displayToken, primaries);
}
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index 8dd1a34..7398cbe 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -24,21 +24,11 @@
class EventThread : public android::EventThread {
public:
- static constexpr auto kCallingUid = static_cast<uid_t>(0);
-
EventThread();
~EventThread() override;
- // TODO(b/302035909): workaround otherwise gtest complains about
- // error: no viable conversion from
- // 'tuple<android::ftl::Flags<android::gui::ISurfaceComposer::EventRegistration> &&>' to 'const
- // tuple<android::ftl::Flags<android::gui::ISurfaceComposer::EventRegistration>>'
- sp<EventThreadConnection> createEventConnection(EventRegistrationFlags flags) const override {
- return createEventConnection(false, flags);
- }
- MOCK_METHOD(sp<EventThreadConnection>, createEventConnection, (bool, EventRegistrationFlags),
- (const));
-
+ MOCK_METHOD(sp<EventThreadConnection>, createEventConnection, (EventRegistrationFlags),
+ (const, override));
MOCK_METHOD(void, enableSyntheticVsync, (bool), (override));
MOCK_METHOD(void, onHotplugReceived, (PhysicalDisplayId, bool), (override));
MOCK_METHOD(void, onHotplugConnectionError, (int32_t), (override));