Merge "InputDispatcher: Only send touchpad nav gestures to trusted overlays" into udc-dev
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index 84900a7..f2b4a6e 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -190,7 +190,8 @@
data.writeInt32(apiType);
data.writeInt32(appUid);
data.writeInt32(appPid);
- status_t err = remote()->transact(LOG_FGS_API_BEGIN_TRANSACTION, data, &reply);
+ status_t err = remote()->transact(LOG_FGS_API_BEGIN_TRANSACTION, data, &reply,
+ IBinder::FLAG_ONEWAY);
if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
ALOGD("FGS Logger Transaction failed");
ALOGD("%d", err);
@@ -205,7 +206,8 @@
data.writeInt32(apiType);
data.writeInt32(appUid);
data.writeInt32(appPid);
- status_t err = remote()->transact(LOG_FGS_API_END_TRANSACTION, data, &reply);
+ status_t err =
+ remote()->transact(LOG_FGS_API_END_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
ALOGD("FGS Logger Transaction failed");
ALOGD("%d", err);
@@ -222,7 +224,8 @@
data.writeInt32(state);
data.writeInt32(appUid);
data.writeInt32(appPid);
- status_t err = remote()->transact(LOG_FGS_API_BEGIN_TRANSACTION, data, &reply);
+ status_t err = remote()->transact(LOG_FGS_API_BEGIN_TRANSACTION, data, &reply,
+ IBinder::FLAG_ONEWAY);
if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
ALOGD("FGS Logger Transaction failed");
ALOGD("%d", err);
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 33bb343..bf34987 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -217,6 +217,7 @@
"DebugEGLImageTracker.cpp",
"DisplayEventDispatcher.cpp",
"DisplayEventReceiver.cpp",
+ "FenceMonitor.cpp",
"GLConsumer.cpp",
"IConsumerListener.cpp",
"IGraphicBufferConsumer.cpp",
@@ -226,6 +227,7 @@
"ITransactionCompletedListener.cpp",
"LayerDebugInfo.cpp",
"LayerMetadata.cpp",
+ "LayerStatePermissions.cpp",
"LayerState.cpp",
"OccupancyTracker.cpp",
"StreamSplitter.cpp",
diff --git a/libs/gui/FenceMonitor.cpp b/libs/gui/FenceMonitor.cpp
new file mode 100644
index 0000000..230c81a
--- /dev/null
+++ b/libs/gui/FenceMonitor.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <gui/FenceMonitor.h>
+#include <gui/TraceUtils.h>
+#include <log/log.h>
+
+#include <thread>
+
+namespace android::gui {
+
+FenceMonitor::FenceMonitor(const char* name) : mName(name), mFencesQueued(0), mFencesSignaled(0) {
+ std::thread thread(&FenceMonitor::loop, this);
+ pthread_setname_np(thread.native_handle(), mName);
+ thread.detach();
+}
+
+void FenceMonitor::queueFence(const sp<Fence>& fence) {
+ char message[64];
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
+ snprintf(message, sizeof(message), "%s fence %u has signaled", mName, mFencesQueued);
+ ATRACE_NAME(message);
+ // Need an increment on both to make the trace number correct.
+ mFencesQueued++;
+ mFencesSignaled++;
+ return;
+ }
+ snprintf(message, sizeof(message), "Trace %s fence %u", mName, mFencesQueued);
+ ATRACE_NAME(message);
+
+ mQueue.push_back(fence);
+ mCondition.notify_one();
+ mFencesQueued++;
+ ATRACE_INT(mName, int32_t(mQueue.size()));
+}
+
+void FenceMonitor::loop() {
+ while (true) {
+ threadLoop();
+ }
+}
+
+void FenceMonitor::threadLoop() {
+ sp<Fence> fence;
+ uint32_t fenceNum;
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+ while (mQueue.empty()) {
+ mCondition.wait(lock);
+ }
+ fence = mQueue[0];
+ fenceNum = mFencesSignaled;
+ }
+ {
+ char message[64];
+ snprintf(message, sizeof(message), "waiting for %s %u", mName, fenceNum);
+ ATRACE_NAME(message);
+
+ status_t result = fence->waitForever(message);
+ if (result != OK) {
+ ALOGE("Error waiting for fence: %d", result);
+ }
+ }
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mQueue.pop_front();
+ mFencesSignaled++;
+ ATRACE_INT(mName, int32_t(mQueue.size()));
+ }
+}
+
+} // namespace android::gui
\ No newline at end of file
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index cefb9a7..d72f65e 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -62,7 +62,7 @@
status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
Vector<ComposerState>& state, const Vector<DisplayState>& displays,
uint32_t flags, const sp<IBinder>& applyToken,
- const InputWindowCommands& commands, int64_t desiredPresentTime,
+ InputWindowCommands commands, int64_t desiredPresentTime,
bool isAutoTimestamp,
const std::vector<client_cache_t>& uncacheBuffers,
bool hasListenerCallbacks,
@@ -188,9 +188,9 @@
SAFE_PARCEL(data.readUint64, &transactionId);
return setTransactionState(frameTimelineInfo, state, displays, stateFlags, applyToken,
- inputWindowCommands, desiredPresentTime, isAutoTimestamp,
- uncacheBuffers, hasListenerCallbacks, listenerCallbacks,
- transactionId);
+ std::move(inputWindowCommands), desiredPresentTime,
+ isAutoTimestamp, uncacheBuffers, hasListenerCallbacks,
+ listenerCallbacks, transactionId);
}
default: {
return BBinder::onTransact(code, data, reply, flags);
diff --git a/libs/gui/LayerStatePermissions.cpp b/libs/gui/LayerStatePermissions.cpp
new file mode 100644
index 0000000..28697ca
--- /dev/null
+++ b/libs/gui/LayerStatePermissions.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/IPCThreadState.h>
+#include <gui/LayerStatePermissions.h>
+#include <private/android_filesystem_config.h>
+#ifndef __ANDROID_VNDK__
+#include <binder/PermissionCache.h>
+#endif // __ANDROID_VNDK__
+#include <gui/LayerState.h>
+
+namespace android {
+std::unordered_map<std::string, int> LayerStatePermissions::mPermissionMap = {
+ // If caller has ACCESS_SURFACE_FLINGER, they automatically get ROTATE_SURFACE_FLINGER
+ // permission, as well
+ {"android.permission.ACCESS_SURFACE_FLINGER",
+ layer_state_t::Permission::ACCESS_SURFACE_FLINGER |
+ layer_state_t::Permission::ROTATE_SURFACE_FLINGER},
+ {"android.permission.ROTATE_SURFACE_FLINGER",
+ layer_state_t::Permission::ROTATE_SURFACE_FLINGER},
+ {"android.permission.INTERNAL_SYSTEM_WINDOW",
+ layer_state_t::Permission::INTERNAL_SYSTEM_WINDOW},
+};
+
+static bool callingThreadHasPermission(const std::string& permission __attribute__((unused)),
+ int pid __attribute__((unused)),
+ int uid __attribute__((unused))) {
+#ifndef __ANDROID_VNDK__
+ return uid == AID_GRAPHICS || uid == AID_SYSTEM ||
+ PermissionCache::checkPermission(String16(permission.c_str()), pid, uid);
+#endif // __ANDROID_VNDK__
+ return false;
+}
+
+uint32_t LayerStatePermissions::getTransactionPermissions(int pid, int uid) {
+ uint32_t permissions = 0;
+ for (auto [permissionName, permissionVal] : mPermissionMap) {
+ if (callingThreadHasPermission(permissionName, pid, uid)) {
+ permissions |= permissionVal;
+ }
+ }
+
+ return permissions;
+}
+} // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index a5cf8d6..ed69100 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -30,6 +30,7 @@
#include <android/gui/DisplayStatInfo.h>
#include <android/native_window.h>
+#include <gui/FenceMonitor.h>
#include <gui/TraceUtils.h>
#include <utils/Log.h>
#include <utils/NativeHandle.h>
@@ -545,82 +546,6 @@
return NO_ERROR;
}
-class FenceMonitor {
-public:
- explicit FenceMonitor(const char* name) : mName(name), mFencesQueued(0), mFencesSignaled(0) {
- std::thread thread(&FenceMonitor::loop, this);
- pthread_setname_np(thread.native_handle(), mName);
- thread.detach();
- }
-
- void queueFence(const sp<Fence>& fence) {
- char message[64];
-
- std::lock_guard<std::mutex> lock(mMutex);
- if (fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
- snprintf(message, sizeof(message), "%s fence %u has signaled", mName, mFencesQueued);
- ATRACE_NAME(message);
- // Need an increment on both to make the trace number correct.
- mFencesQueued++;
- mFencesSignaled++;
- return;
- }
- snprintf(message, sizeof(message), "Trace %s fence %u", mName, mFencesQueued);
- ATRACE_NAME(message);
-
- mQueue.push_back(fence);
- mCondition.notify_one();
- mFencesQueued++;
- ATRACE_INT(mName, int32_t(mQueue.size()));
- }
-
-private:
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wmissing-noreturn"
- void loop() {
- while (true) {
- threadLoop();
- }
- }
-#pragma clang diagnostic pop
-
- void threadLoop() {
- sp<Fence> fence;
- uint32_t fenceNum;
- {
- std::unique_lock<std::mutex> lock(mMutex);
- while (mQueue.empty()) {
- mCondition.wait(lock);
- }
- fence = mQueue[0];
- fenceNum = mFencesSignaled;
- }
- {
- char message[64];
- snprintf(message, sizeof(message), "waiting for %s %u", mName, fenceNum);
- ATRACE_NAME(message);
-
- status_t result = fence->waitForever(message);
- if (result != OK) {
- ALOGE("Error waiting for fence: %d", result);
- }
- }
- {
- std::lock_guard<std::mutex> lock(mMutex);
- mQueue.pop_front();
- mFencesSignaled++;
- ATRACE_INT(mName, int32_t(mQueue.size()));
- }
- }
-
- const char* mName;
- uint32_t mFencesQueued;
- uint32_t mFencesSignaled;
- std::deque<sp<Fence>> mQueue;
- std::condition_variable mCondition;
- std::mutex mMutex;
-};
-
void Surface::getDequeueBufferInputLocked(
IGraphicBufferProducer::DequeueBufferInput* dequeueInput) {
LOG_ALWAYS_FATAL_IF(dequeueInput == nullptr, "input is null");
@@ -694,7 +619,7 @@
ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
- static FenceMonitor hwcReleaseThread("HWC release");
+ static gui::FenceMonitor hwcReleaseThread("HWC release");
hwcReleaseThread.queueFence(fence);
}
@@ -893,7 +818,7 @@
sp<GraphicBuffer>& gbuf(mSlots[slot].buffer);
if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
- static FenceMonitor hwcReleaseThread("HWC release");
+ static gui::FenceMonitor hwcReleaseThread("HWC release");
hwcReleaseThread.queueFence(output.fence);
}
@@ -1163,7 +1088,7 @@
mQueueBufferCondition.broadcast();
if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
- static FenceMonitor gpuCompletionThread("GPU completion");
+ static gui::FenceMonitor gpuCompletionThread("GPU completion");
gpuCompletionThread.queueFence(fence);
}
}
@@ -1871,12 +1796,14 @@
auto frameTimelineVsyncId = static_cast<int64_t>(va_arg(args, int64_t));
auto inputEventId = static_cast<int32_t>(va_arg(args, int32_t));
auto startTimeNanos = static_cast<int64_t>(va_arg(args, int64_t));
+ auto useForRefreshRateSelection = static_cast<bool>(va_arg(args, int32_t));
ALOGV("Surface::%s", __func__);
FrameTimelineInfo ftlInfo;
ftlInfo.vsyncId = frameTimelineVsyncId;
ftlInfo.inputEventId = inputEventId;
ftlInfo.startTimeNanos = startTimeNanos;
+ ftlInfo.useForRefreshRateSelection = useForRefreshRateSelection;
return setFrameTimelineInfo(frameNumber, ftlInfo);
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index eb5cc4f..c6c7367 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -54,6 +54,7 @@
#include <ui/DynamicDisplayInfo.h>
#include <android-base/thread_annotations.h>
+#include <gui/LayerStatePermissions.h>
#include <private/gui/ComposerService.h>
#include <private/gui/ComposerServiceAIDL.h>
@@ -716,11 +717,16 @@
mListenerCallbacks = other.mListenerCallbacks;
}
-void SurfaceComposerClient::Transaction::sanitize() {
+void SurfaceComposerClient::Transaction::sanitize(int pid, int uid) {
+ uint32_t permissions = LayerStatePermissions::getTransactionPermissions(pid, uid);
for (auto & [handle, composerState] : mComposerStates) {
- composerState.state.sanitize(0 /* permissionMask */);
+ composerState.state.sanitize(permissions);
}
- mInputWindowCommands.clear();
+ if (!mInputWindowCommands.empty() &&
+ (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) == 0) {
+ ALOGE("Only privileged callers are allowed to send input commands.");
+ mInputWindowCommands.clear();
+ }
}
std::unique_ptr<SurfaceComposerClient::Transaction>
@@ -2239,11 +2245,13 @@
t.vsyncId = other.vsyncId;
t.inputEventId = other.inputEventId;
t.startTimeNanos = other.startTimeNanos;
+ t.useForRefreshRateSelection = other.useForRefreshRateSelection;
}
} else if (t.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
t.vsyncId = other.vsyncId;
t.inputEventId = other.inputEventId;
t.startTimeNanos = other.startTimeNanos;
+ t.useForRefreshRateSelection = other.useForRefreshRateSelection;
}
}
@@ -2252,6 +2260,7 @@
t.vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID;
t.inputEventId = os::IInputConstants::INVALID_INPUT_EVENT_ID;
t.startTimeNanos = 0;
+ t.useForRefreshRateSelection = false;
}
SurfaceComposerClient::Transaction&
diff --git a/libs/gui/aidl/android/gui/FrameTimelineInfo.aidl b/libs/gui/aidl/android/gui/FrameTimelineInfo.aidl
index 6ffe466..6a86c6a 100644
--- a/libs/gui/aidl/android/gui/FrameTimelineInfo.aidl
+++ b/libs/gui/aidl/android/gui/FrameTimelineInfo.aidl
@@ -33,4 +33,8 @@
// The current time in nanoseconds the application started to render the frame.
long startTimeNanos = 0;
+
+ // Whether this vsyncId should be used to heuristically select the display refresh rate
+ // TODO(b/281695725): Clean this up once TextureView use setFrameRate API
+ boolean useForRefreshRateSelection = false;
}
diff --git a/libs/gui/include/gui/FenceMonitor.h b/libs/gui/include/gui/FenceMonitor.h
new file mode 100644
index 0000000..62cedde
--- /dev/null
+++ b/libs/gui/include/gui/FenceMonitor.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <deque>
+#include <mutex>
+
+#include <ui/Fence.h>
+
+namespace android::gui {
+
+class FenceMonitor {
+public:
+ explicit FenceMonitor(const char* name);
+ void queueFence(const sp<Fence>& fence);
+
+private:
+ void loop();
+ void threadLoop();
+
+ const char* mName;
+ uint32_t mFencesQueued;
+ uint32_t mFencesSignaled;
+ std::deque<sp<Fence>> mQueue;
+ std::condition_variable mCondition;
+ std::mutex mMutex;
+};
+
+} // namespace android::gui
\ No newline at end of file
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 1e67225..bd21851 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -113,7 +113,7 @@
virtual status_t setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
- const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
+ InputWindowCommands inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffer,
bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
uint64_t transactionId) = 0;
diff --git a/libs/gui/include/gui/LayerStatePermissions.h b/libs/gui/include/gui/LayerStatePermissions.h
new file mode 100644
index 0000000..a90f30c
--- /dev/null
+++ b/libs/gui/include/gui/LayerStatePermissions.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <string>
+#include <unordered_map>
+
+namespace android {
+class LayerStatePermissions {
+public:
+ static uint32_t getTransactionPermissions(int pid, int uid);
+
+private:
+ static std::unordered_map<std::string, int> mPermissionMap;
+};
+} // namespace android
\ No newline at end of file
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 945b164..8d2cdaf 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -744,7 +744,7 @@
*
* TODO (b/213644870): Remove all permissioned things from Transaction
*/
- void sanitize();
+ void sanitize(int pid, int uid);
static sp<IBinder> getDefaultApplyToken();
static void setDefaultApplyToken(sp<IBinder> applyToken);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index fccc408..5bc6904 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -699,7 +699,7 @@
Vector<ComposerState>& /*state*/,
const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
const sp<IBinder>& /*applyToken*/,
- const InputWindowCommands& /*inputWindowCommands*/,
+ InputWindowCommands /*inputWindowCommands*/,
int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/,
const std::vector<client_cache_t>& /*cachedBuffer*/,
bool /*hasListenerCallbacks*/,
diff --git a/libs/input/VirtualInputDevice.cpp b/libs/input/VirtualInputDevice.cpp
index af9ce3a..9a459b1 100644
--- a/libs/input/VirtualInputDevice.cpp
+++ b/libs/input/VirtualInputDevice.cpp
@@ -49,11 +49,10 @@
std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(eventTime);
std::chrono::microseconds microseconds =
std::chrono::duration_cast<std::chrono::microseconds>(eventTime - seconds);
- struct input_event ev = {.type = type,
- .code = code,
- .value = value,
- .input_event_sec = static_cast<time_t>(seconds.count()),
- .input_event_usec = static_cast<suseconds_t>(microseconds.count())};
+ struct input_event ev = {.type = type, .code = code, .value = value};
+ ev.input_event_sec = static_cast<decltype(ev.input_event_sec)>(seconds.count());
+ ev.input_event_usec = static_cast<decltype(ev.input_event_usec)>(microseconds.count());
+
return TEMP_FAILURE_RETRY(write(mFd, &ev, sizeof(struct input_event))) == sizeof(ev);
}
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 6c54635..0fee3c1 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -1066,13 +1066,12 @@
(int)compatibility, (int)changeFrameRateStrategy);
}
-static inline int native_window_set_frame_timeline_info(struct ANativeWindow* window,
- uint64_t frameNumber,
- int64_t frameTimelineVsyncId,
- int32_t inputEventId,
- int64_t startTimeNanos) {
+static inline int native_window_set_frame_timeline_info(
+ struct ANativeWindow* window, uint64_t frameNumber, int64_t frameTimelineVsyncId,
+ int32_t inputEventId, int64_t startTimeNanos, int32_t useForRefreshRateSelection) {
return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO, frameNumber,
- frameTimelineVsyncId, inputEventId, startTimeNanos);
+ frameTimelineVsyncId, inputEventId, startTimeNanos,
+ useForRefreshRateSelection);
}
// ------------------------------------------------------------------------------------------------
diff --git a/libs/permission/AppOpsManager.cpp b/libs/permission/AppOpsManager.cpp
index baa9d75..6959274 100644
--- a/libs/permission/AppOpsManager.cpp
+++ b/libs/permission/AppOpsManager.cpp
@@ -146,6 +146,14 @@
}
}
+void AppOpsManager::startWatchingMode(int32_t op, const String16& packageName, int32_t flags,
+ const sp<IAppOpsCallback>& callback) {
+ sp<IAppOpsService> service = getService();
+ if (service != nullptr) {
+ service->startWatchingModeWithFlags(op, packageName, flags, callback);
+ }
+}
+
void AppOpsManager::stopWatchingMode(const sp<IAppOpsCallback>& callback) {
sp<IAppOpsService> service = getService();
if (service != nullptr) {
diff --git a/libs/permission/IAppOpsService.cpp b/libs/permission/IAppOpsService.cpp
index d59f445..7f235a4 100644
--- a/libs/permission/IAppOpsService.cpp
+++ b/libs/permission/IAppOpsService.cpp
@@ -166,6 +166,17 @@
}
return reply.readBool();
}
+
+ virtual void startWatchingModeWithFlags(int32_t op, const String16& packageName,
+ int32_t flags, const sp<IAppOpsCallback>& callback) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+ data.writeInt32(op);
+ data.writeString16(packageName);
+ data.writeInt32(flags);
+ data.writeStrongBinder(IInterface::asBinder(callback));
+ remote()->transact(START_WATCHING_MODE_WITH_FLAGS_TRANSACTION, data, &reply);
+ }
};
IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService")
diff --git a/libs/permission/include/binder/AppOpsManager.h b/libs/permission/include/binder/AppOpsManager.h
index abcd527..243532b 100644
--- a/libs/permission/include/binder/AppOpsManager.h
+++ b/libs/permission/include/binder/AppOpsManager.h
@@ -151,6 +151,10 @@
_NUM_OP = 117
};
+ enum {
+ WATCH_FOREGROUND_CHANGES = 1 << 0
+ };
+
AppOpsManager();
int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
@@ -174,6 +178,8 @@
const std::optional<String16>& attributionTag);
void startWatchingMode(int32_t op, const String16& packageName,
const sp<IAppOpsCallback>& callback);
+ void startWatchingMode(int32_t op, const String16& packageName, int32_t flags,
+ const sp<IAppOpsCallback>& callback);
void stopWatchingMode(const sp<IAppOpsCallback>& callback);
int32_t permissionToOpCode(const String16& permission);
void setCameraAudioRestriction(int32_t mode);
diff --git a/libs/permission/include/binder/IAppOpsService.h b/libs/permission/include/binder/IAppOpsService.h
index 22f056b..918fcdb 100644
--- a/libs/permission/include/binder/IAppOpsService.h
+++ b/libs/permission/include/binder/IAppOpsService.h
@@ -52,6 +52,8 @@
const String16& packageName) = 0;
virtual void setCameraAudioRestriction(int32_t mode) = 0;
virtual bool shouldCollectNotes(int32_t opCode) = 0;
+ virtual void startWatchingModeWithFlags(int32_t op, const String16& packageName,
+ int32_t flags, const sp<IAppOpsCallback>& callback) = 0;
enum {
CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
@@ -64,6 +66,7 @@
CHECK_AUDIO_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+7,
SHOULD_COLLECT_NOTES_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+8,
SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+9,
+ START_WATCHING_MODE_WITH_FLAGS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+10,
};
enum {
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index cfea85f..5854135 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -39,10 +39,10 @@
#include <SkPath.h>
#include <SkPoint.h>
#include <SkPoint3.h>
+#include <SkRRect.h>
#include <SkRect.h>
#include <SkRefCnt.h>
#include <SkRegion.h>
-#include <SkRRect.h>
#include <SkRuntimeEffect.h>
#include <SkSamplingOptions.h>
#include <SkScalar.h>
@@ -51,9 +51,11 @@
#include <SkString.h>
#include <SkSurface.h>
#include <SkTileMode.h>
-#include <src/core/SkTraceEventCommon.h>
#include <android-base/stringprintf.h>
+#include <gui/FenceMonitor.h>
#include <gui/TraceUtils.h>
+#include <pthread.h>
+#include <src/core/SkTraceEventCommon.h>
#include <sync/sync.h>
#include <ui/BlurRegion.h>
#include <ui/DataspaceUtils.h>
@@ -63,6 +65,7 @@
#include <cmath>
#include <cstdint>
+#include <deque>
#include <memory>
#include <numeric>
@@ -229,7 +232,6 @@
static inline SkPoint3 getSkPoint3(const android::vec3& vector) {
return SkPoint3::Make(vector.x, vector.y, vector.z);
}
-
} // namespace
namespace android {
@@ -1134,8 +1136,13 @@
activeSurface->flush();
}
- base::unique_fd drawFence = flushAndSubmit(grContext);
- resultPromise->set_value(sp<Fence>::make(std::move(drawFence)));
+ auto drawFence = sp<Fence>::make(flushAndSubmit(grContext));
+
+ if (ATRACE_ENABLED()) {
+ static gui::FenceMonitor sMonitor("RE Completion");
+ sMonitor.queueFence(drawFence);
+ }
+ resultPromise->set_value(std::move(drawFence));
}
size_t SkiaRenderEngine::getMaxTextureSize() const {
diff --git a/libs/ultrahdr/jpegr.cpp b/libs/ultrahdr/jpegr.cpp
index 0f7aa27..ef927e3 100644
--- a/libs/ultrahdr/jpegr.cpp
+++ b/libs/ultrahdr/jpegr.cpp
@@ -534,7 +534,7 @@
if (mQueuedAllJobs) {
return false;
} else {
- mCv.wait(lock);
+ mCv.wait_for(lock, std::chrono::milliseconds(100));
}
} else {
auto it = mJobs.begin();
@@ -557,6 +557,8 @@
void JobQueue::markQueueForEnd() {
std::unique_lock<std::mutex> lock{mMutex};
mQueuedAllJobs = true;
+ lock.unlock();
+ mCv.notify_all();
}
void JobQueue::reset() {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 0dd3dde..a3c129e 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2495,7 +2495,8 @@
newTouchedWindowHandle = nullptr;
}
- if (!haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) {
+ if (newTouchedWindowHandle != nullptr &&
+ !haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) {
ALOGD("Touch is slipping out of window %s into window %s in display %" PRId32,
oldTouchedWindowHandle->getName().c_str(),
newTouchedWindowHandle->getName().c_str(), displayId);
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index b86906b..3f6d557 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -203,7 +203,7 @@
using Change = InputReaderConfiguration::Change;
- if (!isIgnored()) {
+ if (!changes.any() || !isIgnored()) {
// Full configuration should happen the first time configure is called
// and when the device type is changed. Changing a device type can
// affect various other parameters so should result in a
@@ -446,17 +446,17 @@
// Switch-like devices.
if (classes.test(InputDeviceClass::SWITCH)) {
- mappers.push_back(std::make_unique<SwitchInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<SwitchInputMapper>(contextPtr, readerConfig));
}
// Scroll wheel-like devices.
if (classes.test(InputDeviceClass::ROTARY_ENCODER)) {
- mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<RotaryEncoderInputMapper>(contextPtr, readerConfig));
}
// Vibrator-like devices.
if (classes.test(InputDeviceClass::VIBRATOR)) {
- mappers.push_back(std::make_unique<VibratorInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<VibratorInputMapper>(contextPtr, readerConfig));
}
// Battery-like devices or light-containing devices.
@@ -488,7 +488,7 @@
// Cursor-like devices.
if (classes.test(InputDeviceClass::CURSOR)) {
- mappers.push_back(std::make_unique<CursorInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<CursorInputMapper>(contextPtr, readerConfig));
}
// Touchscreens and touchpad devices.
@@ -501,26 +501,26 @@
(identifier.product == 0x05c4 || identifier.product == 0x09cc);
if (ENABLE_TOUCHPAD_GESTURES_LIBRARY && classes.test(InputDeviceClass::TOUCHPAD) &&
classes.test(InputDeviceClass::TOUCH_MT) && !isSonyDualShock4Touchpad) {
- mappers.push_back(std::make_unique<TouchpadInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<TouchpadInputMapper>(contextPtr, readerConfig));
} else if (classes.test(InputDeviceClass::TOUCH_MT)) {
- mappers.push_back(std::make_unique<MultiTouchInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<MultiTouchInputMapper>(contextPtr, readerConfig));
} else if (classes.test(InputDeviceClass::TOUCH)) {
- mappers.push_back(std::make_unique<SingleTouchInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<SingleTouchInputMapper>(contextPtr, readerConfig));
}
// Joystick-like devices.
if (classes.test(InputDeviceClass::JOYSTICK)) {
- mappers.push_back(std::make_unique<JoystickInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<JoystickInputMapper>(contextPtr, readerConfig));
}
// Motion sensor enabled devices.
if (classes.test(InputDeviceClass::SENSOR)) {
- mappers.push_back(std::make_unique<SensorInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<SensorInputMapper>(contextPtr, readerConfig));
}
// External stylus-like devices.
if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) {
- mappers.push_back(std::make_unique<ExternalStylusInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<ExternalStylusInputMapper>(contextPtr, readerConfig));
}
return mappers;
}
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 6303546..0b8a608 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -149,6 +149,16 @@
return *mapper;
}
+ template <class T, typename... Args>
+ T& constructAndAddMapper(int32_t eventHubId, Args... args) {
+ // create mapper
+ auto& devicePair = mDevices[eventHubId];
+ auto& deviceContext = devicePair.first;
+ auto& mappers = devicePair.second;
+ mappers.push_back(createInputMapper<T>(*deviceContext, args...));
+ return static_cast<T&>(*mappers.back());
+ }
+
// construct and add a controller to the input device
template <class T>
T& addController(int32_t eventHubId) {
diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
index dab4661..061c6a3 100644
--- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
+++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
@@ -199,6 +199,29 @@
}
}
+ // Send BUTTON_RELEASE events. (This has to happen before any UP events to avoid sending
+ // BUTTON_RELEASE events without any pointers.)
+ uint32_t newButtonState;
+ if (coords.size() - upSlots.size() + downSlots.size() == 0) {
+ // If there won't be any pointers down after this evdev sync, we won't be able to send
+ // button updates on their own, as motion events without pointers are invalid. To avoid
+ // erroneously reporting buttons being held for long periods, send BUTTON_RELEASE events for
+ // all pressed buttons when the last pointer is lifted.
+ //
+ // This also prevents us from sending BUTTON_PRESS events too early in the case of touchpads
+ // which report a button press one evdev sync before reporting a touch going down.
+ newButtonState = 0;
+ } else {
+ newButtonState = mCursorButtonAccumulator.getButtonState();
+ }
+ for (uint32_t button = 1; button <= AMOTION_EVENT_BUTTON_FORWARD; button <<= 1) {
+ if (!(newButtonState & button) && mButtonState & button) {
+ mButtonState &= ~button;
+ out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
+ coords, properties, /*actionButton=*/button));
+ }
+ }
+
// For any touches that were lifted, send UP or POINTER_UP events.
for (size_t slotNumber : upSlots) {
const size_t indexToRemove = coordsIndexForSlotNumber.at(slotNumber);
@@ -240,16 +263,11 @@
out.push_back(makeMotionArgs(when, readTime, action, coords, properties));
}
- const uint32_t newButtonState = mCursorButtonAccumulator.getButtonState();
for (uint32_t button = 1; button <= AMOTION_EVENT_BUTTON_FORWARD; button <<= 1) {
if (newButtonState & button && !(mButtonState & button)) {
mButtonState |= button;
out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_PRESS, coords,
properties, /*actionButton=*/button));
- } else if (!(newButtonState & button) && mButtonState & button) {
- mButtonState &= ~button;
- out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
- coords, properties, /*actionButton=*/button));
}
}
return out;
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 8ef5ff6..c684ed4 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -71,9 +71,7 @@
CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext,
const InputReaderConfiguration& readerConfig)
: InputMapper(deviceContext, readerConfig),
- mLastEventTime(std::numeric_limits<nsecs_t>::min()) {
- configureWithZeroChanges(readerConfig);
-}
+ mLastEventTime(std::numeric_limits<nsecs_t>::min()) {}
CursorInputMapper::~CursorInputMapper() {
if (mPointerController != nullptr) {
@@ -142,46 +140,51 @@
ConfigurationChanges changes) {
std::list<NotifyArgs> out = InputMapper::reconfigure(when, readerConfig, changes);
- if (!changes.any()) {
- configureWithZeroChanges(readerConfig);
- return out;
+ if (!changes.any()) { // first time only
+ configureBasicParams();
}
- const bool configurePointerCapture = mParameters.mode != Parameters::Mode::NAVIGATION &&
- changes.test(InputReaderConfiguration::Change::POINTER_CAPTURE);
+ const bool configurePointerCapture = !changes.any() ||
+ (mParameters.mode != Parameters::Mode::NAVIGATION &&
+ changes.test(InputReaderConfiguration::Change::POINTER_CAPTURE));
if (configurePointerCapture) {
configureOnPointerCapture(readerConfig);
out.push_back(NotifyDeviceResetArgs(getContext()->getNextId(), when, getDeviceId()));
}
- if (changes.test(InputReaderConfiguration::Change::POINTER_SPEED) || configurePointerCapture) {
+ if (!changes.any() || changes.test(InputReaderConfiguration::Change::POINTER_SPEED) ||
+ configurePointerCapture) {
configureOnChangePointerSpeed(readerConfig);
}
- if (changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) || configurePointerCapture) {
+ if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) ||
+ configurePointerCapture) {
configureOnChangeDisplayInfo(readerConfig);
}
return out;
}
-void CursorInputMapper::configureParameters() {
- mParameters.mode = Parameters::Mode::POINTER;
- const PropertyMap& config = getDeviceContext().getConfiguration();
+CursorInputMapper::Parameters CursorInputMapper::computeParameters(
+ const InputDeviceContext& deviceContext) {
+ Parameters parameters;
+ parameters.mode = Parameters::Mode::POINTER;
+ const PropertyMap& config = deviceContext.getConfiguration();
std::optional<std::string> cursorModeString = config.getString("cursor.mode");
if (cursorModeString.has_value()) {
if (*cursorModeString == "navigation") {
- mParameters.mode = Parameters::Mode::NAVIGATION;
+ parameters.mode = Parameters::Mode::NAVIGATION;
} else if (*cursorModeString != "pointer" && *cursorModeString != "default") {
ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString->c_str());
}
}
- mParameters.orientationAware = config.getBool("cursor.orientationAware").value_or(false);
+ parameters.orientationAware = config.getBool("cursor.orientationAware").value_or(false);
- mParameters.hasAssociatedDisplay = false;
- if (mParameters.mode == Parameters::Mode::POINTER || mParameters.orientationAware) {
- mParameters.hasAssociatedDisplay = true;
+ parameters.hasAssociatedDisplay = false;
+ if (parameters.mode == Parameters::Mode::POINTER || parameters.orientationAware) {
+ parameters.hasAssociatedDisplay = true;
}
+ return parameters;
}
void CursorInputMapper::dumpParameters(std::string& dump) {
@@ -424,22 +427,11 @@
return mDisplayId;
}
-void CursorInputMapper::configureWithZeroChanges(const InputReaderConfiguration& readerConfig) {
- // Configuration with zero changes
- configureBasicParams();
- if (mParameters.mode != Parameters::Mode::NAVIGATION &&
- readerConfig.pointerCaptureRequest.enable) {
- configureOnPointerCapture(readerConfig);
- }
- configureOnChangePointerSpeed(readerConfig);
- configureOnChangeDisplayInfo(readerConfig);
-}
-
void CursorInputMapper::configureBasicParams() {
mCursorScrollAccumulator.configure(getDeviceContext());
// Configure basic parameters.
- configureParameters();
+ mParameters = computeParameters(getDeviceContext());
// Configure device mode.
switch (mParameters.mode) {
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index caf2e5a..b879bfd 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -53,8 +53,10 @@
class CursorInputMapper : public InputMapper {
public:
- explicit CursorInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~CursorInputMapper();
virtual uint32_t getSources() const override;
@@ -125,15 +127,17 @@
nsecs_t mDownTime;
nsecs_t mLastEventTime;
- void configureParameters();
+ explicit CursorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
void dumpParameters(std::string& dump);
- void configureWithZeroChanges(const InputReaderConfiguration& readerConfig);
void configureBasicParams();
void configureOnPointerCapture(const InputReaderConfiguration& config);
void configureOnChangePointerSpeed(const InputReaderConfiguration& config);
void configureOnChangeDisplayInfo(const InputReaderConfiguration& config);
[[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when, nsecs_t readTime);
+
+ static Parameters computeParameters(const InputDeviceContext& deviceContext);
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
index 841c437..97df02b 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
@@ -26,8 +26,10 @@
class ExternalStylusInputMapper : public InputMapper {
public:
- explicit ExternalStylusInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~ExternalStylusInputMapper() = default;
uint32_t getSources() const override;
@@ -46,6 +48,8 @@
StylusState mStylusState;
+ explicit ExternalStylusInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
[[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when);
};
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index f017317..06de4c2 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -25,6 +25,20 @@
#include "VibrationElement.h"
namespace android {
+/**
+ * This is the factory method that must be used to create any InputMapper
+ */
+template <class T, class... Args>
+std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig, Args... args) {
+ // Using `new` to access non-public constructors.
+ std::unique_ptr<T> mapper(new T(deviceContext, readerConfig, args...));
+ // We need to reset and configure the mapper to ensure it is ready to process event
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ std::list<NotifyArgs> unused = mapper->reset(now);
+ unused += mapper->reconfigure(now, readerConfig, /*changes=*/{});
+ return mapper;
+}
/* An input mapper transforms raw input events into cooked event data.
* A single input device can have multiple associated input mappers in order to interpret
@@ -39,8 +53,15 @@
*/
class InputMapper {
public:
- explicit InputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ /**
+ * Subclasses must either provide a public constructor
+ * or must be-friend the factory method.
+ */
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
+
virtual ~InputMapper();
inline int32_t getDeviceId() { return mDeviceContext.getId(); }
@@ -102,6 +123,9 @@
protected:
InputDeviceContext& mDeviceContext;
+ explicit InputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
+
status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo);
void bumpGeneration();
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.h b/services/inputflinger/reader/mapper/JoystickInputMapper.h
index 49673a2..313f092 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.h
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.h
@@ -22,8 +22,10 @@
class JoystickInputMapper : public InputMapper {
public:
- explicit JoystickInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~JoystickInputMapper();
virtual uint32_t getSources() const override;
@@ -87,6 +89,9 @@
}
};
+ explicit JoystickInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
+
static Axis createAxis(const AxisInfo& AxisInfo, const RawAbsoluteAxisInfo& rawAxisInfo,
bool explicitlyMapped);
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
index a617420..1d788df 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
@@ -23,8 +23,11 @@
class MultiTouchInputMapper : public TouchInputMapper {
public:
- explicit MultiTouchInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
+
~MultiTouchInputMapper() override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
@@ -36,6 +39,8 @@
bool hasStylus() const override;
private:
+ explicit MultiTouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
// simulate_stylus_with_touch is a debug mode that converts all finger pointers reported by this
// mapper's touchscreen into stylus pointers, and adds SOURCE_STYLUS to the input device.
// It is used to simulate stylus events for debugging and testing on a device that does not
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
index d3dcbe1..9e2e8c4 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
@@ -25,8 +25,10 @@
class RotaryEncoderInputMapper : public InputMapper {
public:
- explicit RotaryEncoderInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~RotaryEncoderInputMapper();
virtual uint32_t getSources() const override;
@@ -45,6 +47,8 @@
float mScalingFactor;
ui::Rotation mOrientation;
+ explicit RotaryEncoderInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
[[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when, nsecs_t readTime);
};
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.h b/services/inputflinger/reader/mapper/SensorInputMapper.h
index 1f82559..a55dcd1 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.h
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.h
@@ -27,8 +27,10 @@
class SensorInputMapper : public InputMapper {
public:
- explicit SensorInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
~SensorInputMapper() override;
uint32_t getSources() const override;
@@ -106,6 +108,9 @@
}
};
+ explicit SensorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
+
static Axis createAxis(const AxisInfo& AxisInfo, const RawAbsoluteAxisInfo& rawAxisInfo);
// Axes indexed by raw ABS_* axis index.
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
index 9341007..7726bfb 100644
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
@@ -23,8 +23,11 @@
class SingleTouchInputMapper : public TouchInputMapper {
public:
- explicit SingleTouchInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
+
~SingleTouchInputMapper() override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
@@ -37,6 +40,8 @@
private:
SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
+ explicit SingleTouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.h b/services/inputflinger/reader/mapper/SwitchInputMapper.h
index 7ec282b..2fb48bb 100644
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.h
+++ b/services/inputflinger/reader/mapper/SwitchInputMapper.h
@@ -22,8 +22,10 @@
class SwitchInputMapper : public InputMapper {
public:
- explicit SwitchInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~SwitchInputMapper();
virtual uint32_t getSources() const override;
@@ -36,6 +38,8 @@
uint32_t mSwitchValues;
uint32_t mUpdatedSwitchMask;
+ explicit SwitchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
void processSwitch(int32_t switchCode, int32_t switchValue);
[[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when);
};
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index c72a263..f4d50b8 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -125,8 +125,7 @@
const InputReaderConfiguration& readerConfig)
: InputMapper(deviceContext, readerConfig),
mTouchButtonAccumulator(deviceContext),
- mConfig(readerConfig),
- mParameters(computeParameters(deviceContext)) {}
+ mConfig(readerConfig) {}
TouchInputMapper::~TouchInputMapper() {}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 7141924..d8b59ca 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -146,8 +146,6 @@
class TouchInputMapper : public InputMapper {
public:
- explicit TouchInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
~TouchInputMapper() override;
uint32_t getSources() const override;
@@ -358,25 +356,28 @@
nsecs_t mExternalStylusFusionTimeout;
bool mExternalStylusDataPending;
// A subset of the buttons in mCurrentRawState that came from an external stylus.
- int32_t mExternalStylusButtonsApplied;
+ int32_t mExternalStylusButtonsApplied{0};
// True if we sent a HOVER_ENTER event.
- bool mSentHoverEnter;
+ bool mSentHoverEnter{false};
// Have we assigned pointer IDs for this stream
- bool mHavePointerIds;
+ bool mHavePointerIds{false};
// Is the current stream of direct touch events aborted
- bool mCurrentMotionAborted;
+ bool mCurrentMotionAborted{false};
// The time the primary pointer last went down.
- nsecs_t mDownTime;
+ nsecs_t mDownTime{0};
// The pointer controller, or null if the device is not a pointer.
std::shared_ptr<PointerControllerInterface> mPointerController;
std::vector<VirtualKey> mVirtualKeys;
+ explicit TouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
+
virtual void dumpParameters(std::string& dump);
virtual void configureRawPointerAxes();
virtual void dumpRawPointerAxes(std::string& dump);
@@ -513,7 +514,7 @@
STYLUS,
MOUSE,
};
- PointerUsage mPointerUsage;
+ PointerUsage mPointerUsage{PointerUsage::NONE};
struct PointerGesture {
enum class Mode {
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
index 3128d18..23d0fd3 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -40,8 +40,10 @@
class TouchpadInputMapper : public InputMapper {
public:
- explicit TouchpadInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
~TouchpadInputMapper();
uint32_t getSources() const override;
@@ -58,6 +60,8 @@
private:
void resetGestureInterpreter(nsecs_t when);
+ explicit TouchpadInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
[[nodiscard]] std::list<NotifyArgs> sendHardwareState(nsecs_t when, nsecs_t readTime,
SelfContainedHardwareState schs);
[[nodiscard]] std::list<NotifyArgs> processGestures(nsecs_t when, nsecs_t readTime);
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.h b/services/inputflinger/reader/mapper/VibratorInputMapper.h
index 384c075..9079c73 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.h
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.h
@@ -22,8 +22,10 @@
class VibratorInputMapper : public InputMapper {
public:
- explicit VibratorInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~VibratorInputMapper();
virtual uint32_t getSources() const override;
@@ -46,6 +48,8 @@
ssize_t mIndex;
nsecs_t mNextStepTime;
+ explicit VibratorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
[[nodiscard]] std::list<NotifyArgs> nextStep();
[[nodiscard]] NotifyVibratorStateArgs stopVibrating();
};
diff --git a/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp b/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp
index 3dc5152..99a6a1f 100644
--- a/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp
+++ b/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp
@@ -781,4 +781,175 @@
WithPointerId(/*index=*/1, /*id=*/0)));
}
+// Motion events without any pointers are invalid, so when a button press is reported in the same
+// frame as a touch down, the button press must be reported second. Similarly with a button release
+// and a touch lift.
+TEST_F(CapturedTouchpadEventConverterTest,
+ ButtonPressedAndReleasedInSameFrameAsTouch_ReportedWithPointers) {
+ CapturedTouchpadEventConverter conv = createConverter();
+
+ 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);
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 1);
+
+ std::list<NotifyArgs> args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS), WithPointerCount(1u),
+ WithCoords(50, 100), WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)));
+
+ processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
+ processAxis(conv, EV_KEY, BTN_TOUCH, 0);
+ processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 0);
+ args = processSync(conv);
+ ASSERT_EQ(3u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithPointerCount(1u),
+ WithCoords(50, 100), WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(0)));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_UP));
+}
+
+// Some touchpads sometimes report a button press before they report the finger touching the pad. In
+// that case we need to wait until the touch comes to report the button press.
+TEST_F(CapturedTouchpadEventConverterTest, ButtonPressedBeforeTouch_ReportedOnceTouchOccurs) {
+ CapturedTouchpadEventConverter conv = createConverter();
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 1);
+ ASSERT_EQ(0u, processSync(conv).size());
+
+ 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);
+
+ std::list<NotifyArgs> args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS), WithPointerCount(1u),
+ WithCoords(50, 100), WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)));
+}
+
+// When all fingers are lifted from a touchpad, we should release any buttons that are down, since
+// we won't be able to report them being lifted later if no pointers are present.
+TEST_F(CapturedTouchpadEventConverterTest, ButtonReleasedAfterTouchLifts_ReportedWithLift) {
+ CapturedTouchpadEventConverter conv = createConverter();
+
+ 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);
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 1);
+
+ std::list<NotifyArgs> args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
+
+ processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
+ processAxis(conv, EV_KEY, BTN_TOUCH, 0);
+ processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
+ args = processSync(conv);
+ ASSERT_EQ(3u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithPointerCount(1u),
+ WithCoords(50, 100), WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(0)));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_UP));
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 0);
+ ASSERT_EQ(0u, processSync(conv).size());
+}
+
+TEST_F(CapturedTouchpadEventConverterTest, MultipleButtonsPressedDuringTouch_ReportedCorrectly) {
+ CapturedTouchpadEventConverter conv = createConverter();
+
+ 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),
+ WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 1);
+ std::list<NotifyArgs> args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
+ WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)));
+
+ processAxis(conv, EV_KEY, BTN_RIGHT, 1);
+ args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
+ WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY),
+ WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY |
+ AMOTION_EVENT_BUTTON_SECONDARY)));
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 0);
+ args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
+ WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY)));
+
+ processAxis(conv, EV_KEY, BTN_RIGHT, 0);
+ args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
+ WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY), WithButtonState(0)));
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index d4103fd..fecd0d1 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -5663,6 +5663,46 @@
AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
}
+/**
+ * Two windows, one on the left and another on the right. The left window is slippery. The right
+ * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
+ * touch moves from the left window into the right window, the gesture should continue to go to the
+ * left window. Touch shouldn't slip because the right window can't receive touches. This test
+ * reproduces a crash.
+ */
+TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+
+ sp<FakeWindowHandle> leftSlipperyWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+ leftSlipperyWindow->setSlippery(true);
+ leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
+
+ sp<FakeWindowHandle> rightDropTouchesWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+ rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
+ rightDropTouchesWindow->setDropInput(true);
+
+ mDispatcher->setInputWindows(
+ {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
+
+ // Start touch in the left window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .build());
+ leftSlipperyWindow->consumeMotionDown();
+
+ // And move it into the right window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
+ .build());
+
+ // Since the right window isn't eligible to receive input, touch does not slip.
+ // The left window continues to receive the gesture.
+ leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
+ rightDropTouchesWindow->assertNoEvents();
+}
+
class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
protected:
static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h
index d969034..2b6655c 100644
--- a/services/inputflinger/tests/InputMapperTest.h
+++ b/services/inputflinger/tests/InputMapperTest.h
@@ -73,6 +73,17 @@
return mapper;
}
+ template <class T, typename... Args>
+ T& constructAndAddMapper(Args... args) {
+ // ensure a device entry exists for this eventHubId
+ mDevice->addEmptyEventHubDevice(EVENTHUB_ID);
+ // configure the empty device
+ configureDevice(/*changes=*/{});
+
+ return mDevice->constructAndAddMapper<T>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
+ args...);
+ }
+
void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
ui::Rotation orientation, const std::string& uniqueId,
std::optional<uint8_t> physicalPort,
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index d56db11..9fbe762 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -2603,13 +2603,13 @@
};
TEST_F(SwitchInputMapperTest, GetSources) {
- SwitchInputMapper& mapper = addMapperAndConfigure<SwitchInputMapper>();
+ SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
ASSERT_EQ(uint32_t(AINPUT_SOURCE_SWITCH), mapper.getSources());
}
TEST_F(SwitchInputMapperTest, GetSwitchState) {
- SwitchInputMapper& mapper = addMapperAndConfigure<SwitchInputMapper>();
+ SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 1);
ASSERT_EQ(1, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
@@ -2619,7 +2619,7 @@
}
TEST_F(SwitchInputMapperTest, Process) {
- SwitchInputMapper& mapper = addMapperAndConfigure<SwitchInputMapper>();
+ SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
std::list<NotifyArgs> out;
out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_LID, 1);
ASSERT_TRUE(out.empty());
@@ -2645,13 +2645,13 @@
};
TEST_F(VibratorInputMapperTest, GetSources) {
- VibratorInputMapper& mapper = addMapperAndConfigure<VibratorInputMapper>();
+ VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
}
TEST_F(VibratorInputMapperTest, GetVibratorIds) {
- VibratorInputMapper& mapper = addMapperAndConfigure<VibratorInputMapper>();
+ VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
}
@@ -2659,7 +2659,7 @@
TEST_F(VibratorInputMapperTest, Vibrate) {
constexpr uint8_t DEFAULT_AMPLITUDE = 192;
constexpr int32_t VIBRATION_TOKEN = 100;
- VibratorInputMapper& mapper = addMapperAndConfigure<VibratorInputMapper>();
+ VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
VibrationElement pattern(2);
VibrationSequence sequence(2);
@@ -2784,7 +2784,7 @@
}
TEST_F(SensorInputMapperTest, GetSources) {
- SensorInputMapper& mapper = addMapperAndConfigure<SensorInputMapper>();
+ SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources());
}
@@ -2792,7 +2792,7 @@
TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
setAccelProperties();
prepareAccelAxes();
- SensorInputMapper& mapper = addMapperAndConfigure<SensorInputMapper>();
+ SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER,
std::chrono::microseconds(10000),
@@ -2822,7 +2822,7 @@
TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
setGyroProperties();
prepareGyroAxes();
- SensorInputMapper& mapper = addMapperAndConfigure<SensorInputMapper>();
+ SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE,
std::chrono::microseconds(10000),
@@ -3862,21 +3862,21 @@
TEST_F(CursorInputMapperTest, WhenModeIsPointer_GetSources_ReturnsMouse) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
}
TEST_F(CursorInputMapperTest, WhenModeIsNavigation_GetSources_ReturnsTrackball) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, mapper.getSources());
}
TEST_F(CursorInputMapperTest, WhenModeIsPointer_PopulateDeviceInfo_ReturnsRangeFromPointerController) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
InputDeviceInfo info;
mapper.populateDeviceInfo(info);
@@ -3906,7 +3906,7 @@
TEST_F(CursorInputMapperTest, WhenModeIsNavigation_PopulateDeviceInfo_ReturnsScaledRange) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
InputDeviceInfo info;
mapper.populateDeviceInfo(info);
@@ -3924,7 +3924,7 @@
TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaState) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -4012,7 +4012,7 @@
TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentXYUpdates) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyMotionArgs args;
@@ -4036,7 +4036,7 @@
TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyMotionArgs args;
@@ -4065,7 +4065,7 @@
TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyMotionArgs args;
@@ -4114,7 +4114,7 @@
// InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
// need to be rotated.
addConfigurationProperty("cursor.orientationAware", "1");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
prepareDisplay(ui::ROTATION_90);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
@@ -4132,7 +4132,7 @@
addConfigurationProperty("cursor.mode", "navigation");
// Since InputReader works in the un-rotated coordinate space, only devices that are not
// orientation-aware are affected by display rotation.
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
clearViewports();
prepareDisplay(ui::ROTATION_0);
@@ -4181,7 +4181,7 @@
TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
mFakePointerController->setPosition(100, 200);
@@ -4435,7 +4435,7 @@
TEST_F(CursorInputMapperTest, Process_WhenModeIsPointer_ShouldMoveThePointerAround) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
mFakePointerController->setPosition(100, 200);
@@ -4456,7 +4456,7 @@
TEST_F(CursorInputMapperTest, Process_PointerCapture) {
addConfigurationProperty("cursor.mode", "pointer");
mFakePolicy->setPointerCapture(true);
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyDeviceResetArgs resetArgs;
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
@@ -4548,7 +4548,7 @@
const VelocityControlParameters testParams(/*scale=*/5.f, /*low threshold=*/0.f,
/*high threshold=*/100.f, /*acceleration=*/10.f);
mFakePolicy->setVelocityControlParams(testParams);
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyDeviceResetArgs resetArgs;
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
@@ -4589,7 +4589,7 @@
TEST_F(CursorInputMapperTest, PointerCaptureDisablesOrientationChanges) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyDeviceResetArgs resetArgs;
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
@@ -4630,7 +4630,7 @@
}
TEST_F(CursorInputMapperTest, ConfigureDisplayId_NoAssociatedViewport) {
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
// Set up the default display.
prepareDisplay(ui::ROTATION_90);
@@ -4656,7 +4656,7 @@
}
TEST_F(CursorInputMapperTest, ConfigureDisplayId_WithAssociatedViewport) {
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
// Set up the default display.
prepareDisplay(ui::ROTATION_90);
@@ -4682,7 +4682,7 @@
}
TEST_F(CursorInputMapperTest, ConfigureDisplayId_IgnoresEventsForMismatchedPointerDisplay) {
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
// Set up the default display as the display on which the pointer should be shown.
prepareDisplay(ui::ROTATION_90);
@@ -4715,7 +4715,7 @@
TEST_F(BluetoothCursorInputMapperTest, TimestampSmoothening) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
nsecs_t kernelEventTime = ARBITRARY_TIME;
nsecs_t expectedEventTime = ARBITRARY_TIME;
@@ -4742,7 +4742,7 @@
TEST_F(BluetoothCursorInputMapperTest, TimestampSmootheningIsCapped) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
nsecs_t expectedEventTime = ARBITRARY_TIME;
process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 1);
@@ -4779,7 +4779,7 @@
TEST_F(BluetoothCursorInputMapperTest, TimestampSmootheningNotUsed) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
nsecs_t kernelEventTime = ARBITRARY_TIME;
nsecs_t expectedEventTime = ARBITRARY_TIME;
@@ -5069,7 +5069,7 @@
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
}
@@ -5078,7 +5078,7 @@
prepareButtons();
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
}
@@ -5089,7 +5089,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Unknown key.
ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
@@ -5117,7 +5117,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Unknown key.
ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
@@ -5145,7 +5145,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
uint8_t flags[2] = { 0, 0 };
ASSERT_TRUE(
@@ -5160,7 +5160,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -5210,7 +5210,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -5331,7 +5331,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -5406,7 +5406,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -5502,7 +5502,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -5592,7 +5592,7 @@
prepareAxes(POSITION);
// InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
// need to be rotated. Touchscreens are orientation-aware by default.
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
@@ -5617,7 +5617,7 @@
// Since InputReader works in the un-rotated coordinate space, only devices that are not
// orientation-aware are affected by display rotation.
addConfigurationProperty("touch.orientationAware", "0");
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
@@ -5686,7 +5686,7 @@
addConfigurationProperty("touch.orientation", "ORIENTATION_0");
clearViewports();
prepareDisplay(ui::ROTATION_0);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
// Orientation 0.
@@ -5710,7 +5710,7 @@
addConfigurationProperty("touch.orientation", "ORIENTATION_90");
clearViewports();
prepareDisplay(ui::ROTATION_0);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
// Orientation 90.
@@ -5734,7 +5734,7 @@
addConfigurationProperty("touch.orientation", "ORIENTATION_180");
clearViewports();
prepareDisplay(ui::ROTATION_0);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
// Orientation 180.
@@ -5758,7 +5758,7 @@
addConfigurationProperty("touch.orientation", "ORIENTATION_270");
clearViewports();
prepareDisplay(ui::ROTATION_0);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
// Orientation 270.
@@ -5782,7 +5782,7 @@
// orientation-aware are affected by display rotation.
addConfigurationProperty("touch.orientationAware", "0");
addConfigurationProperty("touch.orientation", "ORIENTATION_90");
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
@@ -5849,7 +5849,7 @@
prepareAxes(POSITION);
addConfigurationProperty("touch.orientationAware", "1");
prepareDisplay(ui::ROTATION_0);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Set a physical frame in the display viewport.
auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
@@ -5903,7 +5903,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// These calculations are based on the input device calibration documentation.
int32_t rawX = 100;
@@ -5948,7 +5948,7 @@
prepareLocationCalibration();
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
int32_t rawX = 100;
int32_t rawY = 200;
@@ -5970,7 +5970,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
NotifyKeyArgs keyArgs;
@@ -6213,7 +6213,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -6349,7 +6349,7 @@
prepareButtons();
prepareAxes(POSITION);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -6420,7 +6420,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -6491,7 +6491,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Touch down.
processDown(mapper, 100, 200);
@@ -6513,7 +6513,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Set the initial state for the touch pointer.
mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 100);
@@ -6541,7 +6541,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
// Down.
@@ -6569,7 +6569,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
NotifyMotionArgs motionArgs;
@@ -6629,7 +6629,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
// Press a stylus button.
@@ -6670,7 +6670,7 @@
mFakePolicy->setStylusButtonMotionEventsEnabled(false);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
// Press a stylus button.
@@ -6707,7 +6707,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mapper.getSources());
@@ -6723,7 +6723,7 @@
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
mFakePolicy->setPointerController(fakePointerController);
mFakePolicy->setStylusPointerIconEnabled(true);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
processKey(mapper, BTN_TOOL_PEN, 1);
processMove(mapper, 100, 200);
@@ -6747,7 +6747,7 @@
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
mFakePolicy->setPointerController(fakePointerController);
mFakePolicy->setStylusPointerIconEnabled(false);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
processKey(mapper, BTN_TOOL_PEN, 1);
processMove(mapper, 100, 200);
@@ -6765,7 +6765,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Ensure that the device is created as a touchscreen, not touch navigation.
ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
@@ -6799,7 +6799,7 @@
mFakePolicy->updateViewport(*viewport);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Hovering inside the physical frame produces events.
processKey(mapper, BTN_TOOL_PEN, 1);
@@ -6905,7 +6905,7 @@
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -6940,7 +6940,7 @@
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -7069,7 +7069,7 @@
addConfigurationProperty("touch.orientation", ftl::enum_string(touchscreenOrientation).c_str());
prepareDisplay(ui::ROTATION_0);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// If the touchscreen is installed in a rotated orientation relative to the display (i.e. in
// orientations of either 90 or 270) this means the display's natural resolution will be
@@ -7121,7 +7121,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(displayRotation);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
const auto& expectedPoints = kMappedCorners.at(displayRotation);
@@ -7159,7 +7159,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
addConfigurationProperty("touch.orientation", "ORIENTATION_270");
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Ori 270, so width and height swapped
const Rect physicalFrame{0, 0, DISPLAY_HEIGHT, DISPLAY_WIDTH};
@@ -7195,7 +7195,7 @@
prepareDisplay(displayRotation);
__attribute__((unused)) SingleTouchInputMapper& mapper =
- addMapperAndConfigure<SingleTouchInputMapper>();
+ constructAndAddMapper<SingleTouchInputMapper>();
const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
// MotionRanges use display pixels as their units
@@ -7240,7 +7240,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mStylusState.when = ARBITRARY_TIME;
mStylusState.pressure = 0.f;
@@ -7729,7 +7729,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION);
prepareVirtualKeys();
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -8013,7 +8013,7 @@
mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
/*flat*/ 0, /*flat*/ 0, /*resolution*/ 15);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// X and Y axes
assertAxisResolution(mapper, AMOTION_EVENT_AXIS_X, 10 / X_PRECISION);
@@ -8037,7 +8037,7 @@
// We do not add ABS_MT_TOUCH_MAJOR / MINOR or ABS_MT_WIDTH_MAJOR / MINOR axes
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Touch major and minor
assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR);
@@ -8052,7 +8052,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID);
prepareVirtualKeys();
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -8223,7 +8223,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
prepareVirtualKeys();
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -8388,7 +8388,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// These calculations are based on the input device calibration documentation.
int32_t rawX = 100;
@@ -8438,7 +8438,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | TOUCH | TOOL | MINOR);
addConfigurationProperty("touch.size.calibration", "geometric");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// These calculations are based on the input device calibration documentation.
int32_t rawX = 100;
@@ -8478,7 +8478,7 @@
addConfigurationProperty("touch.size.scale", "10");
addConfigurationProperty("touch.size.bias", "160");
addConfigurationProperty("touch.size.isSummed", "1");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// These calculations are based on the input device calibration documentation.
// Note: We only provide a single common touch/tool value because the device is assumed
@@ -8528,7 +8528,7 @@
addConfigurationProperty("touch.size.calibration", "area");
addConfigurationProperty("touch.size.scale", "43");
addConfigurationProperty("touch.size.bias", "3");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// These calculations are based on the input device calibration documentation.
int32_t rawX = 100;
@@ -8560,7 +8560,7 @@
prepareAxes(POSITION | PRESSURE);
addConfigurationProperty("touch.pressure.calibration", "amplitude");
addConfigurationProperty("touch.pressure.scale", "0.01");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
InputDeviceInfo info;
mapper.populateDeviceInfo(info);
@@ -8592,7 +8592,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
NotifyKeyArgs keyArgs;
@@ -8835,7 +8835,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0);
mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0);
@@ -8892,7 +8892,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9043,7 +9043,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9113,7 +9113,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9194,7 +9194,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
mFakePolicy->addInputPortAssociation(usb2, hdmi2);
@@ -9224,7 +9224,7 @@
TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
@@ -9253,7 +9253,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Check source is mouse that would obtain the PointerController.
ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
@@ -9273,7 +9273,7 @@
TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) {
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
prepareDisplay(ui::ROTATION_0);
process(mapper, 10, /*readTime=*/11, EV_ABS, ABS_MT_TRACKING_ID, 1);
@@ -9304,7 +9304,7 @@
/*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
processPosition(mapper, 100, 100);
@@ -9324,7 +9324,7 @@
/*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
processPosition(mapper, 100, 100);
@@ -9346,7 +9346,7 @@
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Finger down
int32_t x = 100, y = 100;
@@ -9389,7 +9389,7 @@
// Setup the first touch screen device.
prepareAxes(POSITION | ID | SLOT);
addConfigurationProperty("touch.deviceType", "touchScreen");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Create the second touch screen device, and enable multi fingers.
const std::string USB2 = "USB2";
@@ -9413,9 +9413,9 @@
String8("touchScreen"));
// Setup the second touch screen device.
- MultiTouchInputMapper& mapper2 =
- device2->addMapper<MultiTouchInputMapper>(SECOND_EVENTHUB_ID,
- mFakePolicy->getReaderConfiguration());
+ device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
+ MultiTouchInputMapper& mapper2 = device2->constructAndAddMapper<
+ MultiTouchInputMapper>(SECOND_EVENTHUB_ID, mFakePolicy->getReaderConfiguration());
std::list<NotifyArgs> unused =
device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
/*changes=*/{});
@@ -9480,7 +9480,7 @@
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
// Unrotated video frame
@@ -9504,7 +9504,7 @@
TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) {
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Unrotated video frame
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
NotifyMotionArgs motionArgs;
@@ -9529,7 +9529,7 @@
// Since InputReader works in the un-rotated coordinate space, only devices that are not
// orientation-aware are affected by display rotation.
addConfigurationProperty("touch.orientationAware", "0");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Unrotated video frame
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
NotifyMotionArgs motionArgs;
@@ -9560,7 +9560,7 @@
TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) {
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Unrotated video frames. There's no rule that they must all have the same dimensions,
// so mix these.
TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
@@ -9583,7 +9583,7 @@
// Since InputReader works in the un-rotated coordinate space, only devices that are not
// orientation-aware are affected by display rotation.
addConfigurationProperty("touch.orientationAware", "0");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Unrotated video frames. There's no rule that they must all have the same dimensions,
// so mix these.
TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
@@ -9620,7 +9620,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
ASSERT_EQ(mDevice->isEnabled(), false);
@@ -9641,7 +9641,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9686,7 +9686,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9734,7 +9734,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9809,7 +9809,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9907,7 +9907,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9979,7 +9979,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -10036,7 +10036,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// First finger down.
processId(mapper, FIRST_TRACKING_ID);
@@ -10077,7 +10077,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// First finger touches down and releases.
processId(mapper, FIRST_TRACKING_ID);
@@ -10105,7 +10105,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
// Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the
@@ -10160,7 +10160,7 @@
std::make_shared<FakePointerController>();
mFakePolicy->setPointerController(fakePointerController);
mFakePolicy->setStylusPointerIconEnabled(true);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
processId(mapper, FIRST_TRACKING_ID);
processPressure(mapper, RAW_PRESSURE_MIN);
@@ -10187,7 +10187,7 @@
std::make_shared<FakePointerController>();
mFakePolicy->setPointerController(fakePointerController);
mFakePolicy->setStylusPointerIconEnabled(false);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
processId(mapper, FIRST_TRACKING_ID);
processPressure(mapper, RAW_PRESSURE_MIN);
@@ -10215,7 +10215,7 @@
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
@@ -10250,7 +10250,7 @@
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
mFakePolicy->setPointerCapture(true);
mFakePolicy->setPointerController(fakePointerController);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// captured touchpad should be a touchpad source
NotifyDeviceResetArgs resetArgs;
@@ -10398,7 +10398,7 @@
mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
mFakePolicy->setPointerController(fakePointerController);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// run uncaptured pointer tests - pushes out generic events
// FINGER 0 DOWN
processId(mapper, 3);
@@ -10459,7 +10459,7 @@
mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
mFakePolicy->setPointerController(fakePointerController);
mFakePolicy->setPointerCapture(false);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// uncaptured touchpad should be a pointer device
ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
@@ -10483,7 +10483,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
nsecs_t kernelEventTime = ARBITRARY_TIME;
nsecs_t expectedEventTime = ARBITRARY_TIME;
@@ -10570,7 +10570,7 @@
// which is greater than fraction of the diagnal length of the touchpad (349).
// Thus, MaxSwipWidth is 750.
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
// Two fingers down at once.
@@ -10630,7 +10630,7 @@
// which is greater than fraction of the diagnal length of the touchpad (349).
// Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
preparePointerMode(/*xResolution=*/5, /*yResolution=*/5);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
// Two fingers down at once.
@@ -10686,7 +10686,7 @@
*/
TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -10781,7 +10781,7 @@
TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
// Place two fingers down.
@@ -10828,7 +10828,7 @@
TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
// Start a stylus gesture.
@@ -10904,7 +10904,7 @@
TEST_F(JoystickInputMapperTest, Configure_AssignsDisplayUniqueId) {
prepareAxes();
- JoystickInputMapper& mapper = addMapperAndConfigure<JoystickInputMapper>();
+ JoystickInputMapper& mapper = constructAndAddMapper<JoystickInputMapper>();
mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
diff --git a/services/inputflinger/tests/fuzzers/FuzzContainer.h b/services/inputflinger/tests/fuzzers/FuzzContainer.h
index 84ac0fd..b992928 100644
--- a/services/inputflinger/tests/fuzzers/FuzzContainer.h
+++ b/services/inputflinger/tests/fuzzers/FuzzContainer.h
@@ -75,9 +75,12 @@
template <class T, typename... Args>
T& getMapper(Args... args) {
- T& mapper = mFuzzDevice->addMapper<T>(mFdp->ConsumeIntegral<int32_t>(), args...);
+ int32_t eventhubId = mFdp->ConsumeIntegral<int32_t>();
+ // ensure a device entry exists for this eventHubId
+ mFuzzDevice->addEmptyEventHubDevice(eventhubId);
configureDevice();
- return mapper;
+
+ return mFuzzDevice->template constructAndAddMapper<T>(eventhubId, args...);
}
};
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 20f4de1..f6ca9e2 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -50,8 +50,6 @@
namespace hal = hardware::graphics::composer::hal;
-ui::Transform::RotationFlags DisplayDevice::sPrimaryDisplayRotationFlags = ui::Transform::ROT_0;
-
DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(
const sp<SurfaceFlinger>& flinger, HWComposer& hwComposer, const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay)
@@ -282,10 +280,6 @@
Rect orientedDisplaySpaceRect) {
mOrientation = orientation;
- if (isPrimary()) {
- sPrimaryDisplayRotationFlags = ui::Transform::toRotationFlags(orientation);
- }
-
// We need to take care of display rotation for globalTransform for case if the panel is not
// installed aligned with device orientation.
const auto transformOrientation = orientation + mPhysicalOrientation;
@@ -326,10 +320,6 @@
return mStagedBrightness;
}
-ui::Transform::RotationFlags DisplayDevice::getPrimaryDisplayRotationFlags() {
- return sPrimaryDisplayRotationFlags;
-}
-
void DisplayDevice::dump(utils::Dumper& dumper) const {
using namespace std::string_view_literals;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 51876e7..dc5f8a8 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -109,8 +109,6 @@
ui::Rotation getPhysicalOrientation() const { return mPhysicalOrientation; }
ui::Rotation getOrientation() const { return mOrientation; }
- static ui::Transform::RotationFlags getPrimaryDisplayRotationFlags();
-
std::optional<float> getStagedBrightness() const REQUIRES(kMainThreadContext);
ui::Transform::RotationFlags getTransformHint() const;
const ui::Transform& getTransform() const;
@@ -274,8 +272,6 @@
const ui::Rotation mPhysicalOrientation;
ui::Rotation mOrientation = ui::ROTATION_0;
- static ui::Transform::RotationFlags sPrimaryDisplayRotationFlags;
-
// Allow nullopt as initial power mode.
using TracedPowerMode = TracedOrdinal<hardware::graphics::composer::hal::PowerMode>;
std::optional<TracedPowerMode> mPowerMode;
diff --git a/services/surfaceflinger/FrontEnd/DisplayInfo.h b/services/surfaceflinger/FrontEnd/DisplayInfo.h
index 76b36fe..218a64a 100644
--- a/services/surfaceflinger/FrontEnd/DisplayInfo.h
+++ b/services/surfaceflinger/FrontEnd/DisplayInfo.h
@@ -28,7 +28,7 @@
ui::Transform transform;
bool receivesInput;
bool isSecure;
- // TODO(b/238781169) can eliminate once sPrimaryDisplayRotationFlags is removed.
+ // TODO(b/259407931): can eliminate once SurfaceFlinger::sActiveDisplayRotationFlags is removed.
bool isPrimary;
bool isVirtual;
ui::Transform::RotationFlags rotationFlags;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index ce7d37e..985c6f9 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -667,6 +667,7 @@
snapshot.relativeLayerMetadata.mMap.clear();
}
+// TODO (b/259407931): Remove.
uint32_t getPrimaryDisplayRotationFlags(
const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
for (auto& [_, display] : displays) {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3371ae2..f12aab7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -254,7 +254,8 @@
mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
}
if (mHadClonedChild) {
- mFlinger->mNumClones--;
+ auto& roots = mFlinger->mLayerMirrorRoots;
+ roots.erase(std::remove(roots.begin(), roots.end(), this), roots.end());
}
if (hasTrustedPresentationListener()) {
mFlinger->mNumTrustedPresentationListeners--;
@@ -1649,8 +1650,8 @@
void Layer::dumpOffscreenDebugInfo(std::string& result) const {
std::string hasBuffer = hasBufferOrSidebandStream() ? " (contains buffer)" : "";
- StringAppendF(&result, "Layer %s%s pid:%d uid:%d\n", getName().c_str(), hasBuffer.c_str(),
- mOwnerPid, mOwnerUid);
+ StringAppendF(&result, "Layer %s%s pid:%d uid:%d%s\n", getName().c_str(), hasBuffer.c_str(),
+ mOwnerPid, mOwnerUid, isHandleAlive() ? " handleAlive" : "");
}
void Layer::onDisconnect() {
@@ -2594,7 +2595,7 @@
mDrawingState.inputInfo = tmpInputInfo;
}
-void Layer::updateMirrorInfo() {
+bool Layer::updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates) {
if (mClonedChild == nullptr || !mClonedChild->isClonedFromAlive()) {
// If mClonedChild is null, there is nothing to mirror. If isClonedFromAlive returns false,
// it means that there is a clone, but the layer it was cloned from has been destroyed. In
@@ -2602,7 +2603,7 @@
// destroyed. The root, this layer, will still be around since the client can continue
// to hold a reference, but no cloned layers will be displayed.
mClonedChild = nullptr;
- return;
+ return true;
}
std::map<sp<Layer>, sp<Layer>> clonedLayersMap;
@@ -2617,6 +2618,13 @@
mClonedChild->updateClonedDrawingState(clonedLayersMap);
mClonedChild->updateClonedChildren(sp<Layer>::fromExisting(this), clonedLayersMap);
mClonedChild->updateClonedRelatives(clonedLayersMap);
+
+ for (Layer* root : cloneRootsPendingUpdates) {
+ if (clonedLayersMap.find(sp<Layer>::fromExisting(root)) != clonedLayersMap.end()) {
+ return false;
+ }
+ }
+ return true;
}
void Layer::updateClonedDrawingState(std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) {
@@ -2764,7 +2772,7 @@
void Layer::setClonedChild(const sp<Layer>& clonedChild) {
mClonedChild = clonedChild;
mHadClonedChild = true;
- mFlinger->mNumClones++;
+ mFlinger->mLayerMirrorRoots.push_back(this);
}
bool Layer::setDropInputMode(gui::DropInputMode mode) {
@@ -2977,7 +2985,7 @@
if (mDrawingState.bufferTransform & ui::Transform::ROT_90) {
std::swap(bufferWidth, bufferHeight);
}
- uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
+ uint32_t invTransform = SurfaceFlinger::getActiveDisplayRotationFlags();
if (mDrawingState.transformToDisplayInverse) {
if (invTransform & ui::Transform::ROT_90) {
std::swap(bufferWidth, bufferHeight);
@@ -3077,6 +3085,7 @@
mDrawingState.desiredPresentTime = desiredPresentTime;
mDrawingState.isAutoTimestamp = isAutoTimestamp;
mDrawingState.latchedVsyncId = info.vsyncId;
+ mDrawingState.useVsyncIdForRefreshRateSelection = info.useForRefreshRateSelection;
mDrawingState.modified = true;
if (!buffer) {
resetDrawingStateBufferInfo();
@@ -3139,15 +3148,31 @@
}
void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerProps) {
+ ATRACE_CALL();
const nsecs_t presentTime = [&] {
- if (!mDrawingState.isAutoTimestamp) return mDrawingState.desiredPresentTime;
+ if (!mDrawingState.isAutoTimestamp) {
+ ATRACE_FORMAT_INSTANT("desiredPresentTime");
+ return mDrawingState.desiredPresentTime;
+ }
- const auto prediction = mFlinger->mFrameTimeline->getTokenManager()->getPredictionsForToken(
- mDrawingState.latchedVsyncId);
- if (prediction.has_value()) return prediction->presentTime;
+ if (mDrawingState.useVsyncIdForRefreshRateSelection) {
+ const auto prediction =
+ mFlinger->mFrameTimeline->getTokenManager()->getPredictionsForToken(
+ mDrawingState.latchedVsyncId);
+ if (prediction.has_value()) {
+ ATRACE_FORMAT_INSTANT("predictedPresentTime");
+ return prediction->presentTime;
+ }
+ }
return static_cast<nsecs_t>(0);
}();
+
+ if (ATRACE_ENABLED() && presentTime > 0) {
+ const auto presentIn = TimePoint::fromNs(presentTime) - TimePoint::now();
+ ATRACE_FORMAT_INSTANT("presentIn %s", to_string(presentIn).c_str());
+ }
+
mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime,
scheduler::LayerHistory::LayerUpdateType::Buffer);
}
@@ -3287,7 +3312,7 @@
}
if (getTransformToDisplayInverse()) {
- uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
+ uint32_t invTransform = SurfaceFlinger::getActiveDisplayRotationFlags();
if (invTransform & ui::Transform::ROT_90) {
std::swap(bufWidth, bufHeight);
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2640c92..38590e6 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -234,6 +234,7 @@
float desiredHdrSdrRatio = 1.f;
gui::CachingHint cachingHint = gui::CachingHint::Enabled;
int64_t latchedVsyncId = 0;
+ bool useVsyncIdForRefreshRateSelection = false;
};
explicit Layer(const LayerCreationArgs& args);
@@ -651,7 +652,7 @@
gui::WindowInfo::Type getWindowType() const { return mWindowType; }
- void updateMirrorInfo();
+ bool updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates);
/*
* doTransaction - process the transaction. This is a good place to figure
diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp
index e713263..f855f27 100644
--- a/services/surfaceflinger/LayerFE.cpp
+++ b/services/surfaceflinger/LayerFE.cpp
@@ -25,8 +25,8 @@
#include <system/window.h>
#include <utils/Log.h>
-#include "DisplayDevice.h"
#include "LayerFE.h"
+#include "SurfaceFlinger.h"
namespace android {
@@ -260,7 +260,7 @@
* the code below applies the primary display's inverse transform to
* the texture transform
*/
- uint32_t transform = DisplayDevice::getPrimaryDisplayRotationFlags();
+ uint32_t transform = SurfaceFlinger::getActiveDisplayRotationFlags();
mat4 tr = inverseOrientation(transform);
/**
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
index f6b5afc..d606cff 100644
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -85,7 +85,7 @@
// If layer is offscreen, update mirroring info if it exists
if (mLayer->isRemovedFromCurrentState()) {
mLayer->traverse(LayerVector::StateSet::Drawing,
- [&](Layer* layer) { layer->updateMirrorInfo(); });
+ [&](Layer* layer) { layer->updateMirrorInfo({}); });
mLayer->traverse(LayerVector::StateSet::Drawing,
[&](Layer* layer) { layer->updateCloneBufferInfo(); });
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3c55caf..b05838b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -110,6 +110,7 @@
#include <unordered_map>
#include <vector>
+#include <gui/LayerStatePermissions.h>
#include <ui/DisplayIdentification.h>
#include "BackgroundExecutor.h"
#include "Client.h"
@@ -355,6 +356,8 @@
PermissionCache::checkPermission(permission, pid, uid);
}
+ui::Transform::RotationFlags SurfaceFlinger::sActiveDisplayRotationFlags = ui::Transform::ROT_0;
+
SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
: mFactory(factory),
mPid(getpid()),
@@ -2618,7 +2621,7 @@
refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
refreshArgs.updatingGeometryThisFrame = mGeometryDirty.exchange(false) || mVisibleRegionsDirty;
- refreshArgs.internalDisplayRotationFlags = DisplayDevice::getPrimaryDisplayRotationFlags();
+ refreshArgs.internalDisplayRotationFlags = getActiveDisplayRotationFlags();
if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) {
refreshArgs.colorTransformMatrix = mDrawingState.colorMatrix;
@@ -3562,6 +3565,8 @@
currentState.orientedDisplaySpaceRect);
if (display->getId() == mActiveDisplayId) {
mActiveDisplayTransformHint = display->getTransformHint();
+ sActiveDisplayRotationFlags =
+ ui::Transform::toRotationFlags(display->getOrientation());
}
}
if (currentState.width != drawingState.width ||
@@ -4024,8 +4029,24 @@
}
commitOffscreenLayers();
- if (mNumClones > 0) {
- mDrawingState.traverse([&](Layer* layer) { layer->updateMirrorInfo(); });
+ if (mLayerMirrorRoots.size() > 0) {
+ std::deque<Layer*> pendingUpdates;
+ pendingUpdates.insert(pendingUpdates.end(), mLayerMirrorRoots.begin(),
+ mLayerMirrorRoots.end());
+ std::vector<Layer*> needsUpdating;
+ for (Layer* cloneRoot : mLayerMirrorRoots) {
+ pendingUpdates.pop_front();
+ if (cloneRoot->isRemovedFromCurrentState()) {
+ continue;
+ }
+ if (cloneRoot->updateMirrorInfo(pendingUpdates)) {
+ } else {
+ needsUpdating.push_back(cloneRoot);
+ }
+ }
+ for (Layer* cloneRoot : needsUpdating) {
+ cloneRoot->updateMirrorInfo({});
+ }
}
}
@@ -4132,7 +4153,7 @@
mBootStage = BootStage::BOOTANIMATION;
}
- if (mNumClones > 0) {
+ if (mLayerMirrorRoots.size() > 0) {
mDrawingState.traverse([&](Layer* layer) { layer->updateCloneBufferInfo(); });
}
@@ -4157,8 +4178,8 @@
leakingParentLayerFound = true;
sp<Layer> parent = sp<Layer>::fromExisting(layer);
while (parent) {
- ALOGE("Parent Layer: %s handleIsAlive: %s", parent->getName().c_str(),
- std::to_string(parent->isHandleAlive()).c_str());
+ ALOGE("Parent Layer: %s%s", parent->getName().c_str(),
+ (parent->isHandleAlive() ? "handleAlive" : ""));
parent = parent->getParent();
}
// Sample up to 100 layers
@@ -4173,21 +4194,28 @@
}
});
- ALOGE("Dumping random sampling of on-screen layers: ");
+ int numLayers = 0;
+ mDrawingState.traverse([&](Layer* layer) { numLayers++; });
+
+ ALOGE("Dumping random sampling of on-screen layers total(%u):", numLayers);
mDrawingState.traverse([&](Layer* layer) {
// Aim to dump about 200 layers to avoid totally trashing
// logcat. On the other hand, if there really are 4096 layers
// something has gone totally wrong its probably the most
// useful information in logcat.
if (rand() % 20 == 13) {
- ALOGE("Layer: %s", layer->getName().c_str());
+ ALOGE("Layer: %s%s", layer->getName().c_str(),
+ (layer->isHandleAlive() ? "handleAlive" : ""));
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
});
ALOGE("Dumping random sampling of off-screen layers total(%zu): ",
mOffscreenLayers.size());
for (Layer* offscreenLayer : mOffscreenLayers) {
if (rand() % 20 == 13) {
- ALOGE("Offscreen-layer: %s", offscreenLayer->getName().c_str());
+ ALOGE("Offscreen-layer: %s%s", offscreenLayer->getName().c_str(),
+ (offscreenLayer->isHandleAlive() ? "handleAlive" : ""));
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
}
}));
@@ -4392,7 +4420,7 @@
transaction.inputWindowCommands,
transaction.desiredPresentTime, transaction.isAutoTimestamp,
std::move(transaction.uncacheBufferIds), transaction.postTime,
- transaction.permissions, transaction.hasListenerCallbacks,
+ transaction.hasListenerCallbacks,
transaction.listenerCallbacks, transaction.originPid,
transaction.originUid, transaction.id);
}
@@ -4471,24 +4499,27 @@
status_t SurfaceFlinger::setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states,
const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
- const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
- bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers,
- bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
- uint64_t transactionId) {
+ InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp,
+ const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
ATRACE_CALL();
- uint32_t permissions =
- callingThreadHasUnscopedSurfaceFlingerAccess() ?
- layer_state_t::Permission::ACCESS_SURFACE_FLINGER : 0;
- // Avoid checking for rotation permissions if the caller already has ACCESS_SURFACE_FLINGER
- // permissions.
- if ((permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) ||
- callingThreadHasPermission(sRotateSurfaceFlinger)) {
- permissions |= layer_state_t::Permission::ROTATE_SURFACE_FLINGER;
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int originPid = ipc->getCallingPid();
+ const int originUid = ipc->getCallingUid();
+ uint32_t permissions = LayerStatePermissions::getTransactionPermissions(originPid, originUid);
+ for (auto composerState : states) {
+ composerState.state.sanitize(permissions);
}
- if (callingThreadHasPermission(sInternalSystemWindow)) {
- permissions |= layer_state_t::Permission::INTERNAL_SYSTEM_WINDOW;
+ for (DisplayState display : displays) {
+ display.sanitize(permissions);
+ }
+
+ if (!inputWindowCommands.empty() &&
+ (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) == 0) {
+ ALOGE("Only privileged callers are allowed to send input commands.");
+ inputWindowCommands.clear();
}
if (flags & (eEarlyWakeupStart | eEarlyWakeupEnd)) {
@@ -4504,10 +4535,6 @@
const int64_t postTime = systemTime();
- IPCThreadState* ipc = IPCThreadState::self();
- const int originPid = ipc->getCallingPid();
- const int originUid = ipc->getCallingUid();
-
std::vector<uint64_t> uncacheBufferIds;
uncacheBufferIds.reserve(uncacheBuffers.size());
for (const auto& uncacheBuffer : uncacheBuffers) {
@@ -4554,12 +4581,11 @@
displays,
flags,
applyToken,
- inputWindowCommands,
+ std::move(inputWindowCommands),
desiredPresentTime,
isAutoTimestamp,
std::move(uncacheBufferIds),
postTime,
- permissions,
hasListenerCallbacks,
listenerCallbacks,
originPid,
@@ -4588,14 +4614,12 @@
const InputWindowCommands& inputWindowCommands,
const int64_t desiredPresentTime, bool isAutoTimestamp,
const std::vector<uint64_t>& uncacheBufferIds,
- const int64_t postTime, uint32_t permissions,
- bool hasListenerCallbacks,
+ const int64_t postTime, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks,
int originPid, int originUid, uint64_t transactionId) {
uint32_t transactionFlags = 0;
if (!mLayerLifecycleManagerEnabled) {
for (DisplayState& display : displays) {
- display.sanitize(permissions);
transactionFlags |= setDisplayStateLocked(display);
}
}
@@ -4612,12 +4636,12 @@
if (mLegacyFrontEndEnabled) {
clientStateFlags |=
setClientStateLocked(frameTimelineInfo, resolvedState, desiredPresentTime,
- isAutoTimestamp, postTime, permissions, transactionId);
+ isAutoTimestamp, postTime, transactionId);
} else /*mLayerLifecycleManagerEnabled*/ {
clientStateFlags |= updateLayerCallbacksAndStats(frameTimelineInfo, resolvedState,
desiredPresentTime, isAutoTimestamp,
- postTime, permissions, transactionId);
+ postTime, transactionId);
}
if ((flags & eAnimation) && resolvedState.state.surface) {
if (const auto layer = LayerHandle::getLayer(resolvedState.state.surface)) {
@@ -4634,12 +4658,7 @@
}
transactionFlags |= clientStateFlags;
-
- if (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) {
- transactionFlags |= addInputWindowCommands(inputWindowCommands);
- } else if (!inputWindowCommands.empty()) {
- ALOGE("Only privileged callers are allowed to send input commands.");
- }
+ transactionFlags |= addInputWindowCommands(inputWindowCommands);
for (uint64_t uncacheBufferId : uncacheBufferIds) {
mBufferIdsToUncache.push_back(uncacheBufferId);
@@ -4676,7 +4695,6 @@
uint32_t transactionFlags = 0;
for (auto& transaction : transactions) {
for (DisplayState& display : transaction.displays) {
- display.sanitize(transaction.permissions);
transactionFlags |= setDisplayStateLocked(display);
}
}
@@ -4775,10 +4793,8 @@
uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTimelineInfo,
ResolvedComposerState& composerState,
int64_t desiredPresentTime, bool isAutoTimestamp,
- int64_t postTime, uint32_t permissions,
- uint64_t transactionId) {
+ int64_t postTime, uint64_t transactionId) {
layer_state_t& s = composerState.state;
- s.sanitize(permissions);
std::vector<ListenerCallbacks> filteredListeners;
for (auto& listener : s.listeners) {
@@ -5127,10 +5143,8 @@
ResolvedComposerState& composerState,
int64_t desiredPresentTime,
bool isAutoTimestamp, int64_t postTime,
- uint32_t permissions,
uint64_t transactionId) {
layer_state_t& s = composerState.state;
- s.sanitize(permissions);
std::vector<ListenerCallbacks> filteredListeners;
for (auto& listener : s.listeners) {
@@ -5412,7 +5426,6 @@
const nsecs_t now = systemTime();
state.desiredPresentTime = now;
state.postTime = now;
- state.permissions = layer_state_t::ACCESS_SURFACE_FLINGER;
state.originPid = mPid;
state.originUid = static_cast<int>(getuid());
const uint64_t transactionId = (static_cast<uint64_t>(mPid) << 32) | mUniqueTransactionId++;
@@ -5488,14 +5501,19 @@
onActiveDisplayChangedLocked(activeDisplay.get(), *display);
}
- // Keep uclamp in a separate syscall and set it before changing to RT due to b/190237315.
- // We can merge the syscall later.
- if (SurfaceFlinger::setSchedAttr(true) != NO_ERROR) {
- ALOGW("Couldn't set uclamp.min on display on: %s\n", strerror(errno));
+ if (displayId == mActiveDisplayId) {
+ // TODO(b/281692563): Merge the syscalls. For now, keep uclamp in a separate syscall and
+ // set it before SCHED_FIFO due to b/190237315.
+ if (setSchedAttr(true) != NO_ERROR) {
+ ALOGW("Failed to set uclamp.min after powering on active display: %s",
+ strerror(errno));
+ }
+ if (setSchedFifo(true) != NO_ERROR) {
+ ALOGW("Failed to set SCHED_FIFO after powering on active display: %s",
+ strerror(errno));
+ }
}
- if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
- ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno));
- }
+
getHwComposer().setPowerMode(displayId, mode);
if (displayId == mActiveDisplayId && mode != hal::PowerMode::DOZE_SUSPEND) {
setHWCVsyncEnabled(displayId,
@@ -5509,15 +5527,21 @@
scheduleComposite(FrameHint::kActive);
} else if (mode == hal::PowerMode::OFF) {
// Turn off the display
- if (SurfaceFlinger::setSchedFifo(false) != NO_ERROR) {
- ALOGW("Couldn't set SCHED_OTHER on display off: %s\n", strerror(errno));
- }
- if (SurfaceFlinger::setSchedAttr(false) != NO_ERROR) {
- ALOGW("Couldn't set uclamp.min on display off: %s\n", strerror(errno));
- }
- if (displayId == mActiveDisplayId && *currentModeOpt != hal::PowerMode::DOZE_SUSPEND) {
- mScheduler->disableHardwareVsync(displayId, true);
- mScheduler->enableSyntheticVsync();
+
+ if (displayId == mActiveDisplayId) {
+ if (setSchedFifo(false) != NO_ERROR) {
+ ALOGW("Failed to set SCHED_OTHER after powering off active display: %s",
+ strerror(errno));
+ }
+ if (setSchedAttr(false) != NO_ERROR) {
+ ALOGW("Failed set uclamp.min after powering off active display: %s",
+ strerror(errno));
+ }
+
+ if (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND) {
+ mScheduler->disableHardwareVsync(displayId, true);
+ mScheduler->enableSyntheticVsync();
+ }
}
// Make sure HWVsync is disabled before turning off the display
@@ -7957,6 +7981,7 @@
onActiveDisplaySizeChanged(activeDisplay);
mActiveDisplayTransformHint = activeDisplay.getTransformHint();
+ sActiveDisplayRotationFlags = ui::Transform::toRotationFlags(activeDisplay.getOrientation());
// The policy of the new active/pacesetter display may have changed while it was inactive. In
// that case, its preferred mode has not been propagated to HWC (via setDesiredActiveMode). In
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8eaa1c7..1182b84 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -296,8 +296,7 @@
// the client can no longer modify this layer directly.
void onHandleDestroyed(BBinder* handle, sp<Layer>& layer, uint32_t layerId);
- // TODO: Remove atomic if move dtor to main thread CL lands
- std::atomic<uint32_t> mNumClones;
+ std::vector<Layer*> mLayerMirrorRoots;
TransactionCallbackInvoker& getTransactionCallbackInvoker() {
return mTransactionCallbackInvoker;
@@ -332,6 +331,14 @@
const DisplayDevice* getDisplayFromLayerStack(ui::LayerStack)
REQUIRES(mStateLock, kMainThreadContext);
+ // TODO (b/259407931): Remove.
+ // TODO (b/281857977): This should be annotated with REQUIRES(kMainThreadContext), but this
+ // would require thread safety annotations throughout the frontend (in particular Layer and
+ // LayerFE).
+ static ui::Transform::RotationFlags getActiveDisplayRotationFlags() {
+ return sActiveDisplayRotationFlags;
+ }
+
protected:
// We're reference counted, never destroy SurfaceFlinger directly
virtual ~SurfaceFlinger();
@@ -511,7 +518,7 @@
status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
Vector<ComposerState>& state, const Vector<DisplayState>& displays,
uint32_t flags, const sp<IBinder>& applyToken,
- const InputWindowCommands& inputWindowCommands,
+ InputWindowCommands inputWindowCommands,
int64_t desiredPresentTime, bool isAutoTimestamp,
const std::vector<client_cache_t>& uncacheBuffers,
bool hasListenerCallbacks,
@@ -732,14 +739,16 @@
/*
* Transactions
*/
- bool applyTransactionState(
- const FrameTimelineInfo& info, std::vector<ResolvedComposerState>& state,
- Vector<DisplayState>& displays, uint32_t flags,
- const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
- bool isAutoTimestamp, const std::vector<uint64_t>& uncacheBufferIds,
- const int64_t postTime, uint32_t permissions, bool hasListenerCallbacks,
- const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid,
- uint64_t transactionId) REQUIRES(mStateLock);
+ bool applyTransactionState(const FrameTimelineInfo& info,
+ std::vector<ResolvedComposerState>& state,
+ Vector<DisplayState>& displays, uint32_t flags,
+ const InputWindowCommands& inputWindowCommands,
+ const int64_t desiredPresentTime, bool isAutoTimestamp,
+ const std::vector<uint64_t>& uncacheBufferIds,
+ const int64_t postTime, bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks,
+ int originPid, int originUid, uint64_t transactionId)
+ REQUIRES(mStateLock);
// Flush pending transactions that were presented after desiredPresentTime.
// For test only
bool flushTransactionQueues(VsyncId) REQUIRES(kMainThreadContext);
@@ -760,12 +769,11 @@
uint32_t setClientStateLocked(const FrameTimelineInfo&, ResolvedComposerState&,
int64_t desiredPresentTime, bool isAutoTimestamp,
- int64_t postTime, uint32_t permissions, uint64_t transactionId)
- REQUIRES(mStateLock);
+ int64_t postTime, uint64_t transactionId) REQUIRES(mStateLock);
uint32_t updateLayerCallbacksAndStats(const FrameTimelineInfo&, ResolvedComposerState&,
int64_t desiredPresentTime, bool isAutoTimestamp,
- int64_t postTime, uint32_t permissions,
- uint64_t transactionId) REQUIRES(mStateLock);
+ int64_t postTime, uint64_t transactionId)
+ REQUIRES(mStateLock);
uint32_t getTransactionFlags() const;
// Sets the masked bits, and schedules a commit if needed.
@@ -1389,6 +1397,10 @@
std::atomic<ui::Transform::RotationFlags> mActiveDisplayTransformHint;
+ // Must only be accessed on the main thread.
+ // TODO (b/259407931): Remove.
+ static ui::Transform::RotationFlags sActiveDisplayRotationFlags;
+
bool isRefreshRateOverlayEnabled() const REQUIRES(mStateLock) {
return hasDisplay(
[](const auto& display) { return display.isRefreshRateOverlayEnabled(); });
diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h
index 35c8b6c..62a7dfd 100644
--- a/services/surfaceflinger/TransactionState.h
+++ b/services/surfaceflinger/TransactionState.h
@@ -54,7 +54,7 @@
const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands,
int64_t desiredPresentTime, bool isAutoTimestamp,
- std::vector<uint64_t> uncacheBufferIds, int64_t postTime, uint32_t permissions,
+ std::vector<uint64_t> uncacheBufferIds, int64_t postTime,
bool hasListenerCallbacks, std::vector<ListenerCallbacks> listenerCallbacks,
int originPid, int originUid, uint64_t transactionId)
: frameTimelineInfo(frameTimelineInfo),
@@ -67,7 +67,6 @@
isAutoTimestamp(isAutoTimestamp),
uncacheBufferIds(std::move(uncacheBufferIds)),
postTime(postTime),
- permissions(permissions),
hasListenerCallbacks(hasListenerCallbacks),
listenerCallbacks(listenerCallbacks),
originPid(originPid),
@@ -126,7 +125,6 @@
bool isAutoTimestamp;
std::vector<uint64_t> uncacheBufferIds;
int64_t postTime;
- uint32_t permissions;
bool hasListenerCallbacks;
std::vector<ListenerCallbacks> listenerCallbacks;
int originPid;
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 0495678..cf23169 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -91,7 +91,7 @@
// Set uclamp.min setting on all threads, maybe an overkill but we want
// to cover important threads like RenderEngine.
if (SurfaceFlinger::setSchedAttr(true) != NO_ERROR) {
- ALOGW("Couldn't set uclamp.min: %s\n", strerror(errno));
+ ALOGW("Failed to set uclamp.min during boot: %s", strerror(errno));
}
// The binder threadpool we start will inherit sched policy and priority
@@ -155,7 +155,7 @@
startDisplayService(); // dependency on SF getting registered above
if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
- ALOGW("Couldn't set to SCHED_FIFO: %s", strerror(errno));
+ ALOGW("Failed to set SCHED_FIFO during boot: %s", strerror(errno));
}
// run surface flinger in this thread
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index 4a45eb5..69e9a16 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -31,6 +31,7 @@
#include <utils/String8.h>
#include <functional>
#include "utils/ScreenshotUtils.h"
+#include "utils/WindowInfosListenerUtils.h"
namespace android {
@@ -378,6 +379,58 @@
ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
}
+TEST_F(CredentialsTest, TransactionPermissionTest) {
+ WindowInfosListenerUtils windowInfosListenerUtils;
+ std::string name = "Test Layer";
+ sp<IBinder> token = sp<BBinder>::make();
+ WindowInfo windowInfo;
+ windowInfo.name = name;
+ windowInfo.token = token;
+ sp<SurfaceControl> surfaceControl =
+ mComposerClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceBufferState);
+ const Rect crop(0, 0, 100, 100);
+ {
+ UIDFaker f(AID_SYSTEM);
+ Transaction()
+ .setLayerStack(surfaceControl, ui::DEFAULT_LAYER_STACK)
+ .show(surfaceControl)
+ .setLayer(surfaceControl, INT32_MAX - 1)
+ .setCrop(surfaceControl, crop)
+ .setInputWindowInfo(surfaceControl, windowInfo)
+ .apply();
+ }
+
+ // Called from non privileged process
+ Transaction().setTrustedOverlay(surfaceControl, true);
+ {
+ UIDFaker f(AID_SYSTEM);
+ auto windowIsPresentAndNotTrusted = [&](const std::vector<WindowInfo>& windowInfos) {
+ auto foundWindowInfo =
+ WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos);
+ if (!foundWindowInfo) {
+ return false;
+ }
+ return !foundWindowInfo->inputConfig.test(WindowInfo::InputConfig::TRUSTED_OVERLAY);
+ };
+ windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndNotTrusted);
+ }
+
+ {
+ UIDFaker f(AID_SYSTEM);
+ Transaction().setTrustedOverlay(surfaceControl, true);
+ auto windowIsPresentAndTrusted = [&](const std::vector<WindowInfo>& windowInfos) {
+ auto foundWindowInfo =
+ WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos);
+ if (!foundWindowInfo) {
+ return false;
+ }
+ return foundWindowInfo->inputConfig.test(WindowInfo::InputConfig::TRUSTED_OVERLAY);
+ };
+ windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndTrusted);
+ }
+}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/WindowInfosListener_test.cpp b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
index 3f27360..ad9a674 100644
--- a/services/surfaceflinger/tests/WindowInfosListener_test.cpp
+++ b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
@@ -20,11 +20,13 @@
#include <private/android_filesystem_config.h>
#include <cstdint>
#include <future>
+#include "utils/WindowInfosListenerUtils.h"
namespace android {
using Transaction = SurfaceComposerClient::Transaction;
using gui::DisplayInfo;
using gui::WindowInfo;
+constexpr auto findMatchingWindowInfo = WindowInfosListenerUtils::findMatchingWindowInfo;
using WindowInfosPredicate = std::function<bool(const std::vector<WindowInfo>&)>;
@@ -37,45 +39,14 @@
void TearDown() override { seteuid(AID_ROOT); }
- struct WindowInfosListener : public gui::WindowInfosListener {
- public:
- WindowInfosListener(WindowInfosPredicate predicate, std::promise<void>& promise)
- : mPredicate(std::move(predicate)), mPromise(promise) {}
-
- void onWindowInfosChanged(const gui::WindowInfosUpdate& update) override {
- if (mPredicate(update.windowInfos)) {
- mPromise.set_value();
- }
- }
-
- private:
- WindowInfosPredicate mPredicate;
- std::promise<void>& mPromise;
- };
-
sp<SurfaceComposerClient> mClient;
+ WindowInfosListenerUtils mWindowInfosListenerUtils;
- bool waitForWindowInfosPredicate(WindowInfosPredicate predicate) {
- std::promise<void> promise;
- auto listener = sp<WindowInfosListener>::make(std::move(predicate), promise);
- mClient->addWindowInfosListener(listener);
- auto future = promise.get_future();
- bool satisfied = future.wait_for(std::chrono::seconds{1}) == std::future_status::ready;
- mClient->removeWindowInfosListener(listener);
- return satisfied;
+ bool waitForWindowInfosPredicate(const WindowInfosPredicate& predicate) {
+ return mWindowInfosListenerUtils.waitForWindowInfosPredicate(std::move(predicate));
}
};
-const WindowInfo* findMatchingWindowInfo(const WindowInfo& targetWindowInfo,
- const std::vector<WindowInfo>& windowInfos) {
- for (const WindowInfo& windowInfo : windowInfos) {
- if (windowInfo.token == targetWindowInfo.token) {
- return &windowInfo;
- }
- }
- return nullptr;
-}
-
TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) {
std::string name = "Test Layer";
sp<IBinder> token = sp<BBinder>::make();
diff --git a/services/surfaceflinger/tests/unittests/ActiveDisplayRotationFlagsTest.cpp b/services/surfaceflinger/tests/unittests/ActiveDisplayRotationFlagsTest.cpp
new file mode 100644
index 0000000..7077523
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/ActiveDisplayRotationFlagsTest.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LibSurfaceFlingerUnittests"
+
+#include "DisplayTransactionTestHelpers.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace {
+
+struct ActiveDisplayRotationFlagsTest : DisplayTransactionTest {
+ static constexpr bool kWithMockScheduler = false;
+ ActiveDisplayRotationFlagsTest() : DisplayTransactionTest(kWithMockScheduler) {}
+
+ void SetUp() override {
+ injectMockScheduler(kInnerDisplayId);
+
+ // Inject inner and outer displays with uninitialized power modes.
+ constexpr bool kInitPowerMode = false;
+ {
+ InnerDisplayVariant::injectHwcDisplay<kInitPowerMode>(this);
+ auto injector = InnerDisplayVariant::makeFakeExistingDisplayInjector(this);
+ injector.setPowerMode(std::nullopt);
+ injector.setRefreshRateSelector(mFlinger.scheduler()->refreshRateSelector());
+ mInnerDisplay = injector.inject();
+ }
+ {
+ OuterDisplayVariant::injectHwcDisplay<kInitPowerMode>(this);
+ auto injector = OuterDisplayVariant::makeFakeExistingDisplayInjector(this);
+ injector.setPowerMode(std::nullopt);
+ mOuterDisplay = injector.inject();
+ }
+
+ mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
+ mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);
+
+ // The flags are a static variable, so by modifying them in the test, we
+ // are modifying the real ones used by SurfaceFlinger. Save the original
+ // flags so we can restore them on teardown. This isn't perfect - the
+ // phone may have been rotated during the test, so we're restoring the
+ // wrong flags. But if the phone is rotated, this may also fail the test.
+ mOldRotationFlags = mFlinger.mutableActiveDisplayRotationFlags();
+
+ // Reset to the expected default state.
+ mFlinger.mutableActiveDisplayRotationFlags() = ui::Transform::ROT_0;
+ }
+
+ void TearDown() override { mFlinger.mutableActiveDisplayRotationFlags() = mOldRotationFlags; }
+
+ static inline PhysicalDisplayId kInnerDisplayId = InnerDisplayVariant::DISPLAY_ID::get();
+ static inline PhysicalDisplayId kOuterDisplayId = OuterDisplayVariant::DISPLAY_ID::get();
+
+ sp<DisplayDevice> mInnerDisplay, mOuterDisplay;
+ ui::Transform::RotationFlags mOldRotationFlags;
+};
+
+TEST_F(ActiveDisplayRotationFlagsTest, defaultRotation) {
+ ASSERT_EQ(ui::Transform::ROT_0, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotate90) {
+ auto displayToken = mInnerDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_90;
+
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ ASSERT_EQ(ui::Transform::ROT_90, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotate90_inactive) {
+ auto displayToken = mOuterDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_90;
+
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ ASSERT_EQ(ui::Transform::ROT_0, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotateBoth_innerActive) {
+ auto displayToken = mInnerDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_180;
+
+ displayToken = mOuterDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_270;
+
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ ASSERT_EQ(ui::Transform::ROT_180, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotateBoth_outerActive) {
+ mFlinger.mutableActiveDisplayId() = kOuterDisplayId;
+ auto displayToken = mInnerDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_180;
+
+ displayToken = mOuterDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_270;
+
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ ASSERT_EQ(ui::Transform::ROT_270, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, onActiveDisplayChanged) {
+ auto displayToken = mInnerDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_180;
+
+ displayToken = mOuterDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_270;
+
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ ASSERT_EQ(ui::Transform::ROT_180, SurfaceFlinger::getActiveDisplayRotationFlags());
+
+ mFlinger.onActiveDisplayChanged(mInnerDisplay.get(), *mOuterDisplay);
+ ASSERT_EQ(ui::Transform::ROT_270, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 55705ca..70f8a83 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -70,6 +70,7 @@
":libsurfaceflinger_mock_sources",
":libsurfaceflinger_sources",
"libsurfaceflinger_unittest_main.cpp",
+ "ActiveDisplayRotationFlagsTest.cpp",
"CompositionTest.cpp",
"DisplayIdGeneratorTest.cpp",
"DisplayTransactionTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index a189c00..8e18a3f 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -600,6 +600,10 @@
auto& mutablePrimaryHwcDisplayId() { return getHwComposer().mPrimaryHwcDisplayId; }
auto& mutableActiveDisplayId() { return mFlinger->mActiveDisplayId; }
+ auto& mutableActiveDisplayRotationFlags() {
+ return SurfaceFlinger::sActiveDisplayRotationFlags;
+ }
+
auto fromHandle(const sp<IBinder>& handle) { return LayerHandle::getLayer(handle); }
~TestableSurfaceFlinger() {
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index dbb7c6c..6a641b3 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -386,7 +386,7 @@
transaction.applyToken,
transaction.inputWindowCommands,
transaction.desiredPresentTime,
- transaction.isAutoTimestamp, {}, systemTime(), 0,
+ transaction.isAutoTimestamp, {}, systemTime(),
mHasListenerCallbacks, mCallbacks, getpid(),
static_cast<int>(getuid()), transaction.id);
mFlinger.setTransactionStateInternal(transactionState);
diff --git a/services/surfaceflinger/tests/utils/WindowInfosListenerUtils.h b/services/surfaceflinger/tests/utils/WindowInfosListenerUtils.h
new file mode 100644
index 0000000..8e28a75
--- /dev/null
+++ b/services/surfaceflinger/tests/utils/WindowInfosListenerUtils.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <gui/SurfaceComposerClient.h>
+#include <private/android_filesystem_config.h>
+#include <cstdint>
+#include <future>
+
+namespace android {
+using Transaction = SurfaceComposerClient::Transaction;
+using gui::DisplayInfo;
+using gui::WindowInfo;
+
+using WindowInfosPredicate = std::function<bool(const std::vector<WindowInfo>&)>;
+
+class WindowInfosListenerUtils {
+public:
+ WindowInfosListenerUtils() { mClient = sp<SurfaceComposerClient>::make(); }
+
+ bool waitForWindowInfosPredicate(const WindowInfosPredicate& predicate) {
+ std::promise<void> promise;
+ auto listener = sp<WindowInfosListener>::make(std::move(predicate), promise);
+ mClient->addWindowInfosListener(listener);
+ auto future = promise.get_future();
+ bool satisfied = future.wait_for(std::chrono::seconds{1}) == std::future_status::ready;
+ mClient->removeWindowInfosListener(listener);
+ return satisfied;
+ }
+
+ static const WindowInfo* findMatchingWindowInfo(const WindowInfo& targetWindowInfo,
+ const std::vector<WindowInfo>& windowInfos) {
+ for (const WindowInfo& windowInfo : windowInfos) {
+ if (windowInfo.token == targetWindowInfo.token) {
+ return &windowInfo;
+ }
+ }
+ return nullptr;
+ }
+
+private:
+ struct WindowInfosListener : public gui::WindowInfosListener {
+ public:
+ WindowInfosListener(WindowInfosPredicate predicate, std::promise<void>& promise)
+ : mPredicate(std::move(predicate)), mPromise(promise) {}
+
+ void onWindowInfosChanged(const gui::WindowInfosUpdate& update) override {
+ if (mPredicate(update.windowInfos)) {
+ mPromise.set_value();
+ }
+ }
+
+ private:
+ WindowInfosPredicate mPredicate;
+ std::promise<void>& mPromise;
+ };
+
+ sp<SurfaceComposerClient> mClient;
+};
+
+} // namespace android