diff options
90 files changed, 1170 insertions, 526 deletions
diff --git a/cmds/installd/file_parsing.h b/cmds/installd/file_parsing.h index 88801ca671..0ec5abbd15 100644 --- a/cmds/installd/file_parsing.h +++ b/cmds/installd/file_parsing.h @@ -51,7 +51,7 @@ bool ParseFile(std::istream& input_stream, Func parse) { } template<typename Func> -bool ParseFile(std::string_view str_file, Func parse) { +bool ParseFile(const std::string& str_file, Func parse) { std::ifstream ifs(str_file); if (!ifs.is_open()) { return false; diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh index ae7d8e04d4..2d889fd80d 100644 --- a/cmds/installd/otapreopt_script.sh +++ b/cmds/installd/otapreopt_script.sh @@ -50,7 +50,27 @@ else exit 1 fi -if pm art on-ota-staged --slot "$TARGET_SLOT_SUFFIX"; then +# A source that infinitely emits arbitrary lines. +# When connected to STDIN of another process, this source keeps STDIN open until +# the consumer process closes STDIN or this script dies. +function infinite_source { + while echo .; do + sleep 1 + done +} + +# Delegate to Pre-reboot Dexopt, a feature of ART Service. +# ART Service decides what to do with this request: +# - If Pre-reboot Dexopt is disabled or unsupported, the command returns +# non-zero. This is always the case if the current system is Android 14 or +# earlier. +# - If Pre-reboot Dexopt is enabled in synchronous mode, the command blocks +# until Pre-reboot Dexopt finishes, and returns zero no matter it succeeds or +# not. This is the default behavior if the current system is Android 15. +# - If Pre-reboot Dexopt is enabled in asynchronous mode, the command schedules +# an asynchronous job and returns 0 immediately. The job will then run by the +# job scheduler when the device is idle and charging. +if infinite_source | pm art on-ota-staged --slot "$TARGET_SLOT_SUFFIX"; then # Handled by Pre-reboot Dexopt. exit 0 fi diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index 7a855e1c5b..6594aa6309 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -15,7 +15,6 @@ */ #define LOG_TAG "BpBinder" -#define ATRACE_TAG ATRACE_TAG_AIDL //#define LOG_NDEBUG 0 #include <binder/BpBinder.h> @@ -24,15 +23,10 @@ #include <binder/IResultReceiver.h> #include <binder/RpcSession.h> #include <binder/Stability.h> +#include <binder/Trace.h> #include <stdio.h> -#ifndef __TRUSTY__ -#include <cutils/trace.h> -#else -#define ATRACE_INT(...) -#endif - #include "BuildFlags.h" #include "file.h" @@ -216,7 +210,7 @@ sp<BpBinder> BpBinder::create(int32_t handle) { sTrackingMap[trackedUid]++; } uint32_t numProxies = sBinderProxyCount.fetch_add(1, std::memory_order_relaxed); - ATRACE_INT("binder_proxies", numProxies); + binder::os::trace_int(ATRACE_TAG_AIDL, "binder_proxies", numProxies); uint32_t numLastWarned = sBinderProxyCountWarned.load(std::memory_order_relaxed); uint32_t numNextWarn = numLastWarned + kBinderProxyCountWarnInterval; if (numProxies >= numNextWarn) { @@ -640,8 +634,8 @@ BpBinder::~BpBinder() { } } } - [[maybe_unused]] uint32_t numProxies = --sBinderProxyCount; - ATRACE_INT("binder_proxies", numProxies); + uint32_t numProxies = --sBinderProxyCount; + binder::os::trace_int(ATRACE_TAG_AIDL, "binder_proxies", numProxies); if (ipc) { ipc->expungeHandle(binderHandle(), this); ipc->decWeakHandle(binderHandle()); diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index ef96f803c3..fbc812571a 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -1027,6 +1027,7 @@ status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) goto finish; case BR_FROZEN_REPLY: + ALOGW("Transaction failed because process frozen."); err = FAILED_TRANSACTION; goto finish; @@ -1578,8 +1579,8 @@ void IPCThreadState::logExtendedError() { } #endif - ALOGE_IF(ee.command != BR_OK, "Binder transaction failure: %d/%d/%d", - ee.id, ee.command, ee.param); + ALOGE_IF(ee.command != BR_OK, "Binder transaction failure. id: %d, BR_*: %d, error: %d (%s)", + ee.id, ee.command, ee.param, strerror(-ee.param)); } void IPCThreadState::freeBuffer(const uint8_t* data, size_t /*dataSize*/, diff --git a/libs/binder/OS.h b/libs/binder/OS.h index 5703eb7515..04869a170f 100644 --- a/libs/binder/OS.h +++ b/libs/binder/OS.h @@ -26,6 +26,7 @@ namespace android::binder::os { LIBBINDER_EXPORTED void trace_begin(uint64_t tag, const char* name); LIBBINDER_EXPORTED void trace_end(uint64_t tag); +LIBBINDER_EXPORTED void trace_int(uint64_t tag, const char* name, int32_t value); status_t setNonBlocking(borrowed_fd fd); diff --git a/libs/binder/OS_android.cpp b/libs/binder/OS_android.cpp index 1eace857fb..893ee15578 100644 --- a/libs/binder/OS_android.cpp +++ b/libs/binder/OS_android.cpp @@ -44,6 +44,10 @@ void trace_end(uint64_t tag) { atrace_end(tag); } +void trace_int(uint64_t tag, const char* name, int32_t value) { + atrace_int(tag, name, value); +} + } // namespace os // Legacy trace symbol. To be removed once all of downstream rebuilds. diff --git a/libs/binder/OS_non_android_linux.cpp b/libs/binder/OS_non_android_linux.cpp index 01f3fe0329..0c64eb61c6 100644 --- a/libs/binder/OS_non_android_linux.cpp +++ b/libs/binder/OS_non_android_linux.cpp @@ -39,6 +39,8 @@ void trace_begin(uint64_t, const char*) {} void trace_end(uint64_t) {} +void trace_int(uint64_t, const char*, int32_t) {} + uint64_t GetThreadId() { return syscall(__NR_gettid); } diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp index 15047152a1..5b157cc7c3 100644 --- a/libs/binder/PersistableBundle.cpp +++ b/libs/binder/PersistableBundle.cpp @@ -82,13 +82,12 @@ namespace os { } \ } -#define RETURN_IF_ENTRY_ERASED(map, key) \ - { \ - size_t num_erased = (map).erase(key); \ - if (num_erased) { \ - ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \ - return num_erased; \ - } \ +#define RETURN_IF_ENTRY_ERASED(map, key) \ + { \ + size_t num_erased = (map).erase(key); \ + if (num_erased) { \ + return num_erased; \ + } \ } status_t PersistableBundle::writeToParcel(Parcel* parcel) const { diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index fb2781be59..8485ecd835 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -516,22 +516,23 @@ String8 ProcessState::getDriverName() { return mDriverName; } -static unique_fd open_driver(const char* driver) { +static unique_fd open_driver(const char* driver, String8* error) { auto fd = unique_fd(open(driver, O_RDWR | O_CLOEXEC)); if (!fd.ok()) { - PLOGE("Opening '%s' failed", driver); + error->appendFormat("%d (%s) Opening '%s' failed", errno, strerror(errno), driver); return {}; } int vers = 0; int result = ioctl(fd.get(), BINDER_VERSION, &vers); if (result == -1) { - PLOGE("Binder ioctl to obtain version failed"); + error->appendFormat("%d (%s) Binder ioctl to obtain version failed", errno, + strerror(errno)); return {}; } if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) { - ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! " - "ioctl() return value: %d", - vers, BINDER_CURRENT_PROTOCOL_VERSION, result); + error->appendFormat("Binder driver protocol(%d) does not match user space protocol(%d)! " + "ioctl() return value: %d", + vers, BINDER_CURRENT_PROTOCOL_VERSION, result); return {}; } size_t maxThreads = DEFAULT_MAX_BINDER_THREADS; @@ -565,7 +566,8 @@ ProcessState::ProcessState(const char* driver) mThreadPoolStarted(false), mThreadPoolSeq(1), mCallRestriction(CallRestriction::NONE) { - unique_fd opened = open_driver(driver); + String8 error; + unique_fd opened = open_driver(driver, &error); if (opened.ok()) { // mmap the binder, providing a chunk of virtual address space to receive transactions. @@ -580,8 +582,9 @@ ProcessState::ProcessState(const char* driver) } #ifdef __ANDROID__ - LOG_ALWAYS_FATAL_IF(!opened.ok(), "Binder driver '%s' could not be opened. Terminating.", - driver); + LOG_ALWAYS_FATAL_IF(!opened.ok(), + "Binder driver '%s' could not be opened. Error: %s. Terminating.", + error.c_str(), driver); #endif if (opened.ok()) { diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h index e8d9829b5d..40102bb9f0 100644 --- a/libs/binder/include/binder/RpcSession.h +++ b/libs/binder/include/binder/RpcSession.h @@ -129,9 +129,9 @@ public: setupUnixDomainSocketBootstrapClient(binder::unique_fd bootstrap); /** - * Connects to an RPC server at the CVD & port. + * Connects to an RPC server at the CID & port. */ - [[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockClient(unsigned int cvd, unsigned int port); + [[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockClient(unsigned int cid, unsigned int port); /** * Connects to an RPC server at the given address and port. diff --git a/libs/binder/include/binder/Trace.h b/libs/binder/include/binder/Trace.h index 268157e705..2f450cb36b 100644 --- a/libs/binder/include/binder/Trace.h +++ b/libs/binder/include/binder/Trace.h @@ -41,6 +41,7 @@ namespace os { // libcutils/libutils void trace_begin(uint64_t tag, const char* name); void trace_end(uint64_t tag); +void trace_int(uint64_t tag, const char* name, int32_t value); } // namespace os class LIBBINDER_EXPORTED ScopedTrace { diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp index bd24a20370..8771af52f3 100644 --- a/libs/binder/tests/Android.bp +++ b/libs/binder/tests/Android.bp @@ -62,6 +62,7 @@ cc_test { "binderStatusUnitTest.cpp", "binderMemoryHeapBaseUnitTest.cpp", "binderRecordedTransactionTest.cpp", + "binderPersistableBundleTest.cpp", ], shared_libs: [ "libbinder", @@ -461,6 +462,20 @@ cc_test { } cc_test { + name: "binderRpcTestNoKernelAtAll", + defaults: [ + "binderRpcTest_defaults", + "binderRpcTest_static_defaults", + ], + static_libs: [ + "libbinder_rpc_no_kernel", + ], + cflags: [ + "-DBINDER_NO_KERNEL_IPC_TESTING", + ], +} + +cc_test { name: "binderRpcTestSingleThreaded", defaults: [ "binderRpcTest_defaults", diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp index 9788d9d1dd..00406edcf2 100644 --- a/libs/binder/tests/binderLibTest.cpp +++ b/libs/binder/tests/binderLibTest.cpp @@ -38,6 +38,7 @@ #include <binder/IServiceManager.h> #include <binder/RpcServer.h> #include <binder/RpcSession.h> +#include <binder/Status.h> #include <binder/unique_fd.h> #include <utils/Flattenable.h> @@ -57,6 +58,7 @@ using namespace std::string_literals; using namespace std::chrono_literals; using android::base::testing::HasValue; using android::base::testing::Ok; +using android::binder::Status; using android::binder::unique_fd; using testing::ExplainMatchResult; using testing::Matcher; @@ -253,7 +255,7 @@ class BinderLibTest : public ::testing::Test { public: virtual void SetUp() { m_server = static_cast<BinderLibTestEnv *>(binder_env)->getServer(); - IPCThreadState::self()->restoreCallingWorkSource(0); + IPCThreadState::self()->restoreCallingWorkSource(0); } virtual void TearDown() { } @@ -461,6 +463,35 @@ TEST_F(BinderLibTest, AddManagerToManager) { EXPECT_EQ(NO_ERROR, sm->addService(String16("binderLibTest-manager"), binder)); } +TEST_F(BinderLibTest, RegisterForNotificationsFailure) { + auto sm = defaultServiceManager(); + using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback; + class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback { + void onServiceRegistration(const String16&, const sp<IBinder>&) override {} + virtual ~LocalRegistrationCallbackImpl() {} + }; + sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make(); + + EXPECT_EQ(BAD_VALUE, sm->registerForNotifications(String16("ValidName"), nullptr)); + EXPECT_EQ(UNKNOWN_ERROR, sm->registerForNotifications(String16("InvalidName!$"), cb)); +} + +TEST_F(BinderLibTest, UnregisterForNotificationsFailure) { + auto sm = defaultServiceManager(); + using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback; + class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback { + void onServiceRegistration(const String16&, const sp<IBinder>&) override {} + virtual ~LocalRegistrationCallbackImpl() {} + }; + sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make(); + + EXPECT_EQ(OK, sm->registerForNotifications(String16("ValidName"), cb)); + + EXPECT_EQ(BAD_VALUE, sm->unregisterForNotifications(String16("ValidName"), nullptr)); + EXPECT_EQ(BAD_VALUE, sm->unregisterForNotifications(String16("AnotherValidName"), cb)); + EXPECT_EQ(BAD_VALUE, sm->unregisterForNotifications(String16("InvalidName!!!"), cb)); +} + TEST_F(BinderLibTest, WasParceled) { auto binder = sp<BBinder>::make(); EXPECT_FALSE(binder->wasParceled()); diff --git a/libs/binder/tests/binderPersistableBundleTest.cpp b/libs/binder/tests/binderPersistableBundleTest.cpp new file mode 100644 index 0000000000..392e018735 --- /dev/null +++ b/libs/binder/tests/binderPersistableBundleTest.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <binder/Parcel.h> +#include <binder/PersistableBundle.h> +#include <gtest/gtest.h> +#include <numeric> + +using android::OK; +using android::Parcel; +using android::status_t; +using android::String16; +using android::String8; +using android::os::PersistableBundle; + +namespace android { + +inline std::string to_string(String16 const& str) { + return String8{str}.c_str(); +} + +namespace os { + +template <typename T> +inline std::ostream& operator<<(std::ostream& out, std::vector<T> const& vec) { + using std::to_string; + auto str = + std::accumulate(vec.begin(), vec.end(), std::string{}, + [](std::string const& a, auto const& b) { return a + to_string(b); }); + return out << str; +} + +inline std::ostream& operator<<(std::ostream& out, PersistableBundle const& pb) { +#define PRINT(TYPENAME, TYPE) \ + for (auto const& key : pb.get##TYPENAME##Keys()) { \ + TYPE val{}; \ + pb.get##TYPENAME(key, &val); \ + out << #TYPE " " << key << ": " << val << std::endl; \ + } + + out << "size: " << pb.size() << std::endl; + PRINT(Boolean, bool); + PRINT(Int, int); + PRINT(Long, int64_t); + PRINT(Double, double); + PRINT(String, String16); + PRINT(BooleanVector, std::vector<bool>); + PRINT(IntVector, std::vector<int32_t>); + PRINT(LongVector, std::vector<int64_t>); + PRINT(DoubleVector, std::vector<double>); + PRINT(StringVector, std::vector<String16>); + PRINT(PersistableBundle, PersistableBundle); + +#undef PRINT + + return out; +} + +} // namespace os +} // namespace android + +static const String16 kKey{"key"}; + +static PersistableBundle createSimplePersistableBundle() { + PersistableBundle pb{}; + pb.putInt(kKey, 64); + return pb; +} + +#define TEST_PUT_AND_GET(TYPENAME, TYPE, ...) \ + TEST(PersistableBundle, PutAndGet##TYPENAME) { \ + TYPE const expected{__VA_ARGS__}; \ + PersistableBundle pb{}; \ + \ + pb.put##TYPENAME(kKey, expected); \ + \ + std::set<String16> expectedKeys{kKey}; \ + EXPECT_EQ(pb.get##TYPENAME##Keys(), expectedKeys); \ + \ + TYPE val{}; \ + EXPECT_TRUE(pb.get##TYPENAME(kKey, &val)); \ + EXPECT_EQ(val, expected); \ + } + +TEST_PUT_AND_GET(Boolean, bool, true); +TEST_PUT_AND_GET(Int, int, 64); +TEST_PUT_AND_GET(Long, int64_t, 42); +TEST_PUT_AND_GET(Double, double, 42.64); +TEST_PUT_AND_GET(String, String16, String16{"foo"}); +TEST_PUT_AND_GET(BooleanVector, std::vector<bool>, true, true); +TEST_PUT_AND_GET(IntVector, std::vector<int32_t>, 1, 2); +TEST_PUT_AND_GET(LongVector, std::vector<int64_t>, 1, 2); +TEST_PUT_AND_GET(DoubleVector, std::vector<double>, 4.2, 5.9); +TEST_PUT_AND_GET(StringVector, std::vector<String16>, String16{"foo"}, String16{"bar"}); +TEST_PUT_AND_GET(PersistableBundle, PersistableBundle, createSimplePersistableBundle()); + +TEST(PersistableBundle, ParcelAndUnparcel) { + PersistableBundle expected = createSimplePersistableBundle(); + PersistableBundle out{}; + + Parcel p{}; + EXPECT_EQ(expected.writeToParcel(&p), 0); + p.setDataPosition(0); + EXPECT_EQ(out.readFromParcel(&p), 0); + + EXPECT_EQ(expected, out); +} + +TEST(PersistableBundle, OverwriteKey) { + PersistableBundle pb{}; + + pb.putInt(kKey, 64); + pb.putDouble(kKey, 0.5); + + EXPECT_EQ(pb.getIntKeys().size(), 0); + EXPECT_EQ(pb.getDoubleKeys().size(), 1); + + double out; + EXPECT_TRUE(pb.getDouble(kKey, &out)); + EXPECT_EQ(out, 0.5); +} diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index c044d3943d..19882ea1a9 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -1278,7 +1278,7 @@ static std::vector<BinderRpc::ParamType> getBinderRpcParams() { for (const auto& clientVersion : testVersions()) { for (const auto& serverVersion : testVersions()) { for (bool singleThreaded : {false, true}) { - for (bool noKernel : {false, true}) { + for (bool noKernel : noKernelValues()) { ret.push_back(BinderRpc::ParamType{ .type = type, .security = security, @@ -1299,7 +1299,7 @@ static std::vector<BinderRpc::ParamType> getBinderRpcParams() { .clientVersion = RPC_WIRE_PROTOCOL_VERSION, .serverVersion = RPC_WIRE_PROTOCOL_VERSION, .singleThreaded = false, - .noKernel = false, + .noKernel = !kEnableKernelIpcTesting, }); } } diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h index acc0373bf4..dc22647b85 100644 --- a/libs/binder/tests/binderRpcTestCommon.h +++ b/libs/binder/tests/binderRpcTestCommon.h @@ -64,6 +64,12 @@ namespace android { +#ifdef BINDER_NO_KERNEL_IPC_TESTING +constexpr bool kEnableKernelIpcTesting = false; +#else +constexpr bool kEnableKernelIpcTesting = true; +#endif + constexpr char kLocalInetAddress[] = "127.0.0.1"; enum class RpcSecurity { RAW, TLS }; @@ -72,6 +78,14 @@ static inline std::vector<RpcSecurity> RpcSecurityValues() { return {RpcSecurity::RAW, RpcSecurity::TLS}; } +static inline std::vector<bool> noKernelValues() { + std::vector<bool> values = {true}; + if (kEnableKernelIpcTesting) { + values.push_back(false); + } + return values; +} + static inline bool hasExperimentalRpc() { #ifdef BINDER_RPC_TO_TRUSTY_TEST // Trusty services do not support the experimental version, diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp index 09db32609a..157ab3c85d 100644 --- a/libs/binder/trusty/OS.cpp +++ b/libs/binder/trusty/OS.cpp @@ -40,6 +40,8 @@ void trace_begin(uint64_t, const char*) {} void trace_end(uint64_t) {} +void trace_int(uint64_t, const char*, int32_t) {} + uint64_t GetThreadId() { return 0; } diff --git a/libs/input/InputConsumer.cpp b/libs/input/InputConsumer.cpp index abc039281a..fcf490d5f9 100644 --- a/libs/input/InputConsumer.cpp +++ b/libs/input/InputConsumer.cpp @@ -181,7 +181,8 @@ inline bool isPointerEvent(int32_t source) { } bool shouldResampleTool(ToolType toolType) { - return toolType == ToolType::FINGER || toolType == ToolType::UNKNOWN; + return toolType == ToolType::FINGER || toolType == ToolType::MOUSE || + toolType == ToolType::STYLUS || toolType == ToolType::UNKNOWN; } } // namespace @@ -592,6 +593,11 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event, ALOGD_IF(debugResampling(), "Not resampled, missing id %d", id); return; } + if (!shouldResampleTool(event->getToolType(i))) { + ALOGD_IF(debugResampling(), + "Not resampled, containing unsupported tool type at pointer %d", id); + return; + } } // Find the data to use for resampling. @@ -639,10 +645,18 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event, } if (current->eventTime == sampleTime) { - // Prevents having 2 events with identical times and coordinates. + ALOGD_IF(debugResampling(), "Not resampled, 2 events with identical times."); return; } + for (size_t i = 0; i < pointerCount; i++) { + uint32_t id = event->getPointerId(i); + if (!other->idBits.hasBit(id)) { + ALOGD_IF(debugResampling(), "Not resampled, the other doesn't have pointer id %d.", id); + return; + } + } + // Resample touch coordinates. History oldLastResample; oldLastResample.initializeFrom(touchState.lastResample); @@ -670,22 +684,16 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event, const PointerCoords& currentCoords = current->getPointerById(id); resampledCoords = currentCoords; resampledCoords.isResampled = true; - if (other->idBits.hasBit(id) && shouldResampleTool(event->getToolType(i))) { - const PointerCoords& otherCoords = other->getPointerById(id); - resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X, - lerp(currentCoords.getX(), otherCoords.getX(), alpha)); - resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, - lerp(currentCoords.getY(), otherCoords.getY(), alpha)); - ALOGD_IF(debugResampling(), - "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), " - "other (%0.3f, %0.3f), alpha %0.3f", - id, resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(), - currentCoords.getY(), otherCoords.getX(), otherCoords.getY(), alpha); - } else { - ALOGD_IF(debugResampling(), "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f)", id, - resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(), - currentCoords.getY()); - } + const PointerCoords& otherCoords = other->getPointerById(id); + resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X, + lerp(currentCoords.getX(), otherCoords.getX(), alpha)); + resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, + lerp(currentCoords.getY(), otherCoords.getY(), alpha)); + ALOGD_IF(debugResampling(), + "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), " + "other (%0.3f, %0.3f), alpha %0.3f", + id, resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(), + currentCoords.getY(), otherCoords.getX(), otherCoords.getY(), alpha); } event->addSample(sampleTime, touchState.lastResample.pointers); diff --git a/libs/input/tests/TouchResampling_test.cpp b/libs/input/tests/TouchResampling_test.cpp index 2dc9fdb7f1..8d8b5300c1 100644 --- a/libs/input/tests/TouchResampling_test.cpp +++ b/libs/input/tests/TouchResampling_test.cpp @@ -297,10 +297,9 @@ TEST_F(TouchResamplingTest, EventIsResampledWithDifferentId) { } /** - * Stylus pointer coordinates are not resampled, but an event is still generated for the batch with - * a resampled timestamp and should be marked as such. + * Stylus pointer coordinates are resampled. */ -TEST_F(TouchResamplingTest, StylusCoordinatesNotResampledFor) { +TEST_F(TouchResamplingTest, StylusEventIsResampled) { std::chrono::nanoseconds frameTime; std::vector<InputEventEntry> entries, expectedEntries; @@ -330,15 +329,91 @@ TEST_F(TouchResamplingTest, StylusCoordinatesNotResampledFor) { // id x y {10ms, {{0, 20, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE}, {20ms, {{0, 30, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE}, - // A resampled event is generated, but the stylus coordinates are not resampled. {25ms, - {{0, 30, 30, .toolType = ToolType::STYLUS, .isResampled = true}}, + {{0, 35, 30, .toolType = ToolType::STYLUS, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}, }; consumeInputEventEntries(expectedEntries, frameTime); } /** + * Mouse pointer coordinates are resampled. + */ +TEST_F(TouchResamplingTest, MouseEventIsResampled) { + std::chrono::nanoseconds frameTime; + std::vector<InputEventEntry> entries, expectedEntries; + + // Initial ACTION_DOWN should be separate, because the first consume event will only return + // InputEvent with a single action. + entries = { + // id x y + {0ms, {{0, 10, 20, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_DOWN}, + }; + publishInputEventEntries(entries); + frameTime = 5ms; + expectedEntries = { + // id x y + {0ms, {{0, 10, 20, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_DOWN}, + }; + consumeInputEventEntries(expectedEntries, frameTime); + + // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y + entries = { + // id x y + {10ms, {{0, 20, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE}, + {20ms, {{0, 30, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE}, + }; + publishInputEventEntries(entries); + frameTime = 35ms; + expectedEntries = { + // id x y + {10ms, {{0, 20, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE}, + {20ms, {{0, 30, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE}, + {25ms, + {{0, 35, 30, .toolType = ToolType::MOUSE, .isResampled = true}}, + AMOTION_EVENT_ACTION_MOVE}, + }; + consumeInputEventEntries(expectedEntries, frameTime); +} + +/** + * Motion events with palm tool type are not resampled. + */ +TEST_F(TouchResamplingTest, PalmEventIsNotResampled) { + std::chrono::nanoseconds frameTime; + std::vector<InputEventEntry> entries, expectedEntries; + + // Initial ACTION_DOWN should be separate, because the first consume event will only return + // InputEvent with a single action. + entries = { + // id x y + {0ms, {{0, 10, 20, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_DOWN}, + }; + publishInputEventEntries(entries); + frameTime = 5ms; + expectedEntries = { + // id x y + {0ms, {{0, 10, 20, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_DOWN}, + }; + consumeInputEventEntries(expectedEntries, frameTime); + + // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y + entries = { + // id x y + {10ms, {{0, 20, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE}, + {20ms, {{0, 30, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE}, + }; + publishInputEventEntries(entries); + frameTime = 35ms; + expectedEntries = { + // id x y + {10ms, {{0, 20, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE}, + {20ms, {{0, 30, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE}, + }; + consumeInputEventEntries(expectedEntries, frameTime); +} + +/** * Event should not be resampled when sample time is equal to event time. */ TEST_F(TouchResamplingTest, SampleTimeEqualsEventTime) { diff --git a/libs/renderengine/skia/VulkanInterface.cpp b/libs/renderengine/skia/VulkanInterface.cpp index fc16c5626d..5e756b03ed 100644 --- a/libs/renderengine/skia/VulkanInterface.cpp +++ b/libs/renderengine/skia/VulkanInterface.cpp @@ -197,7 +197,9 @@ void VulkanInterface::onVkDeviceFault(void* callbackContext, const std::string& LOG_ALWAYS_FATAL("%s", crashMsg.str().c_str()); }; -static GrVkGetProc sGetProc = [](const char* proc_name, VkInstance instance, VkDevice device) { +static skgpu::VulkanGetProc sGetProc = [](const char* proc_name, + VkInstance instance, + VkDevice device) { if (device != VK_NULL_HANDLE) { return vkGetDeviceProcAddr(device, proc_name); } @@ -604,7 +606,7 @@ void VulkanInterface::teardown() { mQueue = VK_NULL_HANDLE; // Implicitly destroyed by destroying mDevice. mQueueIndex = 0; mApiVersion = 0; - mGrExtensions = GrVkExtensions(); + mGrExtensions = skgpu::VulkanExtensions(); mGrGetProc = nullptr; mIsProtected = false; mIsRealtimePriority = false; diff --git a/libs/renderengine/skia/VulkanInterface.h b/libs/renderengine/skia/VulkanInterface.h index af0489a470..f20b00251b 100644 --- a/libs/renderengine/skia/VulkanInterface.h +++ b/libs/renderengine/skia/VulkanInterface.h @@ -17,7 +17,8 @@ #pragma once #include <include/gpu/vk/GrVkBackendContext.h> -#include <include/gpu/vk/GrVkExtensions.h> +#include <include/gpu/vk/VulkanExtensions.h> +#include <include/gpu/vk/VulkanTypes.h> #include <vulkan/vulkan.h> @@ -85,12 +86,12 @@ private: VkQueue mQueue = VK_NULL_HANDLE; int mQueueIndex = 0; uint32_t mApiVersion = 0; - GrVkExtensions mGrExtensions; + skgpu::VulkanExtensions mGrExtensions; VkPhysicalDeviceFeatures2* mPhysicalDeviceFeatures2 = nullptr; VkPhysicalDeviceSamplerYcbcrConversionFeatures* mSamplerYcbcrConversionFeatures = nullptr; VkPhysicalDeviceProtectedMemoryFeatures* mProtectedMemoryFeatures = nullptr; VkPhysicalDeviceFaultFeaturesEXT* mDeviceFaultFeatures = nullptr; - GrVkGetProc mGrGetProc = nullptr; + skgpu::VulkanGetProc mGrGetProc = nullptr; bool mIsProtected = false; bool mIsRealtimePriority = false; diff --git a/libs/sensor/libsensor_flags.aconfig b/libs/sensor/libsensor_flags.aconfig index c511f4a72f..cbf3055fd4 100644 --- a/libs/sensor/libsensor_flags.aconfig +++ b/libs/sensor/libsensor_flags.aconfig @@ -8,3 +8,10 @@ flag { bug: "322228259" is_fixed_read_only: true } + +flag { + name: "sensor_event_queue_report_sensor_usage_in_tracing" + namespace: "sensors" + description: "When this flag is enabled, sensor event queue will report sensor usage when system trace is enabled." + bug: "333132224" +}
\ No newline at end of file diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp index 02453ef7a0..7d3a2df550 100644 --- a/services/inputflinger/PointerChoreographer.cpp +++ b/services/inputflinger/PointerChoreographer.cpp @@ -30,10 +30,6 @@ namespace android { -namespace input_flags = com::android::input::flags; -static const bool HIDE_TOUCH_INDICATORS_FOR_SECURE_WINDOWS = - input_flags::hide_pointer_indicators_for_secure_windows(); - namespace { bool isFromMouse(const NotifyMotionArgs& args) { @@ -106,8 +102,31 @@ std::unordered_set<ui::LogicalDisplayId> getPrivacySensitiveDisplaysFromWindowIn // --- PointerChoreographer --- -PointerChoreographer::PointerChoreographer(InputListenerInterface& listener, +PointerChoreographer::PointerChoreographer(InputListenerInterface& inputListener, PointerChoreographerPolicyInterface& policy) + : PointerChoreographer( + inputListener, policy, + [](const sp<android::gui::WindowInfosListener>& listener) { + auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{}, + std::vector<android::gui::DisplayInfo>{}); +#if defined(__ANDROID__) + SurfaceComposerClient::getDefault()->addWindowInfosListener(listener, + &initialInfo); +#endif + return initialInfo.first; + }, + [](const sp<android::gui::WindowInfosListener>& listener) { +#if defined(__ANDROID__) + SurfaceComposerClient::getDefault()->removeWindowInfosListener(listener); +#endif + }) { +} + +PointerChoreographer::PointerChoreographer( + android::InputListenerInterface& listener, + android::PointerChoreographerPolicyInterface& policy, + const android::PointerChoreographer::WindowListenerRegisterConsumer& registerListener, + const android::PointerChoreographer::WindowListenerUnregisterConsumer& unregisterListener) : mTouchControllerConstructor([this]() { return mPolicy.createPointerController( PointerControllerInterface::ControllerType::TOUCH); @@ -117,7 +136,9 @@ PointerChoreographer::PointerChoreographer(InputListenerInterface& listener, mDefaultMouseDisplayId(ui::LogicalDisplayId::DEFAULT), mNotifiedPointerDisplayId(ui::LogicalDisplayId::INVALID), mShowTouchesEnabled(false), - mStylusPointerIconEnabled(false) {} + mStylusPointerIconEnabled(false), + mRegisterListener(registerListener), + mUnregisterListener(unregisterListener) {} PointerChoreographer::~PointerChoreographer() { std::scoped_lock _l(mLock); @@ -125,6 +146,7 @@ PointerChoreographer::~PointerChoreographer() { return; } mWindowInfoListener->onPointerChoreographerDestroyed(); + mUnregisterListener(mWindowInfoListener); } void PointerChoreographer::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) { @@ -391,7 +413,7 @@ void PointerChoreographer::processDeviceReset(const NotifyDeviceResetArgs& args) } void PointerChoreographer::onControllerAddedOrRemovedLocked() { - if (!HIDE_TOUCH_INDICATORS_FOR_SECURE_WINDOWS) { + if (!com::android::input::flags::hide_pointer_indicators_for_secure_windows()) { return; } bool requireListener = !mTouchPointersByDevice.empty() || !mMousePointersByDisplay.empty() || @@ -399,18 +421,10 @@ void PointerChoreographer::onControllerAddedOrRemovedLocked() { if (requireListener && mWindowInfoListener == nullptr) { mWindowInfoListener = sp<PointerChoreographerDisplayInfoListener>::make(this); - auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{}, - std::vector<android::gui::DisplayInfo>{}); -#if defined(__ANDROID__) - SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener, - &initialInfo); -#endif - mWindowInfoListener->setInitialDisplayInfos(initialInfo.first); + mWindowInfoListener->setInitialDisplayInfos(mRegisterListener(mWindowInfoListener)); onPrivacySensitiveDisplaysChangedLocked(mWindowInfoListener->getPrivacySensitiveDisplays()); } else if (!requireListener && mWindowInfoListener != nullptr) { -#if defined(__ANDROID__) - SurfaceComposerClient::getDefault()->removeWindowInfosListener(mWindowInfoListener); -#endif + mUnregisterListener(mWindowInfoListener); mWindowInfoListener = nullptr; } else if (requireListener && mWindowInfoListener != nullptr) { // controller may have been added to an existing privacy sensitive display, we need to diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h index 11c5a0c6c7..d9b075f3ee 100644 --- a/services/inputflinger/PointerChoreographer.h +++ b/services/inputflinger/PointerChoreographer.h @@ -108,10 +108,6 @@ public: void notifyDeviceReset(const NotifyDeviceResetArgs& args) override; void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override; - // Public because it's also used by tests to simulate the WindowInfosListener callback - void onPrivacySensitiveDisplaysChanged( - const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays); - void dump(std::string& dump) override; private: @@ -139,6 +135,8 @@ private: void onPrivacySensitiveDisplaysChangedLocked( const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays) REQUIRES(mLock); + void onPrivacySensitiveDisplaysChanged( + const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays); /* This listener keeps tracks of visible privacy sensitive displays and updates the * choreographer if there are any changes. @@ -194,6 +192,20 @@ private: bool mShowTouchesEnabled GUARDED_BY(mLock); bool mStylusPointerIconEnabled GUARDED_BY(mLock); std::set<ui::LogicalDisplayId /*displayId*/> mDisplaysWithPointersHidden; + +protected: + using WindowListenerRegisterConsumer = std::function<std::vector<gui::WindowInfo>( + const sp<android::gui::WindowInfosListener>&)>; + using WindowListenerUnregisterConsumer = + std::function<void(const sp<android::gui::WindowInfosListener>&)>; + explicit PointerChoreographer(InputListenerInterface& listener, + PointerChoreographerPolicyInterface&, + const WindowListenerRegisterConsumer& registerListener, + const WindowListenerUnregisterConsumer& unregisterListener); + +private: + const WindowListenerRegisterConsumer mRegisterListener; + const WindowListenerUnregisterConsumer mUnregisterListener; }; } // namespace android diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index dae2b6119c..527edb6fe6 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -4885,10 +4885,11 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* ev mLock.lock(); - if (policyFlags & POLICY_FLAG_FILTERED) { - // The events from InputFilter impersonate real hardware devices. Check these - // events for consistency and print an error. An inconsistent event sent from - // InputFilter could cause a crash in the later stages of dispatching pipeline. + { + // Verify all injected streams, whether the injection is coming from apps or from + // input filter. Print an error if the stream becomes inconsistent with this event. + // An inconsistent injected event sent could cause a crash in the later stages of + // dispatching pipeline. auto [it, _] = mInputFilterVerifiersByDisplay.try_emplace(displayId, std::string("Injection on ") + @@ -6388,9 +6389,8 @@ void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime, } if (dispatchEntry.eventEntry->type == EventEntry::Type::KEY) { - const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*(dispatchEntry.eventEntry)); fallbackKeyEntry = - afterKeyEventLockedInterruptable(connection, dispatchEntry, keyEntry, handled); + afterKeyEventLockedInterruptable(connection, &dispatchEntry, handled); } } // End critical section: The -LockedInterruptable methods may have released the lock. @@ -6614,8 +6614,17 @@ void InputDispatcher::processConnectionResponsiveLocked(const Connection& connec } std::unique_ptr<const KeyEntry> InputDispatcher::afterKeyEventLockedInterruptable( - const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry, - const KeyEntry& keyEntry, bool handled) { + const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry, bool handled) { + // The dispatchEntry is currently valid, but it might point to a deleted object after we release + // the lock. For simplicity, make copies of the data of interest here and assume that + // 'dispatchEntry' is not valid after this section. + // Hold a strong reference to the EventEntry to ensure it's valid for the duration of this + // function, even if the DispatchEntry gets destroyed and releases its share of the ownership. + std::shared_ptr<const EventEntry> eventEntry = dispatchEntry->eventEntry; + const bool hasForegroundTarget = dispatchEntry->hasForegroundTarget(); + const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*(eventEntry)); + // To prevent misuse, ensure dispatchEntry is no longer valid. + dispatchEntry = nullptr; if (keyEntry.flags & AKEY_EVENT_FLAG_FALLBACK) { if (!handled) { // Report the key as unhandled, since the fallback was not handled. @@ -6632,7 +6641,7 @@ std::unique_ptr<const KeyEntry> InputDispatcher::afterKeyEventLockedInterruptabl connection->inputState.removeFallbackKey(originalKeyCode); } - if (handled || !dispatchEntry.hasForegroundTarget()) { + if (handled || !hasForegroundTarget) { // If the application handles the original key for which we previously // generated a fallback or if the window is not a foreground window, // then cancel the associated fallback key, if any. diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 6240e7fe72..e2fc7a0d4f 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -687,8 +687,8 @@ private: std::map<ui::LogicalDisplayId /*displayId*/, InputVerifier> mVerifiersByDisplay; // Returns a fallback KeyEntry that should be sent to the connection, if required. std::unique_ptr<const KeyEntry> afterKeyEventLockedInterruptable( - const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry, - const KeyEntry& keyEntry, bool handled) REQUIRES(mLock); + const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry, + bool handled) REQUIRES(mLock); // Find touched state and touched window by token. std::tuple<TouchState*, TouchedWindow*, ui::LogicalDisplayId /*displayId*/> diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index b807b2714f..ed05bddc74 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -403,7 +403,7 @@ std::list<NotifyArgs> InputDevice::process(const RawEvent* rawEvents, size_t cou mDropUntilNextSync = true; } else { for_each_mapper_in_subdevice(rawEvent->deviceId, [&](InputMapper& mapper) { - out += mapper.process(rawEvent); + out += mapper.process(*rawEvent); }); } --count; diff --git a/services/inputflinger/reader/controller/PeripheralController.cpp b/services/inputflinger/reader/controller/PeripheralController.cpp index 27b9d23ff5..49ad8b5d69 100644 --- a/services/inputflinger/reader/controller/PeripheralController.cpp +++ b/services/inputflinger/reader/controller/PeripheralController.cpp @@ -418,7 +418,11 @@ void PeripheralController::configureLights() { } rawInfos.insert_or_assign(rawId, rawInfo.value()); // Check if this is a group LEDs for player ID - std::regex lightPattern("([a-z]+)([0-9]+)"); + // The name for the light has already been parsed and is the `function` + // value; for player ID lights the function is expected to be `player-#`. + // However, the Sony driver will use `sony#` instead on SIXAXIS + // gamepads. + std::regex lightPattern("(player|sony)-?([0-9]+)"); std::smatch results; if (std::regex_match(rawInfo->name, results, lightPattern)) { std::string commonName = results[1].str(); diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp index 09a5f08a23..90685dec2b 100644 --- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp +++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp @@ -155,8 +155,8 @@ std::list<NotifyArgs> CapturedTouchpadEventConverter::process(const RawEvent& ra mMotionAccumulator.finishSync(); } - mCursorButtonAccumulator.process(&rawEvent); - mMotionAccumulator.process(&rawEvent); + mCursorButtonAccumulator.process(rawEvent); + mMotionAccumulator.process(rawEvent); return out; } diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp index c67314dbcf..20cdb59b00 100644 --- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp @@ -55,14 +55,14 @@ void CursorMotionAccumulator::clearRelativeAxes() { mRelY = 0; } -void CursorMotionAccumulator::process(const RawEvent* rawEvent) { - if (rawEvent->type == EV_REL) { - switch (rawEvent->code) { +void CursorMotionAccumulator::process(const RawEvent& rawEvent) { + if (rawEvent.type == EV_REL) { + switch (rawEvent.code) { case REL_X: - mRelX = rawEvent->value; + mRelX = rawEvent.value; break; case REL_Y: - mRelY = rawEvent->value; + mRelY = rawEvent.value; break; } } @@ -215,16 +215,16 @@ std::list<NotifyArgs> CursorInputMapper::reset(nsecs_t when) { return InputMapper::reset(when); } -std::list<NotifyArgs> CursorInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> CursorInputMapper::process(const RawEvent& rawEvent) { std::list<NotifyArgs> out; mCursorButtonAccumulator.process(rawEvent); mCursorMotionAccumulator.process(rawEvent); mCursorScrollAccumulator.process(rawEvent); - if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { + if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) { const auto [eventTime, readTime] = applyBluetoothTimestampSmoothening(getDeviceContext().getDeviceIdentifier(), - rawEvent->when, rawEvent->readTime, + rawEvent.when, rawEvent.readTime, mLastEventTime); out += sync(eventTime, readTime); mLastEventTime = eventTime; diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h index 75ca9c00a8..2108488936 100644 --- a/services/inputflinger/reader/mapper/CursorInputMapper.h +++ b/services/inputflinger/reader/mapper/CursorInputMapper.h @@ -34,7 +34,7 @@ public: CursorMotionAccumulator(); void reset(InputDeviceContext& deviceContext); - void process(const RawEvent* rawEvent); + void process(const RawEvent& rawEvent); void finishSync(); inline int32_t getRelativeX() const { return mRelX; } @@ -62,7 +62,7 @@ public: const InputReaderConfiguration& readerConfig, ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override; diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp index 987d2d0221..3af1d04073 100644 --- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp +++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp @@ -61,13 +61,13 @@ std::list<NotifyArgs> ExternalStylusInputMapper::reset(nsecs_t when) { return InputMapper::reset(when); } -std::list<NotifyArgs> ExternalStylusInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> ExternalStylusInputMapper::process(const RawEvent& rawEvent) { std::list<NotifyArgs> out; mSingleTouchMotionAccumulator.process(rawEvent); mTouchButtonAccumulator.process(rawEvent); - if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { - out += sync(rawEvent->when); + if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) { + out += sync(rawEvent.when); } return out; } diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h index 97df02b69f..c040a7b996 100644 --- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h +++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h @@ -39,7 +39,7 @@ public: const InputReaderConfiguration& config, ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; private: SingleTouchMotionAccumulator mSingleTouchMotionAccumulator; diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h index c7eea0e980..2c51448b4e 100644 --- a/services/inputflinger/reader/mapper/InputMapper.h +++ b/services/inputflinger/reader/mapper/InputMapper.h @@ -78,7 +78,7 @@ public: const InputReaderConfiguration& config, ConfigurationChanges changes); [[nodiscard]] virtual std::list<NotifyArgs> reset(nsecs_t when); - [[nodiscard]] virtual std::list<NotifyArgs> process(const RawEvent* rawEvent) = 0; + [[nodiscard]] virtual std::list<NotifyArgs> process(const RawEvent& rawEvent) = 0; [[nodiscard]] virtual std::list<NotifyArgs> timeoutExpired(nsecs_t when); virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp index 5ce4d30bb3..41e018d392 100644 --- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp +++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp @@ -259,29 +259,29 @@ std::list<NotifyArgs> JoystickInputMapper::reset(nsecs_t when) { return InputMapper::reset(when); } -std::list<NotifyArgs> JoystickInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> JoystickInputMapper::process(const RawEvent& rawEvent) { std::list<NotifyArgs> out; - switch (rawEvent->type) { + switch (rawEvent.type) { case EV_ABS: { - auto it = mAxes.find(rawEvent->code); + auto it = mAxes.find(rawEvent.code); if (it != mAxes.end()) { Axis& axis = it->second; float newValue, highNewValue; switch (axis.axisInfo.mode) { case AxisInfo::MODE_INVERT: - newValue = (axis.rawAxisInfo.maxValue - rawEvent->value) * axis.scale + + newValue = (axis.rawAxisInfo.maxValue - rawEvent.value) * axis.scale + axis.offset; highNewValue = 0.0f; break; case AxisInfo::MODE_SPLIT: - if (rawEvent->value < axis.axisInfo.splitValue) { - newValue = (axis.axisInfo.splitValue - rawEvent->value) * axis.scale + + if (rawEvent.value < axis.axisInfo.splitValue) { + newValue = (axis.axisInfo.splitValue - rawEvent.value) * axis.scale + axis.offset; highNewValue = 0.0f; - } else if (rawEvent->value > axis.axisInfo.splitValue) { + } else if (rawEvent.value > axis.axisInfo.splitValue) { newValue = 0.0f; highNewValue = - (rawEvent->value - axis.axisInfo.splitValue) * axis.highScale + + (rawEvent.value - axis.axisInfo.splitValue) * axis.highScale + axis.highOffset; } else { newValue = 0.0f; @@ -289,7 +289,7 @@ std::list<NotifyArgs> JoystickInputMapper::process(const RawEvent* rawEvent) { } break; default: - newValue = rawEvent->value * axis.scale + axis.offset; + newValue = rawEvent.value * axis.scale + axis.offset; highNewValue = 0.0f; break; } @@ -300,9 +300,9 @@ std::list<NotifyArgs> JoystickInputMapper::process(const RawEvent* rawEvent) { } case EV_SYN: - switch (rawEvent->code) { + switch (rawEvent.code) { case SYN_REPORT: - out += sync(rawEvent->when, rawEvent->readTime, /*force=*/false); + out += sync(rawEvent.when, rawEvent.readTime, /*force=*/false); break; } break; diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.h b/services/inputflinger/reader/mapper/JoystickInputMapper.h index 313f0922b7..621d38bfaa 100644 --- a/services/inputflinger/reader/mapper/JoystickInputMapper.h +++ b/services/inputflinger/reader/mapper/JoystickInputMapper.h @@ -35,7 +35,7 @@ public: const InputReaderConfiguration& config, ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; private: struct Axis { diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp index 21245555a2..1bc87a25a3 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp @@ -237,15 +237,15 @@ std::list<NotifyArgs> KeyboardInputMapper::reset(nsecs_t when) { return out; } -std::list<NotifyArgs> KeyboardInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> KeyboardInputMapper::process(const RawEvent& rawEvent) { std::list<NotifyArgs> out; - mHidUsageAccumulator.process(*rawEvent); - switch (rawEvent->type) { + mHidUsageAccumulator.process(rawEvent); + switch (rawEvent.type) { case EV_KEY: { - int32_t scanCode = rawEvent->code; + int32_t scanCode = rawEvent.code; if (isSupportedScanCode(scanCode)) { - out += processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0, + out += processKey(rawEvent.when, rawEvent.readTime, rawEvent.value != 0, scanCode, mHidUsageAccumulator.consumeCurrentHidUsage()); } break; diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h index f2d3f4d7d8..74bef46d8d 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h @@ -36,7 +36,7 @@ public: const InputReaderConfiguration& config, ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) override; int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override; diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp index bca9d9183b..1986fe286a 100644 --- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp @@ -40,7 +40,7 @@ std::list<NotifyArgs> MultiTouchInputMapper::reset(nsecs_t when) { return TouchInputMapper::reset(when); } -std::list<NotifyArgs> MultiTouchInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> MultiTouchInputMapper::process(const RawEvent& rawEvent) { std::list<NotifyArgs> out = TouchInputMapper::process(rawEvent); mMultiTouchMotionAccumulator.process(rawEvent); diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h index 5c173f365e..cca23279c5 100644 --- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h +++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h @@ -31,7 +31,7 @@ public: ~MultiTouchInputMapper() override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when, const InputReaderConfiguration& config, ConfigurationChanges changes) override; diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp index 0ddbc06890..27ff52fa65 100644 --- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp +++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp @@ -101,12 +101,12 @@ std::list<NotifyArgs> RotaryEncoderInputMapper::reset(nsecs_t when) { return InputMapper::reset(when); } -std::list<NotifyArgs> RotaryEncoderInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> RotaryEncoderInputMapper::process(const RawEvent& rawEvent) { std::list<NotifyArgs> out; mRotaryEncoderScrollAccumulator.process(rawEvent); - if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { - out += sync(rawEvent->when, rawEvent->readTime); + if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) { + out += sync(rawEvent.when, rawEvent.readTime); } return out; } diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h index fe5d152cef..14c540bf6e 100644 --- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h +++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h @@ -39,7 +39,7 @@ public: const InputReaderConfiguration& config, ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; private: CursorScrollAccumulator mRotaryEncoderScrollAccumulator; diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp index a131e3598f..d7f2993daa 100644 --- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp @@ -251,35 +251,35 @@ void SensorInputMapper::processHardWareTimestamp(nsecs_t evTime, int32_t mscTime mPrevMscTime = static_cast<uint32_t>(mscTime); } -std::list<NotifyArgs> SensorInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> SensorInputMapper::process(const RawEvent& rawEvent) { std::list<NotifyArgs> out; - switch (rawEvent->type) { + switch (rawEvent.type) { case EV_ABS: { - auto it = mAxes.find(rawEvent->code); + auto it = mAxes.find(rawEvent.code); if (it != mAxes.end()) { Axis& axis = it->second; - axis.newValue = rawEvent->value * axis.scale + axis.offset; + axis.newValue = rawEvent.value * axis.scale + axis.offset; } break; } case EV_SYN: - switch (rawEvent->code) { + switch (rawEvent.code) { case SYN_REPORT: for (std::pair<const int32_t, Axis>& pair : mAxes) { Axis& axis = pair.second; axis.currentValue = axis.newValue; } - out += sync(rawEvent->when, /*force=*/false); + out += sync(rawEvent.when, /*force=*/false); break; } break; case EV_MSC: - switch (rawEvent->code) { + switch (rawEvent.code) { case MSC_TIMESTAMP: // hardware timestamp is nano seconds - processHardWareTimestamp(rawEvent->when, rawEvent->value); + processHardWareTimestamp(rawEvent.when, rawEvent.value); break; } } diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.h b/services/inputflinger/reader/mapper/SensorInputMapper.h index a55dcd1905..63bc151ac1 100644 --- a/services/inputflinger/reader/mapper/SensorInputMapper.h +++ b/services/inputflinger/reader/mapper/SensorInputMapper.h @@ -40,7 +40,7 @@ public: const InputReaderConfiguration& config, ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; bool enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod, std::chrono::microseconds maxBatchReportLatency) override; void disableSensor(InputDeviceSensorType sensorType) override; diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp index ed0e27067f..140bb0c4ed 100644 --- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp @@ -30,7 +30,7 @@ std::list<NotifyArgs> SingleTouchInputMapper::reset(nsecs_t when) { return TouchInputMapper::reset(when); } -std::list<NotifyArgs> SingleTouchInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> SingleTouchInputMapper::process(const RawEvent& rawEvent) { std::list<NotifyArgs> out = TouchInputMapper::process(rawEvent); mSingleTouchMotionAccumulator.process(rawEvent); diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h index 7726bfb159..bc38711c98 100644 --- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h +++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h @@ -31,7 +31,7 @@ public: ~SingleTouchInputMapper() override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; protected: void syncTouch(nsecs_t when, RawState* outState) override; diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp index 05338da146..f131fb73df 100644 --- a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp @@ -30,16 +30,16 @@ uint32_t SwitchInputMapper::getSources() const { return AINPUT_SOURCE_SWITCH; } -std::list<NotifyArgs> SwitchInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> SwitchInputMapper::process(const RawEvent& rawEvent) { std::list<NotifyArgs> out; - switch (rawEvent->type) { + switch (rawEvent.type) { case EV_SW: - processSwitch(rawEvent->code, rawEvent->value); + processSwitch(rawEvent.code, rawEvent.value); break; case EV_SYN: - if (rawEvent->code == SYN_REPORT) { - out += sync(rawEvent->when); + if (rawEvent.code == SYN_REPORT) { + out += sync(rawEvent.when); } } return out; diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.h b/services/inputflinger/reader/mapper/SwitchInputMapper.h index 2fb48bbf25..5d8aa2c784 100644 --- a/services/inputflinger/reader/mapper/SwitchInputMapper.h +++ b/services/inputflinger/reader/mapper/SwitchInputMapper.h @@ -29,7 +29,7 @@ public: virtual ~SwitchInputMapper(); virtual uint32_t getSources() const override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode) override; virtual void dump(std::string& dump) override; diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index 8b4b691a45..9d049ae780 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -537,18 +537,6 @@ std::optional<DisplayViewport> TouchInputMapper::findViewport() { return getDeviceContext().getAssociatedViewport(); } - const std::optional<std::string> associatedDisplayUniqueIdByDescriptor = - getDeviceContext().getAssociatedDisplayUniqueIdByDescriptor(); - if (associatedDisplayUniqueIdByDescriptor) { - return getDeviceContext().getAssociatedViewport(); - } - - const std::optional<std::string> associatedDisplayUniqueIdByPort = - getDeviceContext().getAssociatedDisplayUniqueIdByPort(); - if (associatedDisplayUniqueIdByPort) { - return getDeviceContext().getAssociatedViewport(); - } - if (mDeviceMode == DeviceMode::POINTER) { std::optional<DisplayViewport> viewport = mConfig.getDisplayViewportById(mConfig.defaultPointerDisplayId); @@ -1415,14 +1403,14 @@ void TouchInputMapper::clearStylusDataPendingFlags() { mExternalStylusFusionTimeout = LLONG_MAX; } -std::list<NotifyArgs> TouchInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> TouchInputMapper::process(const RawEvent& rawEvent) { mCursorButtonAccumulator.process(rawEvent); mCursorScrollAccumulator.process(rawEvent); mTouchButtonAccumulator.process(rawEvent); std::list<NotifyArgs> out; - if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { - out += sync(rawEvent->when, rawEvent->readTime); + if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) { + out += sync(rawEvent.when, rawEvent.readTime); } return out; } diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h index b24f2ff8da..30c58a59c5 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -174,7 +174,7 @@ public: const InputReaderConfiguration& config, ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) override; int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override; diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp index b8911db2da..24efae893e 100644 --- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp @@ -24,6 +24,7 @@ #include <mutex> #include <optional> +#include <android-base/logging.h> #include <android-base/stringprintf.h> #include <android-base/thread_annotations.h> #include <android/input.h> @@ -241,10 +242,10 @@ TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext, mMetricsId(metricsIdFromInputDeviceIdentifier(deviceContext.getDeviceIdentifier())) { RawAbsoluteAxisInfo slotAxisInfo; deviceContext.getAbsoluteAxisInfo(ABS_MT_SLOT, &slotAxisInfo); - if (!slotAxisInfo.valid || slotAxisInfo.maxValue <= 0) { - ALOGW("Touchpad \"%s\" doesn't have a valid ABS_MT_SLOT axis, and probably won't work " - "properly.", - deviceContext.getName().c_str()); + if (!slotAxisInfo.valid || slotAxisInfo.maxValue < 0) { + LOG(WARNING) << "Touchpad " << deviceContext.getName() + << " doesn't have a valid ABS_MT_SLOT axis, and probably won't work properly."; + slotAxisInfo.maxValue = 0; } mMotionAccumulator.configure(deviceContext, slotAxisInfo.maxValue + 1, true); @@ -416,17 +417,17 @@ void TouchpadInputMapper::resetGestureInterpreter(nsecs_t when) { mResettingInterpreter = false; } -std::list<NotifyArgs> TouchpadInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> TouchpadInputMapper::process(const RawEvent& rawEvent) { if (mPointerCaptured) { - return mCapturedEventConverter.process(*rawEvent); + return mCapturedEventConverter.process(rawEvent); } if (mMotionAccumulator.getActiveSlotsCount() == 0) { - mGestureStartTime = rawEvent->when; + mGestureStartTime = rawEvent.when; } std::optional<SelfContainedHardwareState> state = mStateConverter.processRawEvent(rawEvent); if (state) { updatePalmDetectionMetrics(); - return sendHardwareState(rawEvent->when, rawEvent->readTime, *state); + return sendHardwareState(rawEvent.when, rawEvent.readTime, *state); } else { return {}; } diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h index 546fa5bb9c..8baa63e8e0 100644 --- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h @@ -56,7 +56,7 @@ public: const InputReaderConfiguration& config, ConfigurationChanges changes) override; [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; [[nodiscard]] std::list<NotifyArgs> timeoutExpired(nsecs_t when) override; void consumeGesture(const Gesture* gesture); diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp index 8d78d0fd80..a3a48ef034 100644 --- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp @@ -36,7 +36,7 @@ void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo& info) { info.setVibrator(true); } -std::list<NotifyArgs> VibratorInputMapper::process(const RawEvent* rawEvent) { +std::list<NotifyArgs> VibratorInputMapper::process(const RawEvent& rawEvent) { // TODO: Handle FF_STATUS, although it does not seem to be widely supported. return {}; } diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.h b/services/inputflinger/reader/mapper/VibratorInputMapper.h index 9079c73f8e..75196821af 100644 --- a/services/inputflinger/reader/mapper/VibratorInputMapper.h +++ b/services/inputflinger/reader/mapper/VibratorInputMapper.h @@ -30,7 +30,7 @@ public: virtual uint32_t getSources() const override; virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override; - [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; + [[nodiscard]] std::list<NotifyArgs> process(const RawEvent& rawEvent) override; [[nodiscard]] std::list<NotifyArgs> vibrate(const VibrationSequence& sequence, ssize_t repeat, int32_t token) override; diff --git a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp index 153236c177..9e722d41e7 100644 --- a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp +++ b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp @@ -47,32 +47,32 @@ void CursorButtonAccumulator::clearButtons() { mBtnTask = 0; } -void CursorButtonAccumulator::process(const RawEvent* rawEvent) { - if (rawEvent->type == EV_KEY) { - switch (rawEvent->code) { +void CursorButtonAccumulator::process(const RawEvent& rawEvent) { + if (rawEvent.type == EV_KEY) { + switch (rawEvent.code) { case BTN_LEFT: - mBtnLeft = rawEvent->value; + mBtnLeft = rawEvent.value; break; case BTN_RIGHT: - mBtnRight = rawEvent->value; + mBtnRight = rawEvent.value; break; case BTN_MIDDLE: - mBtnMiddle = rawEvent->value; + mBtnMiddle = rawEvent.value; break; case BTN_BACK: - mBtnBack = rawEvent->value; + mBtnBack = rawEvent.value; break; case BTN_SIDE: - mBtnSide = rawEvent->value; + mBtnSide = rawEvent.value; break; case BTN_FORWARD: - mBtnForward = rawEvent->value; + mBtnForward = rawEvent.value; break; case BTN_EXTRA: - mBtnExtra = rawEvent->value; + mBtnExtra = rawEvent.value; break; case BTN_TASK: - mBtnTask = rawEvent->value; + mBtnTask = rawEvent.value; break; } } diff --git a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h index 6960644a1d..256b2bb994 100644 --- a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h +++ b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h @@ -29,7 +29,7 @@ public: CursorButtonAccumulator(); void reset(const InputDeviceContext& deviceContext); - void process(const RawEvent* rawEvent); + void process(const RawEvent& rawEvent); uint32_t getButtonState() const; inline bool isLeftPressed() const { return mBtnLeft; } diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp index 07146941fd..f85cab205b 100644 --- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp +++ b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp @@ -39,14 +39,14 @@ void CursorScrollAccumulator::clearRelativeAxes() { mRelHWheel = 0; } -void CursorScrollAccumulator::process(const RawEvent* rawEvent) { - if (rawEvent->type == EV_REL) { - switch (rawEvent->code) { +void CursorScrollAccumulator::process(const RawEvent& rawEvent) { + if (rawEvent.type == EV_REL) { + switch (rawEvent.code) { case REL_WHEEL: - mRelWheel = rawEvent->value; + mRelWheel = rawEvent.value; break; case REL_HWHEEL: - mRelHWheel = rawEvent->value; + mRelHWheel = rawEvent.value; break; } } diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h index ae1b7a32f4..e563620252 100644 --- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h +++ b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h @@ -31,7 +31,7 @@ public: void configure(InputDeviceContext& deviceContext); void reset(InputDeviceContext& deviceContext); - void process(const RawEvent* rawEvent); + void process(const RawEvent& rawEvent); void finishSync(); inline bool haveRelativeVWheel() const { return mHaveRelWheel; } diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp index b3f170075c..4919068201 100644 --- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp +++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp @@ -45,12 +45,12 @@ void MultiTouchMotionAccumulator::resetSlots() { mCurrentSlot = -1; } -void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) { - if (rawEvent->type == EV_ABS) { +void MultiTouchMotionAccumulator::process(const RawEvent& rawEvent) { + if (rawEvent.type == EV_ABS) { bool newSlot = false; if (mUsingSlotsProtocol) { - if (rawEvent->code == ABS_MT_SLOT) { - mCurrentSlot = rawEvent->value; + if (rawEvent.code == ABS_MT_SLOT) { + mCurrentSlot = rawEvent.value; newSlot = true; } } else if (mCurrentSlot < 0) { @@ -72,12 +72,12 @@ void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) { if (!mUsingSlotsProtocol) { slot.mInUse = true; } - if (rawEvent->code == ABS_MT_POSITION_X || rawEvent->code == ABS_MT_POSITION_Y) { - warnIfNotInUse(*rawEvent, slot); + if (rawEvent.code == ABS_MT_POSITION_X || rawEvent.code == ABS_MT_POSITION_Y) { + warnIfNotInUse(rawEvent, slot); } - slot.populateAxisValue(rawEvent->code, rawEvent->value); + slot.populateAxisValue(rawEvent.code, rawEvent.value); } - } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) { + } else if (rawEvent.type == EV_SYN && rawEvent.code == SYN_MT_REPORT) { // MultiTouch Sync: The driver has returned all data for *one* of the pointers. mCurrentSlot += 1; } diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h index a0f21470c4..388ed82373 100644 --- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h +++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h @@ -76,7 +76,7 @@ public: void configure(const InputDeviceContext& deviceContext, size_t slotCount, bool usingSlotsProtocol); void reset(const InputDeviceContext& deviceContext); - void process(const RawEvent* rawEvent); + void process(const RawEvent& rawEvent); void finishSync(); size_t getActiveSlotsCount() const; diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp index 27b8e40fc6..2b82ddf33d 100644 --- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp +++ b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp @@ -45,29 +45,29 @@ void SingleTouchMotionAccumulator::clearAbsoluteAxes() { mAbsTiltY = 0; } -void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) { - if (rawEvent->type == EV_ABS) { - switch (rawEvent->code) { +void SingleTouchMotionAccumulator::process(const RawEvent& rawEvent) { + if (rawEvent.type == EV_ABS) { + switch (rawEvent.code) { case ABS_X: - mAbsX = rawEvent->value; + mAbsX = rawEvent.value; break; case ABS_Y: - mAbsY = rawEvent->value; + mAbsY = rawEvent.value; break; case ABS_PRESSURE: - mAbsPressure = rawEvent->value; + mAbsPressure = rawEvent.value; break; case ABS_TOOL_WIDTH: - mAbsToolWidth = rawEvent->value; + mAbsToolWidth = rawEvent.value; break; case ABS_DISTANCE: - mAbsDistance = rawEvent->value; + mAbsDistance = rawEvent.value; break; case ABS_TILT_X: - mAbsTiltX = rawEvent->value; + mAbsTiltX = rawEvent.value; break; case ABS_TILT_Y: - mAbsTiltY = rawEvent->value; + mAbsTiltY = rawEvent.value; break; } } diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h index 93056f06e6..fb74bcaf4c 100644 --- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h +++ b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h @@ -28,7 +28,7 @@ class SingleTouchMotionAccumulator { public: SingleTouchMotionAccumulator(); - void process(const RawEvent* rawEvent); + void process(const RawEvent& rawEvent); void reset(InputDeviceContext& deviceContext); inline int32_t getAbsoluteX() const { return mAbsX; } diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp index 8c4bed3267..ba8577e462 100644 --- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp +++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp @@ -52,60 +52,60 @@ void TouchButtonAccumulator::reset() { mHidUsageAccumulator.reset(); } -void TouchButtonAccumulator::process(const RawEvent* rawEvent) { - mHidUsageAccumulator.process(*rawEvent); +void TouchButtonAccumulator::process(const RawEvent& rawEvent) { + mHidUsageAccumulator.process(rawEvent); - if (rawEvent->type == EV_KEY) { - switch (rawEvent->code) { + if (rawEvent.type == EV_KEY) { + switch (rawEvent.code) { case BTN_TOUCH: - mBtnTouch = rawEvent->value; + mBtnTouch = rawEvent.value; break; case BTN_STYLUS: - mBtnStylus = rawEvent->value; + mBtnStylus = rawEvent.value; break; case BTN_STYLUS2: case BTN_0: // BTN_0 is what gets mapped for the HID usage // Digitizers.SecondaryBarrelSwitch - mBtnStylus2 = rawEvent->value; + mBtnStylus2 = rawEvent.value; break; case BTN_TOOL_FINGER: - mBtnToolFinger = rawEvent->value; + mBtnToolFinger = rawEvent.value; break; case BTN_TOOL_PEN: - mBtnToolPen = rawEvent->value; + mBtnToolPen = rawEvent.value; break; case BTN_TOOL_RUBBER: - mBtnToolRubber = rawEvent->value; + mBtnToolRubber = rawEvent.value; break; case BTN_TOOL_BRUSH: - mBtnToolBrush = rawEvent->value; + mBtnToolBrush = rawEvent.value; break; case BTN_TOOL_PENCIL: - mBtnToolPencil = rawEvent->value; + mBtnToolPencil = rawEvent.value; break; case BTN_TOOL_AIRBRUSH: - mBtnToolAirbrush = rawEvent->value; + mBtnToolAirbrush = rawEvent.value; break; case BTN_TOOL_MOUSE: - mBtnToolMouse = rawEvent->value; + mBtnToolMouse = rawEvent.value; break; case BTN_TOOL_LENS: - mBtnToolLens = rawEvent->value; + mBtnToolLens = rawEvent.value; break; case BTN_TOOL_DOUBLETAP: - mBtnToolDoubleTap = rawEvent->value; + mBtnToolDoubleTap = rawEvent.value; break; case BTN_TOOL_TRIPLETAP: - mBtnToolTripleTap = rawEvent->value; + mBtnToolTripleTap = rawEvent.value; break; case BTN_TOOL_QUADTAP: - mBtnToolQuadTap = rawEvent->value; + mBtnToolQuadTap = rawEvent.value; break; case BTN_TOOL_QUINTTAP: - mBtnToolQuintTap = rawEvent->value; + mBtnToolQuintTap = rawEvent.value; break; default: - processMappedKey(rawEvent->code, rawEvent->value); + processMappedKey(rawEvent.code, rawEvent.value); } return; } diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h index e829692206..c7adf8448e 100644 --- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h +++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h @@ -33,7 +33,7 @@ public: void configure(); void reset(); - void process(const RawEvent* rawEvent); + void process(const RawEvent& rawEvent); uint32_t getButtonState() const; ToolType getToolType() const; diff --git a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp index b89b7f38a9..6885adb242 100644 --- a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp +++ b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp @@ -40,15 +40,15 @@ HardwareStateConverter::HardwareStateConverter(const InputDeviceContext& deviceC } std::optional<SelfContainedHardwareState> HardwareStateConverter::processRawEvent( - const RawEvent* rawEvent) { + const RawEvent& rawEvent) { std::optional<SelfContainedHardwareState> out; - if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { - out = produceHardwareState(rawEvent->when); + if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) { + out = produceHardwareState(rawEvent.when); mMotionAccumulator.finishSync(); mMscTimestamp = 0; } - if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) { - mMscTimestamp = rawEvent->value; + if (rawEvent.type == EV_MSC && rawEvent.code == MSC_TIMESTAMP) { + mMscTimestamp = rawEvent.value; } mCursorButtonAccumulator.process(rawEvent); mMotionAccumulator.process(rawEvent); diff --git a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h index 633448e67e..07e62c6eba 100644 --- a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h +++ b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h @@ -44,7 +44,7 @@ public: HardwareStateConverter(const InputDeviceContext& deviceContext, MultiTouchMotionAccumulator& motionAccumulator); - std::optional<SelfContainedHardwareState> processRawEvent(const RawEvent* event); + std::optional<SelfContainedHardwareState> processRawEvent(const RawEvent& event); void reset(); private: diff --git a/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp b/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp index 69264f84ed..f4a5e0dfeb 100644 --- a/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp +++ b/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp @@ -90,7 +90,7 @@ void PropertyProvider::loadPropertiesFromIdcFile(const PropertyMap& idcPropertie // prefixed with "gestureProp." and have spaces replaced by underscores. So, for example, the // configuration key "gestureProp.Palm_Width" refers to the "Palm Width" property. const std::string gesturePropPrefix = "gestureProp."; - for (const std::string key : idcProperties.getKeysWithPrefix(gesturePropPrefix)) { + for (const std::string& key : idcProperties.getKeysWithPrefix(gesturePropPrefix)) { std::string propertyName = key.substr(gesturePropPrefix.length()); for (size_t i = 0; i < propertyName.length(); i++) { if (propertyName[i] == '_') { diff --git a/services/inputflinger/tests/FakePointerController.cpp b/services/inputflinger/tests/FakePointerController.cpp index 456013e347..d0998ba851 100644 --- a/services/inputflinger/tests/FakePointerController.cpp +++ b/services/inputflinger/tests/FakePointerController.cpp @@ -77,10 +77,12 @@ void FakePointerController::setCustomPointerIcon(const SpriteIcon& icon) { } void FakePointerController::setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId displayId) { + mDisplaysToSkipScreenshotFlagChanged = true; mDisplaysToSkipScreenshot.insert(displayId); } void FakePointerController::clearSkipScreenshotFlags() { + mDisplaysToSkipScreenshotFlagChanged = true; mDisplaysToSkipScreenshot.clear(); } @@ -125,13 +127,21 @@ void FakePointerController::assertCustomPointerIconNotSet() { ASSERT_EQ(std::nullopt, mCustomIconStyle); } -void FakePointerController::assertIsHiddenOnMirroredDisplays(ui::LogicalDisplayId displayId, - bool isHidden) { - if (isHidden) { - ASSERT_TRUE(mDisplaysToSkipScreenshot.find(displayId) != mDisplaysToSkipScreenshot.end()); - } else { - ASSERT_TRUE(mDisplaysToSkipScreenshot.find(displayId) == mDisplaysToSkipScreenshot.end()); - } +void FakePointerController::assertIsSkipScreenshotFlagSet(ui::LogicalDisplayId displayId) { + ASSERT_TRUE(mDisplaysToSkipScreenshot.find(displayId) != mDisplaysToSkipScreenshot.end()); +} + +void FakePointerController::assertIsSkipScreenshotFlagNotSet(ui::LogicalDisplayId displayId) { + ASSERT_TRUE(mDisplaysToSkipScreenshot.find(displayId) == mDisplaysToSkipScreenshot.end()); +} + +void FakePointerController::assertSkipScreenshotFlagChanged() { + ASSERT_TRUE(mDisplaysToSkipScreenshotFlagChanged); + mDisplaysToSkipScreenshotFlagChanged = false; +} + +void FakePointerController::assertSkipScreenshotFlagNotChanged() { + ASSERT_FALSE(mDisplaysToSkipScreenshotFlagChanged); } bool FakePointerController::isPointerShown() { diff --git a/services/inputflinger/tests/FakePointerController.h b/services/inputflinger/tests/FakePointerController.h index 8d95f65896..2c76c6214c 100644 --- a/services/inputflinger/tests/FakePointerController.h +++ b/services/inputflinger/tests/FakePointerController.h @@ -57,7 +57,10 @@ public: void assertPointerIconNotSet(); void assertCustomPointerIconSet(PointerIconStyle iconId); void assertCustomPointerIconNotSet(); - void assertIsHiddenOnMirroredDisplays(ui::LogicalDisplayId displayId, bool isHidden); + void assertIsSkipScreenshotFlagSet(ui::LogicalDisplayId displayId); + void assertIsSkipScreenshotFlagNotSet(ui::LogicalDisplayId displayId); + void assertSkipScreenshotFlagChanged(); + void assertSkipScreenshotFlagNotChanged(); bool isPointerShown(); private: @@ -81,6 +84,7 @@ private: std::map<ui::LogicalDisplayId, std::vector<int32_t>> mSpotsByDisplay; std::unordered_set<ui::LogicalDisplayId> mDisplaysToSkipScreenshot; + bool mDisplaysToSkipScreenshotFlagChanged{false}; }; } // namespace android diff --git a/services/inputflinger/tests/HardwareStateConverter_test.cpp b/services/inputflinger/tests/HardwareStateConverter_test.cpp index ff9bd9e75b..34c81fcf02 100644 --- a/services/inputflinger/tests/HardwareStateConverter_test.cpp +++ b/services/inputflinger/tests/HardwareStateConverter_test.cpp @@ -81,7 +81,7 @@ protected: event.type = type; event.code = code; event.value = value; - std::optional<SelfContainedHardwareState> schs = mConverter->processRawEvent(&event); + std::optional<SelfContainedHardwareState> schs = mConverter->processRawEvent(event); EXPECT_FALSE(schs.has_value()); } @@ -93,7 +93,7 @@ protected: event.type = EV_SYN; event.code = SYN_REPORT; event.value = 0; - return mConverter->processRawEvent(&event); + return mConverter->processRawEvent(event); } std::shared_ptr<FakeEventHub> mFakeEventHub; diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp index fea1349b88..b5c9232a78 100644 --- a/services/inputflinger/tests/InputMapperTest.cpp +++ b/services/inputflinger/tests/InputMapperTest.cpp @@ -104,7 +104,7 @@ std::list<NotifyArgs> InputMapperUnitTest::process(nsecs_t when, int32_t type, i event.type = type; event.code = code; event.value = value; - return mMapper->process(&event); + return mMapper->process(event); } const char* InputMapperTest::DEVICE_NAME = "device"; @@ -195,7 +195,7 @@ std::list<NotifyArgs> InputMapperTest::process(InputMapper& mapper, nsecs_t when event.type = type; event.code = code; event.value = value; - std::list<NotifyArgs> processArgList = mapper.process(&event); + std::list<NotifyArgs> processArgList = mapper.process(event); for (const NotifyArgs& args : processArgList) { mFakeListener->notify(args); } diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 8536ff0676..2e65d4a48e 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -309,9 +309,9 @@ private: return {}; } - std::list<NotifyArgs> process(const RawEvent* rawEvent) override { + std::list<NotifyArgs> process(const RawEvent& rawEvent) override { std::scoped_lock<std::mutex> lock(mLock); - mLastEvent = *rawEvent; + mLastEvent = rawEvent; mProcessWasCalled = true; mStateChangedCondition.notify_all(); return mProcessResult; @@ -10595,24 +10595,66 @@ TEST_F(LightControllerTest, MultiColorRGBKeyboardBacklight) { ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR); } +TEST_F(LightControllerTest, SonyPlayerIdLight) { + RawLightInfo info1 = {.id = 1, + .name = "sony1", + .maxBrightness = 255, + .flags = InputLightClass::BRIGHTNESS, + .path = ""}; + RawLightInfo info2 = {.id = 2, + .name = "sony2", + .maxBrightness = 255, + .flags = InputLightClass::BRIGHTNESS, + .path = ""}; + RawLightInfo info3 = {.id = 3, + .name = "sony3", + .maxBrightness = 255, + .flags = InputLightClass::BRIGHTNESS, + .path = ""}; + RawLightInfo info4 = {.id = 4, + .name = "sony4", + .maxBrightness = 255, + .flags = InputLightClass::BRIGHTNESS, + .path = ""}; + mFakeEventHub->addRawLightInfo(info1.id, std::move(info1)); + mFakeEventHub->addRawLightInfo(info2.id, std::move(info2)); + mFakeEventHub->addRawLightInfo(info3.id, std::move(info3)); + mFakeEventHub->addRawLightInfo(info4.id, std::move(info4)); + + PeripheralController& controller = addControllerAndConfigure<PeripheralController>(); + InputDeviceInfo info; + controller.populateDeviceInfo(&info); + std::vector<InputDeviceLightInfo> lights = info.getLights(); + ASSERT_EQ(1U, lights.size()); + ASSERT_STREQ("sony", lights[0].name.c_str()); + ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type); + ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS)); + ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB)); + + ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR)); + ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID)); + ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID); + ASSERT_STREQ("sony", lights[0].name.c_str()); +} + TEST_F(LightControllerTest, PlayerIdLight) { RawLightInfo info1 = {.id = 1, - .name = "player1", + .name = "player-1", .maxBrightness = 255, .flags = InputLightClass::BRIGHTNESS, .path = ""}; RawLightInfo info2 = {.id = 2, - .name = "player2", + .name = "player-2", .maxBrightness = 255, .flags = InputLightClass::BRIGHTNESS, .path = ""}; RawLightInfo info3 = {.id = 3, - .name = "player3", + .name = "player-3", .maxBrightness = 255, .flags = InputLightClass::BRIGHTNESS, .path = ""}; RawLightInfo info4 = {.id = 4, - .name = "player4", + .name = "player-4", .maxBrightness = 255, .flags = InputLightClass::BRIGHTNESS, .path = ""}; @@ -10626,6 +10668,7 @@ TEST_F(LightControllerTest, PlayerIdLight) { controller.populateDeviceInfo(&info); std::vector<InputDeviceLightInfo> lights = info.getLights(); ASSERT_EQ(1U, lights.size()); + ASSERT_STREQ("player", lights[0].name.c_str()); ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type); ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS)); ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB)); diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h index 6389cdc5fb..6a35631e46 100644 --- a/services/inputflinger/tests/InterfaceMocks.h +++ b/services/inputflinger/tests/InterfaceMocks.h @@ -27,7 +27,9 @@ #include <EventHub.h> #include <InputReaderBase.h> +#include <InputReaderContext.h> #include <NotifyArgs.h> +#include <PointerChoreographerPolicyInterface.h> #include <StylusState.h> #include <VibrationElement.h> #include <android-base/logging.h> @@ -174,4 +176,12 @@ public: MOCK_METHOD(void, sysfsNodeChanged, (const std::string& sysfsNodePath), (override)); }; +class MockPointerChoreographerPolicyInterface : public PointerChoreographerPolicyInterface { +public: + MOCK_METHOD(std::shared_ptr<PointerControllerInterface>, createPointerController, + (PointerControllerInterface::ControllerType), (override)); + MOCK_METHOD(void, notifyPointerDisplayIdChanged, + (ui::LogicalDisplayId displayId, const FloatPoint& position), (override)); +}; + } // namespace android diff --git a/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp index 5e67506b48..b441a23803 100644 --- a/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp +++ b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp @@ -38,7 +38,7 @@ protected: event.type = type; event.code = code; event.value = value; - mMotionAccumulator.process(&event); + mMotionAccumulator.process(event); } }; diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp index 69a7382cd4..3f2d6ec45c 100644 --- a/services/inputflinger/tests/PointerChoreographer_test.cpp +++ b/services/inputflinger/tests/PointerChoreographer_test.cpp @@ -22,6 +22,7 @@ #include <vector> #include "FakePointerController.h" +#include "InterfaceMocks.h" #include "NotifyArgsBuilders.h" #include "TestEventMatchers.h" #include "TestInputListener.h" @@ -89,10 +90,55 @@ static std::vector<DisplayViewport> createViewports(std::vector<ui::LogicalDispl // --- PointerChoreographerTest --- -class PointerChoreographerTest : public testing::Test, public PointerChoreographerPolicyInterface { +class TestPointerChoreographer : public PointerChoreographer { +public: + TestPointerChoreographer(InputListenerInterface& inputListener, + PointerChoreographerPolicyInterface& policy, + sp<gui::WindowInfosListener>& windowInfoListener, + const std::vector<gui::WindowInfo>& mInitialWindowInfos); +}; + +TestPointerChoreographer::TestPointerChoreographer( + InputListenerInterface& inputListener, PointerChoreographerPolicyInterface& policy, + sp<gui::WindowInfosListener>& windowInfoListener, + const std::vector<gui::WindowInfo>& mInitialWindowInfos) + : PointerChoreographer( + inputListener, policy, + [&windowInfoListener, + &mInitialWindowInfos](const sp<android::gui::WindowInfosListener>& listener) { + windowInfoListener = listener; + return mInitialWindowInfos; + }, + [&windowInfoListener](const sp<android::gui::WindowInfosListener>& listener) { + windowInfoListener = nullptr; + }) {} + +class PointerChoreographerTest : public testing::Test { protected: TestInputListener mTestListener; - PointerChoreographer mChoreographer{mTestListener, *this}; + sp<gui::WindowInfosListener> mRegisteredWindowInfoListener; + std::vector<gui::WindowInfo> mInjectedInitialWindowInfos; + testing::NiceMock<MockPointerChoreographerPolicyInterface> mMockPolicy; + TestPointerChoreographer mChoreographer{mTestListener, mMockPolicy, + mRegisteredWindowInfoListener, + mInjectedInitialWindowInfos}; + + void SetUp() override { + // flag overrides + input_flags::hide_pointer_indicators_for_secure_windows(true); + + ON_CALL(mMockPolicy, createPointerController).WillByDefault([this](ControllerType type) { + std::shared_ptr<FakePointerController> pc = std::make_shared<FakePointerController>(); + EXPECT_FALSE(pc->isPointerShown()); + mCreatedControllers.emplace_back(type, pc); + return pc; + }); + + ON_CALL(mMockPolicy, notifyPointerDisplayIdChanged) + .WillByDefault([this](ui::LogicalDisplayId displayId, const FloatPoint& position) { + mPointerDisplayIdNotified = displayId; + }); + } std::shared_ptr<FakePointerController> assertPointerControllerCreated( ControllerType expectedType) { @@ -131,23 +177,20 @@ protected: void assertPointerDisplayIdNotNotified() { ASSERT_EQ(std::nullopt, mPointerDisplayIdNotified); } + void assertWindowInfosListenerRegistered() { + ASSERT_NE(nullptr, mRegisteredWindowInfoListener) + << "WindowInfosListener was not registered"; + } + + void assertWindowInfosListenerNotRegistered() { + ASSERT_EQ(nullptr, mRegisteredWindowInfoListener) + << "WindowInfosListener was not unregistered"; + } + private: std::deque<std::pair<ControllerType, std::shared_ptr<FakePointerController>>> mCreatedControllers; std::optional<ui::LogicalDisplayId> mPointerDisplayIdNotified; - - std::shared_ptr<PointerControllerInterface> createPointerController( - ControllerType type) override { - std::shared_ptr<FakePointerController> pc = std::make_shared<FakePointerController>(); - EXPECT_FALSE(pc->isPointerShown()); - mCreatedControllers.emplace_back(type, pc); - return pc; - } - - void notifyPointerDisplayIdChanged(ui::LogicalDisplayId displayId, - const FloatPoint& position) override { - mPointerDisplayIdNotified = displayId; - } }; TEST_F(PointerChoreographerTest, ForwardsArgsToInnerListener) { @@ -1636,16 +1679,36 @@ TEST_F(PointerChoreographerTest, SetsPointerIconForMouseOnTwoDisplays) { firstMousePc->assertPointerIconNotSet(); } -using HidePointerForPrivacySensitiveDisplaysFixtureParam = +using SkipPointerScreenshotForPrivacySensitiveDisplaysFixtureParam = std::tuple<std::string_view /*name*/, uint32_t /*source*/, ControllerType, PointerBuilder, std::function<void(PointerChoreographer&)>, int32_t /*action*/>; -class HidePointerForPrivacySensitiveDisplaysTestFixture +class SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture : public PointerChoreographerTest, - public ::testing::WithParamInterface<HidePointerForPrivacySensitiveDisplaysFixtureParam> {}; + public ::testing::WithParamInterface< + SkipPointerScreenshotForPrivacySensitiveDisplaysFixtureParam> { +protected: + void initializePointerDevice(const PointerBuilder& pointerBuilder, const uint32_t source, + const std::function<void(PointerChoreographer&)> onControllerInit, + const int32_t action) { + mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID})); + + // Add appropriate pointer device + mChoreographer.notifyInputDevicesChanged( + {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, source, DISPLAY_ID)}}); + onControllerInit(mChoreographer); + + // Emit input events to create PointerController + mChoreographer.notifyMotion(MotionArgsBuilder(action, source) + .pointer(pointerBuilder) + .deviceId(DEVICE_ID) + .displayId(DISPLAY_ID) + .build()); + } +}; INSTANTIATE_TEST_SUITE_P( - PointerChoreographerTest, HidePointerForPrivacySensitiveDisplaysTestFixture, + PointerChoreographerTest, SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture, ::testing::Values( std::make_tuple( "TouchSpots", AINPUT_SOURCE_TOUCHSCREEN, ControllerType::TOUCH, @@ -1663,44 +1726,205 @@ INSTANTIATE_TEST_SUITE_P( "DrawingTablet", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS, ControllerType::MOUSE, STYLUS_POINTER, [](PointerChoreographer& pc) {}, AMOTION_EVENT_ACTION_HOVER_ENTER)), - [](const testing::TestParamInfo<HidePointerForPrivacySensitiveDisplaysFixtureParam>& p) { + [](const testing::TestParamInfo< + SkipPointerScreenshotForPrivacySensitiveDisplaysFixtureParam>& p) { return std::string{std::get<0>(p.param)}; }); -TEST_P(HidePointerForPrivacySensitiveDisplaysTestFixture, - HidesPointerOnMirroredDisplaysForPrivacySensitiveDisplay) { +TEST_P(SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture, + WindowInfosListenerIsOnlyRegisteredWhenRequired) { const auto& [name, source, controllerType, pointerBuilder, onControllerInit, action] = GetParam(); - input_flags::hide_pointer_indicators_for_secure_windows(true); + assertWindowInfosListenerNotRegistered(); + + // Listener should registered when a pointer device is added + initializePointerDevice(pointerBuilder, source, onControllerInit, action); + assertWindowInfosListenerRegistered(); + + mChoreographer.notifyInputDevicesChanged({}); + assertWindowInfosListenerNotRegistered(); +} + +TEST_P(SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture, + InitialDisplayInfoIsPopulatedForListener) { + const auto& [name, source, controllerType, pointerBuilder, onControllerInit, action] = + GetParam(); + // listener should not be registered if there is no pointer device + assertWindowInfosListenerNotRegistered(); + + gui::WindowInfo windowInfo; + windowInfo.displayId = DISPLAY_ID; + windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY; + mInjectedInitialWindowInfos = {windowInfo}; + + initializePointerDevice(pointerBuilder, source, onControllerInit, action); + assertWindowInfosListenerRegistered(); + + // Pointer indicators should be hidden based on the initial display info + auto pc = assertPointerControllerCreated(controllerType); + pc->assertIsSkipScreenshotFlagSet(DISPLAY_ID); + pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID); + + // un-marking the privacy sensitive display should reset the state + windowInfo.inputConfig.clear(); + gui::DisplayInfo displayInfo; + displayInfo.displayId = DISPLAY_ID; + mRegisteredWindowInfoListener + ->onWindowInfosChanged(/*windowInfosUpdate=*/ + {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0}); + + pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID); + pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID); +} + +TEST_P(SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture, + SkipsPointerScreenshotForPrivacySensitiveWindows) { + const auto& [name, source, controllerType, pointerBuilder, onControllerInit, action] = + GetParam(); + initializePointerDevice(pointerBuilder, source, onControllerInit, action); + + // By default pointer indicators should not be hidden + auto pc = assertPointerControllerCreated(controllerType); + pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID); + pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID); + + // marking a display privacy sensitive should set flag to hide pointer indicators on the + // display screenshot + gui::WindowInfo windowInfo; + windowInfo.displayId = DISPLAY_ID; + windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY; + gui::DisplayInfo displayInfo; + displayInfo.displayId = DISPLAY_ID; + assertWindowInfosListenerRegistered(); + mRegisteredWindowInfoListener + ->onWindowInfosChanged(/*windowInfosUpdate=*/ + {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0}); + + pc->assertIsSkipScreenshotFlagSet(DISPLAY_ID); + pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID); + + // un-marking the privacy sensitive display should reset the state + windowInfo.inputConfig.clear(); + mRegisteredWindowInfoListener + ->onWindowInfosChanged(/*windowInfosUpdate=*/ + {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0}); + + pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID); + pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID); +} + +TEST_P(SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture, + DoesNotSkipPointerScreenshotForHiddenPrivacySensitiveWindows) { + const auto& [name, source, controllerType, pointerBuilder, onControllerInit, action] = + GetParam(); + initializePointerDevice(pointerBuilder, source, onControllerInit, action); + + // By default pointer indicators should not be hidden + auto pc = assertPointerControllerCreated(controllerType); + pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID); + pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID); + + gui::WindowInfo windowInfo; + windowInfo.displayId = DISPLAY_ID; + windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY; + windowInfo.inputConfig |= gui::WindowInfo::InputConfig::NOT_VISIBLE; + gui::DisplayInfo displayInfo; + displayInfo.displayId = DISPLAY_ID; + assertWindowInfosListenerRegistered(); + mRegisteredWindowInfoListener + ->onWindowInfosChanged(/*windowInfosUpdate=*/ + {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0}); + + pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID); + pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID); +} + +TEST_P(SkipPointerScreenshotForPrivacySensitiveDisplaysTestFixture, + DoesNotUpdateControllerForUnchangedPrivacySensitiveWindows) { + const auto& [name, source, controllerType, pointerBuilder, onControllerInit, action] = + GetParam(); + initializePointerDevice(pointerBuilder, source, onControllerInit, action); + + auto pc = assertPointerControllerCreated(controllerType); + gui::WindowInfo windowInfo; + windowInfo.displayId = DISPLAY_ID; + windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY; + gui::DisplayInfo displayInfo; + displayInfo.displayId = DISPLAY_ID; + assertWindowInfosListenerRegistered(); + mRegisteredWindowInfoListener + ->onWindowInfosChanged(/*windowInfosUpdate=*/ + {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0}); + + gui::WindowInfo windowInfo2 = windowInfo; + windowInfo2.inputConfig.clear(); + pc->assertSkipScreenshotFlagChanged(); + + // controller should not be updated if there are no changes in privacy sensitive windows + mRegisteredWindowInfoListener->onWindowInfosChanged(/*windowInfosUpdate=*/ + {{windowInfo, windowInfo2}, + {displayInfo}, + /*vsyncId=*/0, + /*timestamp=*/0}); + pc->assertSkipScreenshotFlagNotChanged(); +} + +TEST_F_WITH_FLAGS( + PointerChoreographerTest, HidesPointerScreenshotForExistingPrivacySensitiveWindows, + REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags, + hide_pointer_indicators_for_secure_windows))) { mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID})); - // Add appropriate pointer device + // Add a first mouse device mChoreographer.notifyInputDevicesChanged( - {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, source, DISPLAY_ID)}}); - onControllerInit(mChoreographer); + {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, DISPLAY_ID)}}); - // Emit input events to create PointerController - mChoreographer.notifyMotion(MotionArgsBuilder(action, source) - .pointer(pointerBuilder) + mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE) + .pointer(MOUSE_POINTER) .deviceId(DEVICE_ID) .displayId(DISPLAY_ID) .build()); - // By default pointer indicators should not be hidden - auto pc = assertPointerControllerCreated(controllerType); - pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/false); - pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false); + gui::WindowInfo windowInfo; + windowInfo.displayId = DISPLAY_ID; + windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY; + gui::DisplayInfo displayInfo; + displayInfo.displayId = DISPLAY_ID; + assertWindowInfosListenerRegistered(); + mRegisteredWindowInfoListener + ->onWindowInfosChanged(/*windowInfosUpdate=*/ + {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0}); - // marking a display privacy sensitive should set flag to hide pointer indicators on the - // corresponding mirrored display - mChoreographer.onPrivacySensitiveDisplaysChanged(/*privacySensitiveDisplays=*/{DISPLAY_ID}); - pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/true); - pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false); + auto pc = assertPointerControllerCreated(ControllerType::MOUSE); + pc->assertIsSkipScreenshotFlagSet(DISPLAY_ID); + pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID); + + // Add a second touch device and controller + mChoreographer.notifyInputDevicesChanged( + {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID)}}); + mChoreographer.setShowTouchesEnabled(true); + mChoreographer.notifyMotion( + MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(FIRST_TOUCH_POINTER) + .deviceId(DEVICE_ID) + .displayId(DISPLAY_ID) + .build()); + + // Pointer indicators should be hidden for this controller by default + auto pc2 = assertPointerControllerCreated(ControllerType::TOUCH); + pc->assertIsSkipScreenshotFlagSet(DISPLAY_ID); + pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID); // un-marking the privacy sensitive display should reset the state - mChoreographer.onPrivacySensitiveDisplaysChanged(/*privacySensitiveDisplays=*/{}); - pc->assertIsHiddenOnMirroredDisplays(DISPLAY_ID, /*isHidden=*/false); - pc->assertIsHiddenOnMirroredDisplays(ANOTHER_DISPLAY_ID, /*isHidden=*/false); + windowInfo.inputConfig.clear(); + mRegisteredWindowInfoListener + ->onWindowInfosChanged(/*windowInfosUpdate=*/ + {{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0}); + + pc->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID); + pc->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID); + pc2->assertIsSkipScreenshotFlagNotSet(DISPLAY_ID); + pc2->assertIsSkipScreenshotFlagNotSet(ANOTHER_DISPLAY_ID); } TEST_P(StylusTestFixture, SetsPointerIconForStylus) { @@ -2070,4 +2294,41 @@ TEST_F(PointerChoreographerTest, MouseAndDrawingTabletReportMouseEvents) { assertPointerControllerRemoved(pc); } +class PointerChoreographerWindowInfoListenerTest : public testing::Test {}; + +TEST_F_WITH_FLAGS( + PointerChoreographerWindowInfoListenerTest, + doesNotCrashIfListenerCalledAfterPointerChoreographerDestroyed, + REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags, + hide_pointer_indicators_for_secure_windows))) { + sp<android::gui::WindowInfosListener> registeredListener; + sp<android::gui::WindowInfosListener> localListenerCopy; + { + testing::NiceMock<MockPointerChoreographerPolicyInterface> mockPolicy; + EXPECT_CALL(mockPolicy, createPointerController(ControllerType::MOUSE)) + .WillOnce(testing::Return(std::make_shared<FakePointerController>())); + TestInputListener testListener; + std::vector<gui::WindowInfo> injectedInitialWindowInfos; + TestPointerChoreographer testChoreographer{testListener, mockPolicy, registeredListener, + injectedInitialWindowInfos}; + testChoreographer.setDisplayViewports(createViewports({DISPLAY_ID})); + + // Add mouse to create controller and listener + testChoreographer.notifyInputDevicesChanged( + {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, DISPLAY_ID)}}); + + ASSERT_NE(nullptr, registeredListener) << "WindowInfosListener was not registered"; + localListenerCopy = registeredListener; + } + ASSERT_EQ(nullptr, registeredListener) << "WindowInfosListener was not unregistered"; + + gui::WindowInfo windowInfo; + windowInfo.displayId = DISPLAY_ID; + windowInfo.inputConfig |= gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY; + gui::DisplayInfo displayInfo; + displayInfo.displayId = DISPLAY_ID; + localListenerCopy->onWindowInfosChanged( + /*windowInfosUpdate=*/{{windowInfo}, {displayInfo}, /*vsyncId=*/0, /*timestamp=*/0}); +} + } // namespace android diff --git a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp index af20a271b8..836151787c 100644 --- a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp @@ -81,7 +81,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig, InputReaderConfiguration::Change(0)); RawEvent rawEvent = getFuzzedRawEvent(*fdp); - unused += mapper.process(&rawEvent); + unused += mapper.process(rawEvent); }, [&]() -> void { std::list<NotifyArgs> unused = mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); diff --git a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp index 922cbdfb87..8c3189e089 100644 --- a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp @@ -80,7 +80,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { }, [&]() -> void { RawEvent rawEvent = getFuzzedRawEvent(*fdp); - std::list<NotifyArgs> unused = mapper.process(&rawEvent); + std::list<NotifyArgs> unused = mapper.process(rawEvent); }, [&]() -> void { mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(), diff --git a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp index d3f66900da..f29577d7f0 100644 --- a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp @@ -100,7 +100,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { }, [&]() -> void { RawEvent rawEvent = getFuzzedRawEvent(*fdp); - std::list<NotifyArgs> unused = mapper.process(&rawEvent); + std::list<NotifyArgs> unused = mapper.process(rawEvent); }, [&]() -> void { mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(), diff --git a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp index ac2030afd3..a42d447fe3 100644 --- a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp @@ -44,7 +44,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { [&]() -> void { mapper.getSources(); }, [&]() -> void { RawEvent rawEvent = getFuzzedRawEvent(*fdp); - std::list<NotifyArgs> unused = mapper.process(&rawEvent); + std::list<NotifyArgs> unused = mapper.process(rawEvent); }, [&]() -> void { mapper.getSwitchState(fdp->ConsumeIntegral<uint32_t>(), diff --git a/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp index 643e8b9f97..c620032eef 100644 --- a/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp @@ -176,7 +176,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { }, [&]() -> void { RawEvent event = getFuzzedRawEvent(*fdp); - std::list<NotifyArgs> unused = mapper.process(&event); + std::list<NotifyArgs> unused = mapper.process(event); }, })(); } diff --git a/services/sensorservice/senserservice_flags.aconfig b/services/sensorservice/senserservice_flags.aconfig index 5b499a8fd8..7abfbaab07 100644 --- a/services/sensorservice/senserservice_flags.aconfig +++ b/services/sensorservice/senserservice_flags.aconfig @@ -27,4 +27,4 @@ flag { namespace: "sensors" description: "When this flag is enabled, sensor service will only erase dynamic sensor data at the end of the threadLoop to prevent race condition." bug: "329020894" -}
\ No newline at end of file +} diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp index 2b20de38d7..39a6b777bb 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp @@ -260,27 +260,36 @@ void LayerHierarchyBuilder::detachFromRelativeParent(LayerHierarchy* hierarchy) hierarchy->mParent->updateChild(hierarchy, LayerHierarchy::Variant::Attached); } -void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) { - if (root->mLayer) { - attachToRelativeParent(root); - } - for (auto& [child, childVariant] : root->mChildren) { - if (childVariant == LayerHierarchy::Variant::Detached || - childVariant == LayerHierarchy::Variant::Attached) { - attachHierarchyToRelativeParent(child); +std::vector<LayerHierarchy*> LayerHierarchyBuilder::getDescendants(LayerHierarchy* root) { + std::vector<LayerHierarchy*> hierarchies; + hierarchies.push_back(root); + std::vector<LayerHierarchy*> descendants; + for (size_t i = 0; i < hierarchies.size(); i++) { + LayerHierarchy* hierarchy = hierarchies[i]; + if (hierarchy->mLayer) { + descendants.push_back(hierarchy); + } + for (auto& [child, childVariant] : hierarchy->mChildren) { + if (childVariant == LayerHierarchy::Variant::Detached || + childVariant == LayerHierarchy::Variant::Attached) { + hierarchies.push_back(child); + } } } + return descendants; } -void LayerHierarchyBuilder::detachHierarchyFromRelativeParent(LayerHierarchy* root) { - if (root->mLayer) { - detachFromRelativeParent(root); +void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) { + std::vector<LayerHierarchy*> hierarchiesToAttach = getDescendants(root); + for (LayerHierarchy* hierarchy : hierarchiesToAttach) { + attachToRelativeParent(hierarchy); } - for (auto& [child, childVariant] : root->mChildren) { - if (childVariant == LayerHierarchy::Variant::Detached || - childVariant == LayerHierarchy::Variant::Attached) { - detachHierarchyFromRelativeParent(child); - } +} + +void LayerHierarchyBuilder::detachHierarchyFromRelativeParent(LayerHierarchy* root) { + std::vector<LayerHierarchy*> hierarchiesToDetach = getDescendants(root); + for (LayerHierarchy* hierarchy : hierarchiesToDetach) { + detachFromRelativeParent(hierarchy); } } diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h index 69710be8df..d023f9e9f5 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h @@ -218,6 +218,7 @@ private: void detachFromParent(LayerHierarchy*); void attachToRelativeParent(LayerHierarchy*); void detachFromRelativeParent(LayerHierarchy*); + std::vector<LayerHierarchy*> getDescendants(LayerHierarchy*); void attachHierarchyToRelativeParent(LayerHierarchy*); void detachHierarchyFromRelativeParent(LayerHierarchy*); void init(const std::vector<std::unique_ptr<RequestedLayerState>>&); diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp index 4b0618e5aa..dd5e8bd007 100644 --- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp +++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp @@ -152,6 +152,10 @@ void LayerLifecycleManager::onHandlesDestroyed( if (swapErase(linkedLayer->mirrorIds, layer.id)) { linkedLayer->changes |= RequestedLayerState::Changes::Mirror; } + if (linkedLayer->layerIdToMirror == layer.id) { + linkedLayer->layerIdToMirror = UNASSIGNED_LAYER_ID; + linkedLayer->changes |= RequestedLayerState::Changes::Mirror; + } if (linkedLayer->touchCropId == layer.id) { linkedLayer->touchCropId = UNASSIGNED_LAYER_ID; } diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 2b4e234604..59eb7f5d4a 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -315,39 +315,15 @@ void RegionSamplingThread::captureSample() { return true; }; - std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()> getLayerSnapshots; - if (mFlinger.mLayerLifecycleManagerEnabled) { - auto filterFn = [&](const frontend::LayerSnapshot& snapshot, - bool& outStopTraversal) -> bool { - const Rect bounds = - frontend::RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds), - snapshot.transparentRegionHint); - const ui::Transform transform = snapshot.geomLayerTransform; - return layerFilterFn(snapshot.name.c_str(), snapshot.path.id, bounds, transform, - outStopTraversal); - }; - getLayerSnapshots = - mFlinger.getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID, - filterFn); - } else { - auto traverseLayers = [&](const LayerVector::Visitor& visitor) { - bool stopLayerFound = false; - auto filterVisitor = [&](Layer* layer) { - // We don't want to capture any layers beyond the stop layer - if (stopLayerFound) return; - - if (!layerFilterFn(layer->getDebugName(), layer->getSequence(), - Rect(layer->getBounds()), layer->getTransform(), - stopLayerFound)) { - return; - } - visitor(layer); - }; - mFlinger.traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, {}, - filterVisitor); - }; - getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); - } + auto filterFn = [&](const frontend::LayerSnapshot& snapshot, bool& outStopTraversal) -> bool { + const Rect bounds = frontend::RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds), + snapshot.transparentRegionHint); + const ui::Transform transform = snapshot.geomLayerTransform; + return layerFilterFn(snapshot.name.c_str(), snapshot.path.id, bounds, transform, + outStopTraversal); + }; + auto getLayerSnapshotsFn = + mFlinger.getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID, filterFn); std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr; if (mCachedBuffer && mCachedBuffer->getBuffer()->getWidth() == sampledBounds.getWidth() && @@ -379,7 +355,7 @@ void RegionSamplingThread::captureSample() { ui::Dataspace::V0_SRGB, kHintForSeamlessTransition, true /* captureSecureLayers */, displayWeak), - getLayerSnapshots, buffer, kRegionSampling, kGrayscale, + getLayerSnapshotsFn, buffer, kRegionSampling, kGrayscale, kIsProtected, nullptr) .get(); fenceResult.ok()) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index be0c1548d7..97469c0886 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -7863,14 +7863,13 @@ status_t SurfaceFlinger::setSchedAttr(bool enabled) { namespace { -ui::Dataspace pickBestDataspace(ui::Dataspace requestedDataspace, const DisplayDevice* display, +ui::Dataspace pickBestDataspace(ui::Dataspace requestedDataspace, + const compositionengine::impl::OutputCompositionState& state, bool capturingHdrLayers, bool hintForSeamlessTransition) { - if (requestedDataspace != ui::Dataspace::UNKNOWN || display == nullptr) { + if (requestedDataspace != ui::Dataspace::UNKNOWN) { return requestedDataspace; } - const auto& state = display->getCompositionDisplay()->getState(); - const auto dataspaceForColorMode = ui::pickDataspaceFor(state.colorMode); // TODO: Enable once HDR screenshots are ready. @@ -7950,23 +7949,14 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, } } - GetLayerSnapshotsFunction getLayerSnapshots; - if (mLayerLifecycleManagerEnabled) { - getLayerSnapshots = - getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds)); - } else { - auto traverseLayers = [this, args, excludeLayerIds, - layerStack](const LayerVector::Visitor& visitor) { - traverseLayersInLayerStack(layerStack, args.uid, std::move(excludeLayerIds), visitor); - }; - getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); - } + GetLayerSnapshotsFunction getLayerSnapshotsFn = + getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds)); captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>, args.sourceCrop, reqSize, args.dataspace, args.hintForSeamlessTransition, args.captureSecureLayers, displayWeak), - getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected, + getLayerSnapshotsFn, reqSize, args.pixelFormat, args.allowProtected, args.grayscale, captureListener); } @@ -8003,16 +7993,9 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args return; } - GetLayerSnapshotsFunction getLayerSnapshots; - if (mLayerLifecycleManagerEnabled) { - getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID, - /*snapshotFilterFn=*/nullptr); - } else { - auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) { - traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, {}, visitor); - }; - getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); - } + GetLayerSnapshotsFunction getLayerSnapshotsFn = + getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID, + /*snapshotFilterFn=*/nullptr); if (captureListener == nullptr) { ALOGE("capture screen must provide a capture listener callback"); @@ -8027,7 +8010,7 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args Rect(), size, args.dataspace, args.hintForSeamlessTransition, false /* captureSecureLayers */, displayWeak), - getLayerSnapshots, size, args.pixelFormat, kAllowProtected, kGrayscale, + getLayerSnapshotsFn, size, args.pixelFormat, kAllowProtected, kGrayscale, captureListener); } @@ -8109,42 +8092,16 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, return; } - GetLayerSnapshotsFunction getLayerSnapshots; - if (mLayerLifecycleManagerEnabled) { - std::optional<FloatRect> parentCrop = std::nullopt; - if (args.childrenOnly) { - parentCrop = crop.isEmpty() ? FloatRect(0, 0, reqSize.width, reqSize.height) - : crop.toFloatRect(); - } - - getLayerSnapshots = getLayerSnapshotsForScreenshots(parent->sequence, args.uid, - std::move(excludeLayerIds), - args.childrenOnly, parentCrop); - } else { - auto traverseLayers = [parent, args, excludeLayerIds](const LayerVector::Visitor& visitor) { - parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - if (!layer->isVisible()) { - return; - } else if (args.childrenOnly && layer == parent.get()) { - return; - } else if (args.uid != CaptureArgs::UNSET_UID && args.uid != layer->getOwnerUid()) { - return; - } - - auto p = sp<Layer>::fromExisting(layer); - while (p != nullptr) { - if (excludeLayerIds.count(p->sequence) != 0) { - return; - } - p = p->getParent(); - } - - visitor(layer); - }); - }; - getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); + std::optional<FloatRect> parentCrop = std::nullopt; + if (args.childrenOnly) { + parentCrop = crop.isEmpty() ? FloatRect(0, 0, reqSize.width, reqSize.height) + : crop.toFloatRect(); } + GetLayerSnapshotsFunction getLayerSnapshotsFn = + getLayerSnapshotsForScreenshots(parent->sequence, args.uid, std::move(excludeLayerIds), + args.childrenOnly, parentCrop); + if (captureListener == nullptr) { ALOGD("capture screen must provide a capture listener callback"); invokeScreenCaptureError(BAD_VALUE, captureListener); @@ -8155,7 +8112,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, reqSize, dataspace, args.captureSecureLayers, args.hintForSeamlessTransition, parent, args.childrenOnly), - getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected, + getLayerSnapshotsFn, reqSize, args.pixelFormat, args.allowProtected, args.grayscale, captureListener); } @@ -8184,7 +8141,7 @@ bool SurfaceFlinger::layersHasProtectedLayer( } void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuilder, - GetLayerSnapshotsFunction getLayerSnapshots, + GetLayerSnapshotsFunction getLayerSnapshotsFn, ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, const sp<IScreenCaptureListener>& captureListener) { @@ -8205,7 +8162,7 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuil const bool supportsProtected = getRenderEngine().supportsProtectedContent(); bool hasProtectedLayer = false; if (allowProtected && supportsProtected) { - auto layers = mScheduler->schedule([=]() { return getLayerSnapshots(); }).get(); + auto layers = mScheduler->schedule([=]() { return getLayerSnapshotsFn(); }).get(); hasProtectedLayer = layersHasProtectedLayer(layers); } const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected; @@ -8232,41 +8189,71 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuil renderengine::impl::ExternalTexture::Usage:: WRITEABLE); auto futureFence = - captureScreenshot(renderAreaBuilder, getLayerSnapshots, texture, + captureScreenshot(renderAreaBuilder, getLayerSnapshotsFn, texture, false /* regionSampling */, grayscale, isProtected, captureListener); futureFence.get(); } -ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot( - RenderAreaBuilderVariant renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshots, - const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, - bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener) { - ATRACE_CALL(); - - auto takeScreenshotFn = [=, this, renderAreaBuilder = std::move(renderAreaBuilder)]() REQUIRES( - kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> { - // LayerSnapshots must be obtained from the main thread. - auto layers = getLayerSnapshots(); - +const sp<const DisplayDevice> SurfaceFlinger::getRenderAreaDisplay( + RenderAreaBuilderVariant& renderAreaBuilder, OutputCompositionState& state) { + sp<const DisplayDevice> display = nullptr; + { + Mutex::Autolock lock(mStateLock); if (auto* layerRenderAreaBuilder = std::get_if<LayerRenderAreaBuilder>(&renderAreaBuilder)) { // LayerSnapshotBuilder should only be accessed from the main thread. - frontend::LayerSnapshot* snapshot = + const frontend::LayerSnapshot* snapshot = mLayerSnapshotBuilder.getSnapshot(layerRenderAreaBuilder->layer->getSequence()); if (!snapshot) { ALOGW("Couldn't find layer snapshot for %d", layerRenderAreaBuilder->layer->getSequence()); } else { layerRenderAreaBuilder->setLayerSnapshot(*snapshot); + display = findDisplay( + [layerStack = snapshot->outputFilter.layerStack](const auto& display) { + return display.getLayerStack() == layerStack; + }); } + } else if (auto* displayRenderAreaBuilder = + std::get_if<DisplayRenderAreaBuilder>(&renderAreaBuilder)) { + display = displayRenderAreaBuilder->displayWeak.promote(); } - if (FlagManager::getInstance().ce_fence_promise()) { - for (auto& [layer, layerFE] : layers) { - attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK); - } + if (display == nullptr) { + display = getDefaultDisplayDeviceLocked(); } + if (display != nullptr) { + state = display->getCompositionDisplay()->getState(); + } + } + return display; +} + +std::vector<std::pair<Layer*, sp<android::LayerFE>>> +SurfaceFlinger::getLayerSnapshotsFromMainThread(GetLayerSnapshotsFunction getLayerSnapshotsFn) { + auto layers = getLayerSnapshotsFn(); + if (FlagManager::getInstance().ce_fence_promise()) { + for (auto& [layer, layerFE] : layers) { + attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK); + } + } + return layers; +} + +ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot( + RenderAreaBuilderVariant renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn, + const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, + bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener) { + ATRACE_CALL(); + + auto takeScreenshotFn = [=, this, renderAreaBuilder = std::move(renderAreaBuilder)]() REQUIRES( + kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> { + auto layers = getLayerSnapshotsFromMainThread(getLayerSnapshotsFn); + + OutputCompositionState state; + const auto display = getRenderAreaDisplay(renderAreaBuilder, state); + ScreenCaptureResults captureResults; std::unique_ptr<const RenderArea> renderArea = std::visit([](auto&& arg) -> std::unique_ptr<RenderArea> { return arg.build(); }, @@ -8283,7 +8270,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot( ftl::SharedFuture<FenceResult> renderFuture = renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale, - isProtected, captureResults, layers); + isProtected, captureResults, display, state, layers); if (captureListener) { // Defer blocking on renderFuture back to the Binder thread. @@ -8313,18 +8300,10 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot( } ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( - std::unique_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots, - const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, - bool grayscale, bool isProtected, ScreenCaptureResults& captureResults) { - auto layers = getLayerSnapshots(); - return renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale, isProtected, - captureResults, layers); -} - -ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( std::unique_ptr<const RenderArea> renderArea, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults& captureResults, + const sp<const DisplayDevice> display, const OutputCompositionState& state, std::vector<std::pair<Layer*, sp<android::LayerFE>>>& layers) { ATRACE_CALL(); @@ -8351,60 +8330,35 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( const bool enableLocalTonemapping = FlagManager::getInstance().local_tonemap_screenshots() && !renderArea->getHintForSeamlessTransition(); - { - Mutex::Autolock lock(mStateLock); - const DisplayDevice* display = nullptr; - if (parent) { - const frontend::LayerSnapshot* snapshot = - mLayerSnapshotBuilder.getSnapshot(parent->sequence); - if (snapshot) { - display = findDisplay([layerStack = snapshot->outputFilter.layerStack]( - const auto& display) { - return display.getLayerStack() == layerStack; - }).get(); - } - } + if (display != nullptr) { + captureResults.capturedDataspace = + pickBestDataspace(requestedDataspace, state, captureResults.capturedHdrLayers, + renderArea->getHintForSeamlessTransition()); + sdrWhitePointNits = state.sdrWhitePointNits; - if (display == nullptr) { - display = renderArea->getDisplayDevice().get(); - } - - if (display == nullptr) { - display = getDefaultDisplayDeviceLocked().get(); - } - - if (display != nullptr) { - const auto& state = display->getCompositionDisplay()->getState(); - captureResults.capturedDataspace = - pickBestDataspace(requestedDataspace, display, captureResults.capturedHdrLayers, - renderArea->getHintForSeamlessTransition()); - sdrWhitePointNits = state.sdrWhitePointNits; - - if (!captureResults.capturedHdrLayers) { - displayBrightnessNits = sdrWhitePointNits; - } else { - displayBrightnessNits = state.displayBrightnessNits; - - if (!enableLocalTonemapping) { - // Only clamp the display brightness if this is not a seamless transition. - // Otherwise for seamless transitions it's important to match the current - // display state as the buffer will be shown under these same conditions, and we - // want to avoid any flickers - if (sdrWhitePointNits > 1.0f && !renderArea->getHintForSeamlessTransition()) { - // Restrict the amount of HDR "headroom" in the screenshot to avoid - // over-dimming the SDR portion. 2.0 chosen by experimentation - constexpr float kMaxScreenshotHeadroom = 2.0f; - displayBrightnessNits = std::min(sdrWhitePointNits * kMaxScreenshotHeadroom, - displayBrightnessNits); - } + if (!captureResults.capturedHdrLayers) { + displayBrightnessNits = sdrWhitePointNits; + } else { + displayBrightnessNits = state.displayBrightnessNits; + if (!enableLocalTonemapping) { + // Only clamp the display brightness if this is not a seamless transition. + // Otherwise for seamless transitions it's important to match the current + // display state as the buffer will be shown under these same conditions, and we + // want to avoid any flickers + if (sdrWhitePointNits > 1.0f && !renderArea->getHintForSeamlessTransition()) { + // Restrict the amount of HDR "headroom" in the screenshot to avoid + // over-dimming the SDR portion. 2.0 chosen by experimentation + constexpr float kMaxScreenshotHeadroom = 2.0f; + displayBrightnessNits = std::min(sdrWhitePointNits * kMaxScreenshotHeadroom, + displayBrightnessNits); } } + } - // Screenshots leaving the device should be colorimetric - if (requestedDataspace == ui::Dataspace::UNKNOWN && - renderArea->getHintForSeamlessTransition()) { - renderIntent = state.renderIntent; - } + // Screenshots leaving the device should be colorimetric + if (requestedDataspace == ui::Dataspace::UNKNOWN && + renderArea->getHintForSeamlessTransition()) { + renderIntent = state.renderIntent; } } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8a390162d9..209d9bcfe6 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -898,25 +898,26 @@ private: ui::Size bufferSize, ui::PixelFormat, bool allowProtected, bool grayscale, const sp<IScreenCaptureListener>&); + using OutputCompositionState = compositionengine::impl::OutputCompositionState; + + const sp<const DisplayDevice> getRenderAreaDisplay(RenderAreaBuilderVariant& renderAreaBuilder, + OutputCompositionState& state) + REQUIRES(kMainThreadContext); + + std::vector<std::pair<Layer*, sp<android::LayerFE>>> getLayerSnapshotsFromMainThread( + GetLayerSnapshotsFunction getLayerSnapshotsFn) REQUIRES(kMainThreadContext); + ftl::SharedFuture<FenceResult> captureScreenshot( RenderAreaBuilderVariant, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, bool grayscale, bool isProtected, const sp<IScreenCaptureListener>&); - // Overloaded version of renderScreenImpl that is used when layer snapshots have - // not yet been captured, and thus cannot yet be passed in as a parameter. - // Needed for TestableSurfaceFlinger. - ftl::SharedFuture<FenceResult> renderScreenImpl( - std::unique_ptr<const RenderArea>, GetLayerSnapshotsFunction, - const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, - bool grayscale, bool isProtected, ScreenCaptureResults&) EXCLUDES(mStateLock) - REQUIRES(kMainThreadContext); - ftl::SharedFuture<FenceResult> renderScreenImpl( std::unique_ptr<const RenderArea>, const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults&, - std::vector<std::pair<Layer*, sp<android::LayerFE>>>& layers) EXCLUDES(mStateLock) + const sp<const DisplayDevice> display, const OutputCompositionState& state, + std::vector<std::pair<Layer*, sp<android::LayerFE>>>& layers) REQUIRES(kMainThreadContext); // If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 0ddddbd7f3..08973de195 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -205,7 +205,8 @@ void CompositionTest::captureScreenComposition() { CaptureArgs::UNSET_UID, {}, visitor); }; - auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); + // TODO: Use SurfaceFlinger::getLayerSnapshotsForScreenshots instead of this legacy function + auto getLayerSnapshotsFn = RenderArea::fromTraverseLayersLambda(traverseLayers); const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; @@ -215,7 +216,7 @@ void CompositionTest::captureScreenComposition() { HAL_PIXEL_FORMAT_RGBA_8888, 1, usage); - auto future = mFlinger.renderScreenImpl(std::move(renderArea), getLayerSnapshots, + auto future = mFlinger.renderScreenImpl(mDisplay, std::move(renderArea), getLayerSnapshotsFn, mCaptureScreenBuffer, regionSampling); ASSERT_TRUE(future.valid()); const auto fenceResult = future.get(); diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp index 2b333f4b87..b79bdb4231 100644 --- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp @@ -777,4 +777,28 @@ TEST_F(LayerHierarchyTest, canMirrorDisplayWithMirrors) { EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expected); } +// (b/343901186) +TEST_F(LayerHierarchyTest, cleanUpDanglingMirrorLayer) { + LayerHierarchyBuilder hierarchyBuilder; + hierarchyBuilder.update(mLifecycleManager); + mirrorLayer(/*layer*/ 14, /*parent*/ 1, /*layerToMirror*/ 2); + UPDATE_AND_VERIFY(hierarchyBuilder); + + std::vector<uint32_t> expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 14, 2, 2}; + EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath); + EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath); + expectedTraversalPath = {}; + EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath); + + // destroy layer handle + reparentLayer(2, UNASSIGNED_LAYER_ID); + destroyLayerHandle(2); + UPDATE_AND_VERIFY(hierarchyBuilder); + expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 14}; + EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath); + EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath); + expectedTraversalPath = {}; + EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath); +} + } // namespace android::surfaceflinger::frontend diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 265f804fc8..7889096fe2 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -485,23 +485,27 @@ public: return mFlinger->setPowerModeInternal(display, mode); } - auto renderScreenImpl(std::unique_ptr<const RenderArea> renderArea, - SurfaceFlinger::GetLayerSnapshotsFunction traverseLayers, + auto renderScreenImpl(const sp<DisplayDevice> display, + std::unique_ptr<const RenderArea> renderArea, + SurfaceFlinger::GetLayerSnapshotsFunction getLayerSnapshotsFn, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling) { + Mutex::Autolock lock(mFlinger->mStateLock); + ftl::FakeGuard guard(kMainThreadContext); + ScreenCaptureResults captureResults; - return FTL_FAKE_GUARD(kMainThreadContext, - mFlinger->renderScreenImpl(std::move(renderArea), traverseLayers, - buffer, regionSampling, - false /* grayscale */, - false /* isProtected */, captureResults)); + SurfaceFlinger::OutputCompositionState state = display->getCompositionDisplay()->getState(); + auto layers = mFlinger->getLayerSnapshotsFromMainThread(getLayerSnapshotsFn); + + return mFlinger->renderScreenImpl(std::move(renderArea), buffer, regionSampling, + false /* grayscale */, false /* isProtected */, + captureResults, display, state, layers); } auto traverseLayersInLayerStack(ui::LayerStack layerStack, int32_t uid, std::unordered_set<uint32_t> excludeLayerIds, const LayerVector::Visitor& visitor) { - return mFlinger->SurfaceFlinger::traverseLayersInLayerStack(layerStack, uid, - excludeLayerIds, visitor); + return mFlinger->traverseLayersInLayerStack(layerStack, uid, excludeLayerIds, visitor); } auto getDisplayNativePrimaries(const sp<IBinder>& displayToken, |